aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Porter2022-05-22 17:27:48 -0700
committerLars Ingebrigtsen2022-05-24 14:58:00 +0200
commita49ecdd0ff2b2526fcc519bb23ce1f5113c8fb1d (patch)
treed8ac3f279ad977d2ae21f42d27a389b6b53ecddd
parentbe17333acee2086d1c729197dfe64432f6ad6625 (diff)
downloademacs-a49ecdd0ff2b2526fcc519bb23ce1f5113c8fb1d.tar.gz
emacs-a49ecdd0ff2b2526fcc519bb23ce1f5113c8fb1d.zip
Keep subcommands in pipelines from clobbering the head/tail processes
* lisp/eshell/esh-cmd.el (eshell-execute-pipeline): Use 'make-symbol' for headproc and tailproc. (eshell-do-pipelines, eshell-do-pipelines-synchronously): Adapt to the above. * test/lisp/eshell/eshell-tests.el (eshell-test/pipe-subcommand) (eshell-test/pipe-subcommand-with-pipe): New test. * doc/misc/eshell.texi (Bugs and ideas): Remove item about piping to process from loop; this commit fixes it (bug#55590).
-rw-r--r--doc/misc/eshell.texi8
-rw-r--r--lisp/eshell/esh-cmd.el15
-rw-r--r--test/lisp/eshell/eshell-tests.el16
3 files changed, 26 insertions, 13 deletions
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index d35a642b62d..85e5a4933fd 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -1758,14 +1758,6 @@ alias arg=blah
1758function arg () @{ blah $* @} 1758function arg () @{ blah $* @}
1759@end example 1759@end example
1760 1760
1761@item @samp{for i in 1 2 3 @{ grep -q a b && *echo has it @} | wc -l} outputs result after prompt
1762
1763In fact, piping to a process from a looping construct doesn't work in
1764general. If I change the call to @code{eshell-copy-handles} in
1765@code{eshell-rewrite-for-command} to use @code{eshell-protect}, it seems
1766to work, but the output occurs after the prompt is displayed. The whole
1767structured command thing is too complicated at present.
1768
1769@item Pcomplete sometimes gets stuck 1761@item Pcomplete sometimes gets stuck
1770 1762
1771You press @key{TAB}, but no completions appear, even though the 1763You press @key{TAB}, but no completions appear, even though the
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 42616e7037d..73c250632ce 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -827,8 +827,8 @@ This macro calls itself recursively, with NOTFIRST non-nil."
827 ((cdr pipeline) t) 827 ((cdr pipeline) t)
828 (t (quote 'last))))) 828 (t (quote 'last)))))
829 (let ((proc ,(car pipeline))) 829 (let ((proc ,(car pipeline)))
830 (setq headproc (or proc headproc)) 830 (set headproc (or proc (symbol-value headproc)))
831 (setq tailproc (or tailproc proc)) 831 (set tailproc (or (symbol-value tailproc) proc))
832 proc)))))) 832 proc))))))
833 833
834(defmacro eshell-do-pipelines-synchronously (pipeline) 834(defmacro eshell-do-pipelines-synchronously (pipeline)
@@ -861,7 +861,7 @@ This is used on systems where async subprocesses are not supported."
861 (let ((result ,(car pipeline))) 861 (let ((result ,(car pipeline)))
862 ;; tailproc gets the result of the last successful process in 862 ;; tailproc gets the result of the last successful process in
863 ;; the pipeline. 863 ;; the pipeline.
864 (setq tailproc (or result tailproc)) 864 (set tailproc (or result (symbol-value tailproc)))
865 ,(if (cdr pipeline) 865 ,(if (cdr pipeline)
866 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline)))) 866 `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
867 result)))) 867 result))))
@@ -870,7 +870,11 @@ This is used on systems where async subprocesses are not supported."
870 870
871(defmacro eshell-execute-pipeline (pipeline) 871(defmacro eshell-execute-pipeline (pipeline)
872 "Execute the commands in PIPELINE, connecting each to one another." 872 "Execute the commands in PIPELINE, connecting each to one another."
873 `(let ((eshell-in-pipeline-p t) headproc tailproc) 873 `(let ((eshell-in-pipeline-p t)
874 (headproc (make-symbol "headproc"))
875 (tailproc (make-symbol "tailproc")))
876 (set headproc nil)
877 (set tailproc nil)
874 (progn 878 (progn
875 ,(if (fboundp 'make-process) 879 ,(if (fboundp 'make-process)
876 `(eshell-do-pipelines ,pipeline) 880 `(eshell-do-pipelines ,pipeline)
@@ -880,7 +884,8 @@ This is used on systems where async subprocesses are not supported."
880 (car (aref eshell-current-handles 884 (car (aref eshell-current-handles
881 ,eshell-error-handle)) nil))) 885 ,eshell-error-handle)) nil)))
882 (eshell-do-pipelines-synchronously ,pipeline))) 886 (eshell-do-pipelines-synchronously ,pipeline)))
883 (eshell-process-identity (cons headproc tailproc))))) 887 (eshell-process-identity (cons (symbol-value headproc)
888 (symbol-value tailproc))))))
884 889
885(defmacro eshell-as-subcommand (command) 890(defmacro eshell-as-subcommand (command)
886 "Execute COMMAND using a temp buffer. 891 "Execute COMMAND using a temp buffer.
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index 7cdeb017e44..c0affed80aa 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -114,6 +114,22 @@ e.g. \"{(+ 1 2)} 3\" => 3"
114 (eshell-wait-for-subprocess) 114 (eshell-wait-for-subprocess)
115 (eshell-match-result "OLLEH\n"))) 115 (eshell-match-result "OLLEH\n")))
116 116
117(ert-deftest eshell-test/pipe-subcommand ()
118 "Check that piping with an asynchronous subcommand works"
119 (skip-unless (and (executable-find "echo")
120 (executable-find "cat")))
121 (with-temp-eshell
122 (eshell-command-result-p "echo ${*echo hi} | *cat"
123 "hi")))
124
125(ert-deftest eshell-test/pipe-subcommand-with-pipe ()
126 "Check that piping with an asynchronous subcommand with its own pipe works"
127 (skip-unless (and (executable-find "echo")
128 (executable-find "cat")))
129 (with-temp-eshell
130 (eshell-command-result-p "echo ${*echo hi | *cat} | *cat"
131 "hi")))
132
117(ert-deftest eshell-test/redirect-buffer () 133(ert-deftest eshell-test/redirect-buffer ()
118 "Check that piping to a buffer works" 134 "Check that piping to a buffer works"
119 (with-temp-buffer 135 (with-temp-buffer