emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 99b360bb5aa: Allow specifying stdout/stderr separately in some Es


From: Jim Porter
Subject: master 99b360bb5aa: Allow specifying stdout/stderr separately in some Eshell commands
Date: Thu, 18 Jul 2024 19:13:57 -0400 (EDT)

branch: master
commit 99b360bb5aabf324cf038c27ac76ac1513319754
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>

    Allow specifying stdout/stderr separately in some Eshell commands
    
    * lisp/eshell/eshell.el (eshell-command): Add ERROR-TARGET.
    * lisp/eshell/em-script.el (eshell-execute-file): Make interactive, and
    add ERROR-TARGET.
    
    * doc/misc/eshell.texi (One-Off Commands, Scripts): Update
    documentation.
    
    * etc/NEWS: Announce this change.
---
 doc/misc/eshell.texi     | 35 +++++++++++++++++++++++++----------
 etc/NEWS                 | 12 ++++++++++++
 lisp/eshell/em-script.el | 21 +++++++++++++++------
 lisp/eshell/eshell.el    | 33 ++++++++++++++++++++++-----------
 4 files changed, 74 insertions(+), 27 deletions(-)

diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index d4e182bcbb2..8a4f460d03c 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -235,11 +235,19 @@ Start a new Eshell session, no matter if another one 
already exists.
 
 You can also run individual Eshell commands from anywhere within Emacs:
 
-@deffn Command eshell-command command &optional to-current-buffer
+@deffn Command eshell-command command &optional output-target error-target
 Execute the Eshell command string @var{command} and show the output in a
-buffer.  If @var{to-current-buffer} is non-@code{nil} (interactively,
-with the prefix argument), then insert output into the current buffer at
-point.
+buffer.  If @var{output-target} is @code{t} (interactively, with the
+prefix argument), write the command's standard output to the current
+buffer at point.  If @code{nil}, write the output to a new output
+buffer.  For any other value, output to that Eshell target
+(@pxref{Redirection}).
+
+@var{error-target} is similar to @var{output-target}, except that it
+controls where to write standard error, and a @code{nil} value means to
+write standard error to the same place as standard output.  (To suppress
+standard error, you can write to the Eshell virtual target
+@file{/dev/null}.)
 
 When the command ends with @kbd{&}, Eshell will evaluate the command
 asynchronously.  Otherwise, it will wait until the command has finished
@@ -275,13 +283,20 @@ the special variables @code{$0}, @code{$1}, @dots{}, 
@code{$9}, and
 
 You can also invoke Eshell scripts from outside of Eshell:
 
-@defun eshell-execute-file file &optional args destination
+@deffn Command eshell-execute-file file &optional args output-target 
error-target
 Execute the Eshell commands contained in @var{file}, passing an optional
-list of @var{args} to the script.  If @var{destination} is @code{t},
-write the command output to the current buffer.  If @code{nil}, don't
-write the output anywhere.  For any other value, output to the
-corresponding Eshell target (@pxref{Redirection}).
-@end defun
+list of @var{args} to the script.  If @var{output-target} is @code{t}
+(interactively, with the prefix argument), write the command output to
+the current buffer.  If @code{nil}, don't write the output anywhere.
+For any other value, output to the corresponding Eshell target
+(@pxref{Redirection}).
+
+@var{error-target} is similar to @var{output-target}, except that it
+controls where to write standard error, and a @code{nil} value means to
+write standard error to the same place as standard output.  (To suppress
+standard error, you can write to the Eshell virtual target
+@file{/dev/null\}.)
+@end deffn
 
 @cindex batch scripts
 @defun eshell-batch-file
diff --git a/etc/NEWS b/etc/NEWS
index 60bde2abb40..5429db1dded 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -60,6 +60,18 @@ this will prompt for confirmation before creating a new 
buffer when
 necessary.  To restore the previous behavior, set this option to
 'confirm-kill-process'.
 
