From 0e9d89c2373a3f82385e61330233e88698df0d1a Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 28 Jan 2023 15:06:31 -0800 Subject: [PATCH 2/3] Simplify how Eshell's iterative evaluation handles 'if' forms The previous implementation used 'eshell-test-body' and 'eshell-command-body' to track the condition and the then/else forms, but those special variables are only needed for looping. 'if' only evaluates each form once (at most). * lisp/eshell/esh-cmd.el (Command evaluation macros): Remove 'if' from the notes about 'eshell-test-body' and 'eshell-command-body'. (eshell-do-eval): Reimplement evaluation of 'if' forms. (eshell-eval-command): Don't let-bind 'eshell-command-body' and 'eshell-test-body'; they're no longer needed here. --- lisp/eshell/esh-cmd.el | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 2dd8f5d6042..5dbbd770582 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -745,9 +745,9 @@ eshell-separate-commands ;; `condition-case', `if', `let', `prog1', `progn', `quote', `setq', ;; `unwind-protect', and `while'. ;; -;; @ When using `if' or `while', first let-bind `eshell-test-body' and +;; @ When using `while', first let-bind `eshell-test-body' and ;; `eshell-command-body' to '(nil). Eshell uses these variables to -;; handle conditional evaluation. +;; handle evaluating its subforms multiple times. ;; ;; @ The two `special' variables are `eshell-current-handles' and ;; `eshell-current-subjob-p'. Bind them locally with a `let' if you @@ -1031,9 +1031,7 @@ eshell-eval-command ;; We can just stick the new command at the end of the current ;; one, and everything will happen as it should. (setcdr (last (cdr eshell-current-command)) - (list `(let ((here (and (eobp) (point))) - (eshell-command-body '(nil)) - (eshell-test-body '(nil))) + (list `(let ((here (and (eobp) (point)))) ,(and input `(insert-and-inherit ,(concat input "\n"))) (if here @@ -1149,23 +1147,17 @@ eshell-do-eval (setcar eshell-test-body (copy-tree (car args)))) (setcar eshell-command-body nil)) ((eq (car form) 'if) - ;; `copy-tree' is needed here so that the test argument - ;; doesn't get modified and thus always yield the same result. - (if (car eshell-command-body) - (progn - (cl-assert (not synchronous-p)) - (eshell-do-eval (car eshell-command-body))) - (unless (car eshell-test-body) - (setcar eshell-test-body (copy-tree (car args)))) - (setcar eshell-command-body - (copy-tree - (if (cadr (eshell-do-eval (car eshell-test-body) - synchronous-p)) - (cadr args) - (car (cddr args))))) - (eshell-do-eval (car eshell-command-body) synchronous-p)) - (setcar eshell-command-body nil) - (setcar eshell-test-body nil)) + (eshell-manipulate "evaluating if condition" + (setcar args (eshell-do-eval (car args) synchronous-p))) + (eshell-do-eval + (cond + ((eval (car args)) ; COND is non-nil + (cadr args)) + ((cdddr args) ; Multiple ELSE forms + `(progn ,@(cddr args))) + (t ; Zero or one ELSE forms + (caddr args))) + synchronous-p)) ((eq (car form) 'setcar) (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) (eval form)) -- 2.25.1