@end table
@vindex eshell-virtual-targets
-You can, of course, define your own virtual targets. They are defined
-by adding a list of the form @samp{("/dev/name" @var{function}
-@var{mode})} to @code{eshell-virtual-targets}. The first element is
-the device name; @var{function} may be either a lambda or a function
-name. If @var{mode} is @code{nil}, then the function is the output
-function; if it is non-@code{nil}, then the function is passed the
-redirection mode as a symbol--@code{overwrite} for @code{>},
-@code{append} for @code{>>}, or @code{insert} for @code{>>>}--and the
-function is expected to return the output function.
-
-The output function is called once on each line of output until
-@code{nil} is passed, indicating end of output.
+@vindex eshell-generic-target
+@findex eshell-output-object-to-target
+@findex eshell-close-target
+You can, of course, define your own virtual targets. These are entries
+in @code{eshell-virtual-targets} with the form @samp{(@var{filename}
+@var{output-function} @var{pass-mode})}. The first element,
+@var{filename}, is the device name, usually of the form
+@samp{"/dev/@var{name}"}. The second, @var{output-function}, should be a
+function: Eshell will repeatedly call it with the redirected output.
+This argument can also be an @code{eshell-generic-target} instance. In
+this case, Eshell will repeatedly call the generic function
+@code{eshell-output-object-to-target} with the output; once the
+redirection has completed, Eshell will then call the generic function
+@code{eshell-close-target}, passing non-@code{nil} if the redirected
+command succeeded.
+
+If @var{pass-mode} is non-@code{nil}, then Eshell will pass the
+redirection mode as an argument to @code{output-function} as a
+symbol: @code{overwrite} for @code{>}, @code{append} for @code{>>}, or
+@code{insert} for @code{>>>}. In this case, @code{output-function}
+should return the real output function (either an ordinary function or
+an @code{eshell-generic-target} as described above).
+
+@defun eshell-function-target-create output-function &optional close-function
+Create a new virtual target for Eshell that repeatedly calls
+@var{output-function} with the redirected output, as described above.
+If @var{close-function} is non-nil, Eshell will call it when closing the
+target, passing non-@code{nil} if the redirected command succeeded.
+@end defun
@node Pipelines
@section Pipelines
#'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.
-
-If the third element is non-nil, the redirection mode is passed as an
-argument (which is the symbol `overwrite', `append' or `insert'), and
-the function is expected to return another function -- which is the
-output function. Otherwise, the second element itself is the output
-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."
+Each member is of the following form:
+
+ (FILENAME OUTPUT-FUNCTION [PASS-MODE])
+
+When the user specifies FILENAME as a redirection target, Eshell will
+repeatedly call the OUTPUT-FUNCTION with the redirected output as
+strings. OUTPUT-FUNCTION can also be an `eshell-generic-target'
+instance. In this case, Eshell will repeatedly call the function in the
+`output-function' slot with the string output; once the redirection has
+completed, Eshell will then call the function in the `close-function'
+slot, passing the exit status of the redirected command.
+
+If PASS-MODE is non-nil, Eshell will pass the redirection mode as an
+argument (which is the symbol `overwrite', `append' or `insert') to
+OUTPUT-FUNCTION, which should return the real output function (either an
+ordinary function or `eshell-generic-target' as desribed above)."
:version "30.1"
:type '(repeat
(list (string :tag "Target")
(eshell-print object)
(eshell-print "\n"))
-(cl-defstruct (eshell-virtual-target
+(cl-defstruct (eshell-generic-target (:constructor nil))
+ "An Eshell target.
+This is mainly useful for creating virtual targets (see
+`eshell-virtual-targets').")
+
+(cl-defstruct (eshell-function-target
+ (:include eshell-generic-target)
(:constructor nil)
- (:constructor eshell-virtual-target-create (output-function)))
- "A virtual target (see `eshell-virtual-targets')."
- output-function)
+ (:constructor eshell-function-target-create
+ (output-function &optional close-function)))
+ "An Eshell target that calls an OUTPUT-FUNCTION."
+ output-function close-function)
(cl-defgeneric eshell-get-target (raw-target &optional _mode)
"Convert RAW-TARGET, which is a raw argument, into a valid output target.
(cl-defmethod eshell-get-target ((raw-target string) &optional mode)
"Convert a string RAW-TARGET into a valid output target using MODE.
If TARGET is a virtual target (see `eshell-virtual-targets'),
-return an `eshell-virtual-target' instance; otherwise, return a
+return an `eshell-generic-target' instance; otherwise, return a
marker for a file named TARGET."
(setq mode (or mode 'insert))
(if-let ((redir (assoc raw-target eshell-virtual-targets)))
- (eshell-virtual-target-create
- (if (nth 2 redir)
- (funcall (nth 1 redir) mode)
- (nth 1 redir)))
+ (let ((target (if (nth 2 redir)
+ (funcall (nth 1 redir) mode)
+ (nth 1 redir))))
+ (unless (eshell-generic-target-p target)
+ (setq target (eshell-function-target-create target)))
+ target)
(let ((exists (get-file-buffer raw-target))
(buf (find-file-noselect raw-target t)))
(with-current-buffer buf
(throw 'done nil))
(process-send-eof target))))
-(cl-defmethod eshell-close-target ((_target eshell-virtual-target) _status)
- "Close a virtual TARGET."
- nil)
+(cl-defmethod eshell-close-target ((target eshell-function-target) status)
+ "Close an Eshell function TARGET."
+ (when-let ((close-function (eshell-function-target-close-function target)))
+ (funcall close-function status)))
(cl-defgeneric eshell-output-object-to-target (object target)
"Output OBJECT to TARGET.
object)
(cl-defmethod eshell-output-object-to-target (object
- (target eshell-virtual-target))
- "Output OBJECT to the virtual TARGET."
- (funcall (eshell-virtual-target-output-function target) object))
+ (target eshell-function-target))
+ "Output OBJECT to the Eshell function TARGET."
+ (funcall (eshell-function-target-output-function target) object))
(defun eshell-output-object (object &optional handle-index handles)
"Insert OBJECT, using HANDLE-INDEX specifically.