++++
+*** 'eshell-execute-file' is now an interactive command.
+Interactively, this now prompts for a script file to execute. With the
+prefix argument, it will also insert any output into the current buffer
+at point.
+
++++
+*** 'eshell-command' and 'eshell-execute-file' can now set where stderr goes.
+These functions now take an optional ERROR-TARGET argument to control
+where to send the standard error output.  See the "(eshell) Entry
+Points" node in the Eshell manual for more details.
+
 +++
 *** Eshell's built-in "wait" command now accepts a timeout.
 By passing "-t" or "--timeout", you can specify a maximum time to wait
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index ba020d2eb5b..80dea16106b 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -106,20 +106,29 @@ Comments begin with `#'."
          (eshell--source-file file args subcommand-p)))
 
 ;;;###autoload
-(defun eshell-execute-file (file &optional args destination)
+(defun eshell-execute-file (file &optional args output-target error-target)
   "Execute a series of Eshell commands in FILE, passing ARGS.
-If DESTINATION is t, write the command output to the current buffer.  If
-nil, don't write the output anywhere.  For any other value, output to
-the corresponding Eshell target (see `eshell-get-target').
+If OUTPUT-TARGET is t (interactively, with the prefix argument), write
+the command's standard output to the current buffer at point.  If nil,
+don't write the output anywhere.  For any other value, output to that
+Eshell target (see `eshell-get-target').
+
+ERROR-TARGET is similar to OUTPUT-TARGET, except that it controls where
+to write standard error, and a nil value means to write standard error
+to the same place as standard output.  (To suppress standard error, you
+can write to the Eshell virtual target \"/dev/null\".)
 
 Comments begin with `#'."
+  (interactive (list (read-file-name "Execute file: " nil nil t)
+                     nil (not (not current-prefix-arg))))
   (let ((eshell-non-interactive-p t)
-        (stdout (if (eq destination t) (current-buffer) destination)))
+        (stdout (if (eq output-target t) (current-buffer) output-target))
+        (stderr (if (eq error-target t) (current-buffer) error-target)))
     (with-temp-buffer
       (eshell-mode)
       (eshell-do-eval
        `(let ((eshell-current-handles
-               (eshell-create-handles ,stdout 'insert))
+               (eshell-create-handles ,stdout 'insert ,stderr 'insert))
               (eshell-current-subjob-p))
           ,(eshell--source-file file args))
        t))))
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index d60101d51e1..6637ff36a2c 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -327,31 +327,42 @@ information on Eshell, see Info node `(eshell)Top'."
 (defvar eshell-command-buffer-name-sync "*Eshell Command Output*")
 
 ;;;###autoload
-(defun eshell-command (command &optional to-current-buffer)
+(defun eshell-command (command &optional output-target error-target)
   "Execute the Eshell command string COMMAND.
-If TO-CURRENT-BUFFER is non-nil (interactively, with the prefix
-argument), then insert output into the current buffer at point.
-
-When \"&\" is added at end of command, the command is async and its output
-appears in a specific buffer.  You can customize
+If OUTPUT-TARGET is t (interactively, with the prefix argument), write
+the command's standard output to the current buffer at point.  If nil,
+write the output to a new output buffer.  For any other value, output to
+that Eshell target (see `eshell-get-target').
+
+ERROR-TARGET is similar to OUTPUT-TARGET, except that it controls where
+to write standard error, and a nil value means to write standard error
+to the same place as standard output.  (To suppress standard error, you
+can write to the Eshell virtual target \"/dev/null\".)
+
+When \"&\" is added at end of command, the command is async and its
+output appears in a specific buffer.  You can customize
 `eshell-command-async-buffer' to specify what to do when this output
 buffer is already taken by another running shell command."
   (interactive (list (eshell-read-command)
-                     current-prefix-arg))
+                     (not (not current-prefix-arg))))
   (save-excursion
-    (let ((stdout (if to-current-buffer (current-buffer) t))
+    (let ((stdout (cond ((eq output-target t) (current-buffer))
+                        ((not output-target) t)
+                        (t output-target)))
+          (stderr (if (eq error-target t) (current-buffer) error-target))
           (buf (set-buffer (generate-new-buffer " *eshell cmd*")))
          (eshell-non-interactive-p t))
       (eshell-mode)
       (let* ((proc (eshell-eval-command
                     `(let ((eshell-current-handles
-                            (eshell-create-handles ,stdout 'insert))
+                            (eshell-create-handles ,stdout 'insert
+                                                   ,stderr 'insert))
                            (eshell-current-subjob-p))
                       ,(eshell-parse-command command))
                     command))
              (async (eq (car-safe proc) :eshell-background))
              (bufname (cond
-                       (to-current-buffer nil)
+                       ((not (eq stdout t)) nil)
                        (async eshell-command-buffer-name-async)
                        (t eshell-command-buffer-name-sync)))
              unique)
@@ -394,7 +405,7 @@ buffer is already taken by another running shell command."
          (while (and (bolp) (not (bobp)))
            (delete-char -1)))
        (cl-assert (and buf (buffer-live-p buf)))
-       (unless to-current-buffer
+        (unless bufname
           (let ((len (if async 2
                       (count-lines (point-min) (point-max)))))
            (cond



reply via email to

[Prev in Thread] Current Thread [Next in Thread]