You can copy the following Elisp code to your init files.
It contains a modified version of function
Essentially I changed
(insert-file-contents file) to
Furthermore I needed a minor modification of
It also contains the function
define-eshell-script defining an Eshell command with a doc string and an Eshell script given by a string. The script takes care of the formalities for the script required by Eshell internals (e.g., correctly registering in the list variable
eshell-complex-commands). Those formalities make the newly defined command interruptible.
(require 'cl-lib) ;; for macro `cl-pushnew' (not autoloaded ?!)
(require 'esh-cmd) ;; for variable `eshell-complex-commands'
(defun eshell-source-string (string &optional args subcommand-p)
"Execute a series of Eshell commands in STRING, passing ARGS.
Comments begin with `#'."
(interactive "sString to be evaluated as eshell script: ")
(let ((orig (point))
;; FIXME: Why not use a temporary buffer and avoid this
;; "insert&delete" business? --Stef
(list (list 'eshell-command-name (list 'quote "source-string"))
(list 'quote args)))
(let ((cmd (eshell-parse-command (cons here (point)))))
(setq cmd (list 'eshell-as-subcommand cmd)))
(delete-region here (point))
(defun define-eshell-script (cmd doc string)
"Define CMD as eshell script STRING with documentation DOC.
CMD can be a string or a symbol."
(let ((fun (intern (concat "eshell/" cmd))))
`(lambda (&rest args)
(eshell-source-string ,string args)))
(cl-pushnew cmd (default-value 'eshell-complex-commands) :test #'equal)
(dolist (buffer (buffer-list))
(when (derived-mode-p 'eshell-mode)
(cl-pushnew cmd eshell-complex-commands :test #'equal))))
(put fun 'eshell-no-numeric-conversions t)))
If the above functions are available you can define your actual script with the help of
define-eshell-script as follows.
(define-eshell-script "script" "The doc-string: Output 1, sleep, and output 2."
"bash -c \"echo 1; sleep 3; echo 2;\"
The usage example in Eshell looks like you want it:
/Path/to/current/dir $ script