aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/eshell
diff options
context:
space:
mode:
authorJim Porter2022-01-20 14:37:54 +0100
committerLars Ingebrigtsen2022-01-20 14:37:54 +0100
commit4450c8bdd93d1b2e7f276e26be2cc37372034c22 (patch)
treee45604026d24ea26a1bb7ec342cc6d72edbce505 /lisp/eshell
parent55c1670bc52c924d80c72e55bf3864023749be29 (diff)
downloademacs-4450c8bdd93d1b2e7f276e26be2cc37372034c22.tar.gz
emacs-4450c8bdd93d1b2e7f276e26be2cc37372034c22.zip
Consider subcommands when deciding to invoke Eshell command directly
When an Eshell command contains an asynchronous subcommand (such as calling an external process), it must be evaluated iteratively. See bug#30725. * lisp/eshell/esh-cmd.el (eshell-invoke-command): Move most of the logic from here... (eshell--invoke-command-directly): ... to here. Also add checks for subcommands. * test/lisp/eshell/eshell-tests.el (eshell-test--max-subprocess-time): New variable. (eshell-wait-for-subprocess): New function. (eshell-command-result-p): Use 'eshell-wait-for-subprocess'. (eshell-test/interp-cmd-external): New test (bug#30725).
Diffstat (limited to 'lisp/eshell')
-rw-r--r--lisp/eshell/esh-cmd.el57
1 files changed, 43 insertions, 14 deletions
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index a2d7d9431a9..25e3a5a2054 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -903,21 +903,50 @@ at the moment are:
903 "Completion for the `debug' command." 903 "Completion for the `debug' command."
904 (while (pcomplete-here '("errors" "commands")))) 904 (while (pcomplete-here '("errors" "commands"))))
905 905
906(defun eshell--invoke-command-directly (command)
907 "Determine whether the given COMMAND can be invoked directly.
908COMMAND should be a non-top-level Eshell command in parsed form.
909
910A command can be invoked directly if all of the following are true:
911
912* The command is of the form
913 \"(eshell-trap-errors (eshell-named-command NAME ARGS))\",
914 where ARGS is optional.
915
916* NAME is a string referring to an alias function and isn't a
917 complex command (see `eshell-complex-commands').
918
919* Any argument in ARGS that calls a subcommand can also be
920 invoked directly."
921 (when (and (eq (car command) 'eshell-trap-errors)
922 (eq (car (cadr command)) 'eshell-named-command))
923 (let ((name (cadr (cadr command)))
924 (args (cdr-safe (nth 2 (cadr command)))))
925 (and name (stringp name)
926 (not (member name eshell-complex-commands))
927 (catch 'simple
928 (dolist (pred eshell-complex-commands t)
929 (when (and (functionp pred)
930 (funcall pred name))
931 (throw 'simple nil))))
932 (eshell-find-alias-function name)
933 (catch 'indirect-subcommand
934 (dolist (arg args t)
935 (pcase arg
936 (`(eshell-escape-arg
937 (let ,_
938 (eshell-convert
939 (eshell-command-to-value
940 (eshell-as-subcommand ,subcommand)))))
941 (unless (eshell--invoke-command-directly subcommand)
942 (throw 'indirect-subcommand nil))))))))))
943
906(defun eshell-invoke-directly (command) 944(defun eshell-invoke-directly (command)
907 (let ((base (cadr (nth 2 (nth 2 (cadr command))))) name) 945 "Determine whether the given COMMAND can be invoked directly.
908 (if (and (eq (car base) 'eshell-trap-errors) 946COMMAND should be a top-level Eshell command in parsed form, as
909 (eq (car (cadr base)) 'eshell-named-command)) 947produced by `eshell-parse-command'."
910 (setq name (cadr (cadr base)))) 948 (let ((base (cadr (nth 2 (nth 2 (cadr command))))))
911 (and name (stringp name) 949 (eshell--invoke-command-directly base)))
912 (not (member name eshell-complex-commands))
913 (catch 'simple
914 (progn
915 (dolist (pred eshell-complex-commands)
916 (if (and (functionp pred)
917 (funcall pred name))
918 (throw 'simple nil)))
919 t))
920 (eshell-find-alias-function name))))
921 950
922(defun eshell-eval-command (command &optional input) 951(defun eshell-eval-command (command &optional input)
923 "Evaluate the given COMMAND iteratively." 952 "Evaluate the given COMMAND iteratively."