emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 1565dbcae35 3/3: Simplify usage of 'while' forms in Eshell's iter


From: Jim Porter
Subject: master 1565dbcae35 3/3: Simplify usage of 'while' forms in Eshell's iterative evaluation
Date: Fri, 17 Mar 2023 01:32:43 -0400 (EDT)

branch: master
commit 1565dbcae35c1e42b22066fde226e3b063614a9e
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>

    Simplify usage of 'while' forms in Eshell's iterative evaluation
    
    Now, 'eshell-do-eval' rewrites 'while' forms to let-bind variables for
    the command and test bodies.  This means that external code, such as
    command rewriting hooks, no longer has to worry about this, making it
    easier to pass "normal" Lisp forms to 'eshell-do-eval' (bug#61954).
    
    * lisp/eshell/esh-cmd.el (eshell-command-body, eshell-test-body): No
    longer used outside of 'eshell-do-eval', so rename to...
    (eshell--command-body, eshell--test-body): ... these.
    (Command evaluation macros): Remove obsolete description about 'if'
    and 'while' forms.
    (eshell-rewrite-for-command, eshell-structure-basic-command): Remove
    'eshell-command-body' and 'eshell-test-body'.
    (eshell-do-eval): Reimplement handling of 'while' forms.
---
 lisp/eshell/esh-cmd.el | 59 ++++++++++++++++++++++++++------------------------
 1 file changed, 31 insertions(+), 28 deletions(-)

diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 5dbbd770582..93f2616020c 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -494,8 +494,8 @@ hooks should be run before and after the command."
      (t
       (list sym (car terms))))))
 
-(defvar eshell-command-body)
-(defvar eshell-test-body)
+(defvar eshell--command-body)
+(defvar eshell--test-body)
 
 (defsubst eshell-invokify-arg (arg &optional share-output silent)
   "Change ARG so it can be invoked from a structured command.
@@ -540,9 +540,7 @@ implemented via rewriting, rather than as a function."
                       (if (listp elem)
                           elem
                         `(list ,elem)))
-                    (nthcdr 3 terms))))
-               (eshell-command-body '(nil))
-               (eshell-test-body '(nil)))
+                    (nthcdr 3 terms)))))
            (while for-items
              (let ((,(intern (cadr terms)) (car for-items))
                   (eshell--local-vars (cons ',(intern (cadr terms))
@@ -579,8 +577,7 @@ function."
 
   ;; finally, create the form that represents this structured
   ;; command
-  `(let ((eshell-command-body '(nil))
-         (eshell-test-body '(nil)))
+  `(progn
      (,func ,test ,body ,else)
      (eshell-close-handles)))
 
@@ -745,10 +742,6 @@ if none)."
 ;;   `condition-case', `if', `let', `prog1', `progn', `quote', `setq',
 ;;   `unwind-protect', and `while'.
 ;;
-;; @ When using `while', first let-bind `eshell-test-body' and
-;;   `eshell-command-body' to '(nil).  Eshell uses these variables to
-;;   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
 ;;   need to change them.  Change them directly only if your intention
@@ -1128,24 +1121,34 @@ have been replaced by constants."
     (let ((args (cdr form)))
       (cond
        ((eq (car form) 'while)
+        ;; Wrap the `while' form with let-bindings for the command and
+        ;; test bodies.  This helps us resume evaluation midway
+        ;; through the loop.
+        (let ((new-form (copy-tree `(let ((eshell--command-body nil)
+                                          (eshell--test-body nil))
+                                      (eshell--wrapped-while ,@args)))))
+          (eshell-manipulate "modifying while form"
+            (setcar form (car new-form))
+            (setcdr form (cdr new-form)))
+          (eshell-do-eval form synchronous-p)))
+       ((eq (car form) 'eshell--wrapped-while)
+        (when eshell--command-body
+          (cl-assert (not synchronous-p))
+          (eshell-do-eval eshell--command-body)
+          (setq eshell--command-body nil
+                eshell--test-body nil))
         ;; `copy-tree' is needed here so that the test argument
-       ;; doesn't get modified and thus always yield the same result.
-       (when (car eshell-command-body)
-         (cl-assert (not synchronous-p))
-         (eshell-do-eval (car eshell-command-body))
-         (setcar eshell-command-body nil)
-         (setcar eshell-test-body nil))
-       (unless (car eshell-test-body)
-          (setcar eshell-test-body (copy-tree (car args))))
-       (while (cadr (eshell-do-eval (car eshell-test-body) synchronous-p))
-         (setcar eshell-command-body
-                  (if (cddr args)
-                      `(progn ,@(copy-tree (cdr args)))
-                    (copy-tree (cadr args))))
-         (eshell-do-eval (car eshell-command-body) synchronous-p)
-         (setcar eshell-command-body nil)
-          (setcar eshell-test-body (copy-tree (car args))))
-       (setcar eshell-command-body nil))
+        ;; doesn't get modified and thus always yield the same result.
+        (unless eshell--test-body
+          (setq eshell--test-body (copy-tree (car args))))
+        (while (cadr (eshell-do-eval eshell--test-body synchronous-p))
+          (setq eshell--command-body
+                (if (cddr args)
+                    `(progn ,@(copy-tree (cdr args)))
+                  (copy-tree (cadr args))))
+          (eshell-do-eval eshell--command-body synchronous-p)
+          (setq eshell--command-body nil
+                eshell--test-body (copy-tree (car args)))))
        ((eq (car form) 'if)
         (eshell-manipulate "evaluating if condition"
           (setcar args (eshell-do-eval (car args) synchronous-p)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]