From: Sean Whitton Date: Sat, 2 Apr 2022 14:08:41 +0000 (+0200) Subject: em-extpipe: Catch eshell-incomplete thrown while parsing X-Git-Tag: emacs-29.0.90~1931^2~814 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=02ef00d89c64d713f29f4ed12dbcae9f8d31bb9a;p=emacs.git em-extpipe: Catch eshell-incomplete thrown while parsing * lisp/eshell/em-extpipe.el (em-extpipe--or-with-catch): New macro. (eshell-parse-external-pipeline): Use new macro to treat `eshell-incomplete' as a failure of the parse function to move us forward (Bug#54603). Thanks to Jim Porter for the report and for help isolating the problem. * test/lisp/eshell/eshell-tests.el (eshell-test/lisp-command-with-quote): New test for Bug#54603, thanks to Jim Porter (bug#54603). --- diff --git a/lisp/eshell/em-extpipe.el b/lisp/eshell/em-extpipe.el index eb5b3bfe1df..3db1dea5955 100644 --- a/lisp/eshell/em-extpipe.el +++ b/lisp/eshell/em-extpipe.el @@ -49,6 +49,19 @@ (add-hook 'eshell-pre-rewrite-command-hook #'eshell-rewrite-external-pipeline -20 t)) +(defmacro em-extpipe--or-with-catch (&rest disjuncts) + "Evaluate DISJUNCTS like `or' but catch `eshell-incomplete'. + +If `eshell-incomplete' is thrown during the evaluation of a +disjunct, that disjunct yields nil." + (let ((result (gensym))) + `(let (,result) + (or ,@(cl-loop for disjunct in disjuncts collect + `(if (catch 'eshell-incomplete + (ignore (setq ,result ,disjunct))) + nil + ,result)))))) + (defun eshell-parse-external-pipeline () "Parse a pipeline intended for execution by the external shell. @@ -105,10 +118,11 @@ as though it were Eshell syntax." (if (re-search-forward pat next t) (throw 'found (match-beginning 1)) (goto-char next) - (while (or (eshell-parse-lisp-argument) - (eshell-parse-backslash) - (eshell-parse-double-quote) - (eshell-parse-literal-quote))) + (while (em-extpipe--or-with-catch + (eshell-parse-lisp-argument) + (eshell-parse-backslash) + (eshell-parse-double-quote) + (eshell-parse-literal-quote))) ;; Guard against an infinite loop if none of ;; the parsers moved us forward. (unless (or (> (point) next) (eobp)) diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el index e31db07c619..1e303f70e5f 100644 --- a/test/lisp/eshell/eshell-tests.el +++ b/test/lisp/eshell/eshell-tests.el @@ -44,6 +44,10 @@ "Test `eshell-command-result' with an elisp command." (should (equal (eshell-test-command-result "(+ 1 2)") 3))) +(ert-deftest eshell-test/lisp-command-with-quote () + "Test `eshell-command-result' with an elisp command containing a quote." + (should (equal (eshell-test-command-result "(eq 'foo nil)") nil))) + (ert-deftest eshell-test/for-loop () "Test `eshell-command-result' with a for loop.." (let ((process-environment (cons "foo" process-environment)))