diff options
| author | Jim Porter | 2022-01-20 14:37:54 +0100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-01-20 14:37:54 +0100 |
| commit | 4450c8bdd93d1b2e7f276e26be2cc37372034c22 (patch) | |
| tree | e45604026d24ea26a1bb7ec342cc6d72edbce505 /lisp/eshell | |
| parent | 55c1670bc52c924d80c72e55bf3864023749be29 (diff) | |
| download | emacs-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.el | 57 |
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. | ||
| 908 | COMMAND should be a non-top-level Eshell command in parsed form. | ||
| 909 | |||
| 910 | A 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) | 946 | COMMAND should be a top-level Eshell command in parsed form, as |
| 909 | (eq (car (cadr base)) 'eshell-named-command)) | 947 | produced 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." |