diff options
| author | Po Lu | 2023-03-17 15:05:45 +0800 |
|---|---|---|
| committer | Po Lu | 2023-03-17 15:05:45 +0800 |
| commit | 2d666daaa3babeda669c39a8cfe36c4d30222512 (patch) | |
| tree | d733295b529ead57d4ae417b670c8a60b0730855 | |
| parent | 45b5c9b8b72a9dd561c7e2d43ead8ce64e79b041 (diff) | |
| parent | 1565dbcae35c1e42b22066fde226e3b063614a9e (diff) | |
| download | emacs-2d666daaa3babeda669c39a8cfe36c4d30222512.tar.gz emacs-2d666daaa3babeda669c39a8cfe36c4d30222512.zip | |
Merge remote-tracking branch 'origin/master' into feature/android
| -rw-r--r-- | lisp/eshell/esh-cmd.el | 115 |
1 files changed, 54 insertions, 61 deletions
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index d609711402a..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." | |||
| 494 | (t | 494 | (t |
| 495 | (list sym (car terms)))))) | 495 | (list sym (car terms)))))) |
| 496 | 496 | ||
| 497 | (defvar eshell-command-body) | 497 | (defvar eshell--command-body) |
| 498 | (defvar eshell-test-body) | 498 | (defvar eshell--test-body) |
| 499 | 499 | ||
| 500 | (defsubst eshell-invokify-arg (arg &optional share-output silent) | 500 | (defsubst eshell-invokify-arg (arg &optional share-output silent) |
| 501 | "Change ARG so it can be invoked from a structured command. | 501 | "Change ARG so it can be invoked from a structured command. |
| @@ -533,25 +533,21 @@ implemented via rewriting, rather than as a function." | |||
| 533 | (equal (nth 2 terms) "in")) | 533 | (equal (nth 2 terms) "in")) |
| 534 | (let ((body (car (last terms)))) | 534 | (let ((body (car (last terms)))) |
| 535 | (setcdr (last terms 2) nil) | 535 | (setcdr (last terms 2) nil) |
| 536 | `(let ((for-items | 536 | `(let ((for-items |
| 537 | (copy-tree | 537 | (append |
| 538 | (append | 538 | ,@(mapcar |
| 539 | ,@(mapcar | 539 | (lambda (elem) |
| 540 | (lambda (elem) | 540 | (if (listp elem) |
| 541 | (if (listp elem) | 541 | elem |
| 542 | elem | 542 | `(list ,elem))) |
| 543 | `(list ,elem))) | 543 | (nthcdr 3 terms))))) |
| 544 | (cdr (cddr terms)))))) | 544 | (while for-items |
| 545 | (eshell-command-body '(nil)) | 545 | (let ((,(intern (cadr terms)) (car for-items)) |
| 546 | (eshell-test-body '(nil))) | ||
| 547 | (while (car for-items) | ||
| 548 | (let ((,(intern (cadr terms)) (car for-items)) | ||
| 549 | (eshell--local-vars (cons ',(intern (cadr terms)) | 546 | (eshell--local-vars (cons ',(intern (cadr terms)) |
| 550 | eshell--local-vars))) | 547 | eshell--local-vars))) |
| 551 | (eshell-protect | 548 | (eshell-protect |
| 552 | ,(eshell-invokify-arg body t))) | 549 | ,(eshell-invokify-arg body t))) |
| 553 | (setcar for-items (cadr for-items)) | 550 | (setq for-items (cdr for-items))) |
| 554 | (setcdr for-items (cddr for-items))) | ||
| 555 | (eshell-close-handles))))) | 551 | (eshell-close-handles))))) |
| 556 | 552 | ||
| 557 | (defun eshell-structure-basic-command (func names keyword test body | 553 | (defun eshell-structure-basic-command (func names keyword test body |
| @@ -581,8 +577,7 @@ function." | |||
| 581 | 577 | ||
| 582 | ;; finally, create the form that represents this structured | 578 | ;; finally, create the form that represents this structured |
| 583 | ;; command | 579 | ;; command |
| 584 | `(let ((eshell-command-body '(nil)) | 580 | `(progn |
| 585 | (eshell-test-body '(nil))) | ||
| 586 | (,func ,test ,body ,else) | 581 | (,func ,test ,body ,else) |
| 587 | (eshell-close-handles))) | 582 | (eshell-close-handles))) |
| 588 | 583 | ||
| @@ -747,10 +742,6 @@ if none)." | |||
| 747 | ;; `condition-case', `if', `let', `prog1', `progn', `quote', `setq', | 742 | ;; `condition-case', `if', `let', `prog1', `progn', `quote', `setq', |
| 748 | ;; `unwind-protect', and `while'. | 743 | ;; `unwind-protect', and `while'. |
| 749 | ;; | 744 | ;; |
| 750 | ;; @ When using `if' or `while', first let-bind `eshell-test-body' and | ||
| 751 | ;; `eshell-command-body' to '(nil). Eshell uses these variables to | ||
| 752 | ;; handle conditional evaluation. | ||
| 753 | ;; | ||
| 754 | ;; @ The two `special' variables are `eshell-current-handles' and | 745 | ;; @ The two `special' variables are `eshell-current-handles' and |
| 755 | ;; `eshell-current-subjob-p'. Bind them locally with a `let' if you | 746 | ;; `eshell-current-subjob-p'. Bind them locally with a `let' if you |
| 756 | ;; need to change them. Change them directly only if your intention | 747 | ;; need to change them. Change them directly only if your intention |
| @@ -1033,9 +1024,7 @@ produced by `eshell-parse-command'." | |||
| 1033 | ;; We can just stick the new command at the end of the current | 1024 | ;; We can just stick the new command at the end of the current |
| 1034 | ;; one, and everything will happen as it should. | 1025 | ;; one, and everything will happen as it should. |
| 1035 | (setcdr (last (cdr eshell-current-command)) | 1026 | (setcdr (last (cdr eshell-current-command)) |
| 1036 | (list `(let ((here (and (eobp) (point))) | 1027 | (list `(let ((here (and (eobp) (point)))) |
| 1037 | (eshell-command-body '(nil)) | ||
| 1038 | (eshell-test-body '(nil))) | ||
| 1039 | ,(and input | 1028 | ,(and input |
| 1040 | `(insert-and-inherit ,(concat input "\n"))) | 1029 | `(insert-and-inherit ,(concat input "\n"))) |
| 1041 | (if here | 1030 | (if here |
| @@ -1132,42 +1121,46 @@ have been replaced by constants." | |||
| 1132 | (let ((args (cdr form))) | 1121 | (let ((args (cdr form))) |
| 1133 | (cond | 1122 | (cond |
| 1134 | ((eq (car form) 'while) | 1123 | ((eq (car form) 'while) |
| 1124 | ;; Wrap the `while' form with let-bindings for the command and | ||
| 1125 | ;; test bodies. This helps us resume evaluation midway | ||
| 1126 | ;; through the loop. | ||
| 1127 | (let ((new-form (copy-tree `(let ((eshell--command-body nil) | ||
| 1128 | (eshell--test-body nil)) | ||
| 1129 | (eshell--wrapped-while ,@args))))) | ||
| 1130 | (eshell-manipulate "modifying while form" | ||
| 1131 | (setcar form (car new-form)) | ||
| 1132 | (setcdr form (cdr new-form))) | ||
| 1133 | (eshell-do-eval form synchronous-p))) | ||
| 1134 | ((eq (car form) 'eshell--wrapped-while) | ||
| 1135 | (when eshell--command-body | ||
| 1136 | (cl-assert (not synchronous-p)) | ||
| 1137 | (eshell-do-eval eshell--command-body) | ||
| 1138 | (setq eshell--command-body nil | ||
| 1139 | eshell--test-body nil)) | ||
| 1135 | ;; `copy-tree' is needed here so that the test argument | 1140 | ;; `copy-tree' is needed here so that the test argument |
| 1136 | ;; doesn't get modified and thus always yield the same result. | 1141 | ;; doesn't get modified and thus always yield the same result. |
| 1137 | (when (car eshell-command-body) | 1142 | (unless eshell--test-body |
| 1138 | (cl-assert (not synchronous-p)) | 1143 | (setq eshell--test-body (copy-tree (car args)))) |
| 1139 | (eshell-do-eval (car eshell-command-body)) | 1144 | (while (cadr (eshell-do-eval eshell--test-body synchronous-p)) |
| 1140 | (setcar eshell-command-body nil) | 1145 | (setq eshell--command-body |
| 1141 | (setcar eshell-test-body nil)) | 1146 | (if (cddr args) |
| 1142 | (unless (car eshell-test-body) | 1147 | `(progn ,@(copy-tree (cdr args))) |
| 1143 | (setcar eshell-test-body (copy-tree (car args)))) | 1148 | (copy-tree (cadr args)))) |
| 1144 | (while (cadr (eshell-do-eval (car eshell-test-body) synchronous-p)) | 1149 | (eshell-do-eval eshell--command-body synchronous-p) |
| 1145 | (setcar eshell-command-body | 1150 | (setq eshell--command-body nil |
| 1146 | (if (cddr args) | 1151 | eshell--test-body (copy-tree (car args))))) |
| 1147 | `(progn ,@(copy-tree (cdr args))) | ||
| 1148 | (copy-tree (cadr args)))) | ||
| 1149 | (eshell-do-eval (car eshell-command-body) synchronous-p) | ||
| 1150 | (setcar eshell-command-body nil) | ||
| 1151 | (setcar eshell-test-body (copy-tree (car args)))) | ||
| 1152 | (setcar eshell-command-body nil)) | ||
| 1153 | ((eq (car form) 'if) | 1152 | ((eq (car form) 'if) |
| 1154 | ;; `copy-tree' is needed here so that the test argument | 1153 | (eshell-manipulate "evaluating if condition" |
| 1155 | ;; doesn't get modified and thus always yield the same result. | 1154 | (setcar args (eshell-do-eval (car args) synchronous-p))) |
| 1156 | (if (car eshell-command-body) | 1155 | (eshell-do-eval |
| 1157 | (progn | 1156 | (cond |
| 1158 | (cl-assert (not synchronous-p)) | 1157 | ((eval (car args)) ; COND is non-nil |
| 1159 | (eshell-do-eval (car eshell-command-body))) | 1158 | (cadr args)) |
| 1160 | (unless (car eshell-test-body) | 1159 | ((cdddr args) ; Multiple ELSE forms |
| 1161 | (setcar eshell-test-body (copy-tree (car args)))) | 1160 | `(progn ,@(cddr args))) |
| 1162 | (setcar eshell-command-body | 1161 | (t ; Zero or one ELSE forms |
| 1163 | (copy-tree | 1162 | (caddr args))) |
| 1164 | (if (cadr (eshell-do-eval (car eshell-test-body) | 1163 | synchronous-p)) |
| 1165 | synchronous-p)) | ||
| 1166 | (cadr args) | ||
| 1167 | (car (cddr args))))) | ||
| 1168 | (eshell-do-eval (car eshell-command-body) synchronous-p)) | ||
| 1169 | (setcar eshell-command-body nil) | ||
| 1170 | (setcar eshell-test-body nil)) | ||
| 1171 | ((eq (car form) 'setcar) | 1164 | ((eq (car form) 'setcar) |
| 1172 | (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) | 1165 | (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) |
| 1173 | (eval form)) | 1166 | (eval form)) |