Simplify handling of /dev/null redirection in Eshell
This also fixes an issue where "echo hi > foo > /dev/null" didn't write to the file "foo". (Note that users can still use their system's null device name when redirecting; Eshell doesn't need to do anything special to support that.) * lisp/eshell/esh-io.el (eshell-virtual-targets): Add "/dev/null". (eshell-set-output-handle): Handle 'eshell-null-device'. * test/lisp/eshell/esh-io-tests.el (esh-io-test/redirect-subcommands/dev-null) (esh-io-test/virtual/dev-null, esh-io-test/virtual/dev-null/multiple): New tests.
This commit is contained in:
parent
6defbd65b6
commit
17bf6a829c
2 changed files with 58 additions and 29 deletions
|
@ -116,16 +116,22 @@ from executing while Emacs is redisplaying."
|
|||
:group 'eshell-io)
|
||||
|
||||
(defcustom eshell-virtual-targets
|
||||
'(("/dev/eshell" eshell-interactive-print nil)
|
||||
'(;; The literal string "/dev/null" is intentional here. It just
|
||||
;; provides compatibility so that users can redirect to
|
||||
;; "/dev/null" no matter the actual value of `null-device'.
|
||||
("/dev/null" (lambda (_mode) (throw 'eshell-null-device t)) t)
|
||||
("/dev/eshell" eshell-interactive-print nil)
|
||||
("/dev/kill" (lambda (mode)
|
||||
(if (eq mode 'overwrite)
|
||||
(kill-new ""))
|
||||
'eshell-kill-append) t)
|
||||
(when (eq mode 'overwrite)
|
||||
(kill-new ""))
|
||||
#'eshell-kill-append)
|
||||
t)
|
||||
("/dev/clip" (lambda (mode)
|
||||
(if (eq mode 'overwrite)
|
||||
(let ((select-enable-clipboard t))
|
||||
(kill-new "")))
|
||||
'eshell-clipboard-append) t))
|
||||
(when (eq mode 'overwrite)
|
||||
(let ((select-enable-clipboard t))
|
||||
(kill-new "")))
|
||||
#'eshell-clipboard-append)
|
||||
t))
|
||||
"Map virtual devices name to Emacs Lisp functions.
|
||||
If the user specifies any of the filenames above as a redirection
|
||||
target, the function in the second element will be called.
|
||||
|
@ -138,10 +144,8 @@ function.
|
|||
|
||||
The output function is then called repeatedly with single strings,
|
||||
which represents successive pieces of the output of the command, until nil
|
||||
is passed, meaning EOF.
|
||||
|
||||
NOTE: /dev/null is handled specially as a virtual target, and should
|
||||
not be added to this variable."
|
||||
is passed, meaning EOF."
|
||||
:version "30.1"
|
||||
:type '(repeat
|
||||
(list (string :tag "Target")
|
||||
function
|
||||
|
@ -357,21 +361,17 @@ the value already set in `eshell-last-command-result'."
|
|||
"Set handle INDEX for the current HANDLES to point to TARGET using MODE.
|
||||
If HANDLES is nil, use `eshell-current-handles'."
|
||||
(when target
|
||||
(let ((handles (or handles eshell-current-handles)))
|
||||
(if (and (stringp target)
|
||||
(string= target (null-device)))
|
||||
(aset handles index nil)
|
||||
(let* ((where (eshell-get-target target mode))
|
||||
(handle (or (aref handles index)
|
||||
(aset handles index (list nil nil 1))))
|
||||
(current (car handle))
|
||||
(defaultp (cadr handle)))
|
||||
(if (not defaultp)
|
||||
(unless (member where current)
|
||||
(setq current (append current (list where))))
|
||||
(setq current (list where)))
|
||||
(setcar handle current)
|
||||
(setcar (cdr handle) nil))))))
|
||||
(let* ((handles (or handles eshell-current-handles))
|
||||
(handle (or (aref handles index)
|
||||
(aset handles index (list nil nil 1))))
|
||||
(defaultp (cadr handle))
|
||||
(current (unless defaultp (car handle))))
|
||||
(catch 'eshell-null-device
|
||||
(let ((where (eshell-get-target target mode)))
|
||||
(unless (member where current)
|
||||
(setq current (append current (list where))))))
|
||||
(setcar handle current)
|
||||
(setcar (cdr handle) nil))))
|
||||
|
||||
(defun eshell-copy-output-handle (index index-to-copy &optional handles)
|
||||
"Copy the handle INDEX-TO-COPY to INDEX for the current HANDLES.
|
||||
|
|
|
@ -166,6 +166,17 @@ ensure only its statement is redirected."
|
|||
(should (equal (buffer-string) "bar")))
|
||||
(should (equal (buffer-string) "foobaz"))))
|
||||
|
||||
(ert-deftest esh-io-test/redirect-subcommands/dev-null ()
|
||||
"Check that redirecting subcommands applies to all subcommands.
|
||||
Include a redirect to /dev/null to ensure it only applies to its
|
||||
statement."
|
||||
(eshell-with-temp-buffer bufname "old"
|
||||
(with-temp-eshell
|
||||
(eshell-insert-command
|
||||
(format "{echo foo; echo bar > /dev/null; echo baz} > #<%s>"
|
||||
bufname)))
|
||||
(should (equal (buffer-string) "foobaz"))))
|
||||
|
||||
(ert-deftest esh-io-test/redirect-subcommands/interpolated ()
|
||||
"Check that redirecting interpolated subcommands applies to all subcommands."
|
||||
(eshell-with-temp-buffer bufname "old"
|
||||
|
@ -302,12 +313,30 @@ stdout originally pointed (the terminal)."
|
|||
|
||||
;; Virtual targets
|
||||
|
||||
(ert-deftest esh-io-test/virtual-dev-eshell ()
|
||||
(ert-deftest esh-io-test/virtual/dev-null ()
|
||||
"Check that redirecting to /dev/null works."
|
||||
(with-temp-eshell
|
||||
(eshell-match-command-output "echo hi > /dev/null" "\\`\\'")))
|
||||
|
||||
(ert-deftest esh-io-test/virtual/dev-null/multiple ()
|
||||
"Check that redirecting to /dev/null works alongside other redirections."
|
||||
(eshell-with-temp-buffer bufname "old"
|
||||
(with-temp-eshell
|
||||
(eshell-match-command-output
|
||||
(format "echo new > /dev/null > #<%s>" bufname) "\\`\\'"))
|
||||
(should (equal (buffer-string) "new")))
|
||||
(eshell-with-temp-buffer bufname "old"
|
||||
(with-temp-eshell
|
||||
(eshell-match-command-output
|
||||
(format "echo new > #<%s> > /dev/null" bufname) "\\`\\'"))
|
||||
(should (equal (buffer-string) "new"))))
|
||||
|
||||
(ert-deftest esh-io-test/virtual/dev-eshell ()
|
||||
"Check that redirecting to /dev/eshell works."
|
||||
(with-temp-eshell
|
||||
(eshell-match-command-output "echo hi > /dev/eshell" "hi")))
|
||||
|
||||
(ert-deftest esh-io-test/virtual-dev-kill ()
|
||||
(ert-deftest esh-io-test/virtual/dev-kill ()
|
||||
"Check that redirecting to /dev/kill works."
|
||||
(with-temp-eshell
|
||||
(eshell-insert-command "echo one > /dev/kill")
|
||||
|
|
Loading…
Add table
Reference in a new issue