From 7a64056e44a6f789fb2f58cca2c6876cfdcc107d Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 26 Feb 2022 20:55:22 -0800 Subject: [PATCH 2/5] Add a new macro to simplify parsing temporary Eshell command strings This abstracts out the somewhat-unusual "insert&delete" logic in 'eshell-parse-command' so that it can be used elsewhere, and also ensures that the deletion occurs even if an an error occurs. * lisp/eshell/esh-cmd.el (eshell-with-temp-command): New macro. (eshell-parse-command): Use it. --- lisp/eshell/esh-cmd.el | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index dceb061c8f..04b54d9d79 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -350,6 +350,36 @@ eshell-complete-lisp-symbols (defvar eshell--sep-terms) +(defmacro eshell-with-temp-command (command &rest body) + "Narrow the buffer to COMMAND and execute the forms in BODY. +COMMAND can either be a string, or a cons cell demarcating a +buffer region. If COMMAND is a string, temporarily insert it +into the buffer before narrowing. Point will be set to the +beginning of the narrowed region. + +The value returned is the last form in BODY." + (declare (indent 1)) + `(let ((cmd ,command)) + (if (stringp cmd) + ;; Since parsing relies partly on buffer-local state + ;; (e.g. that of `eshell-parse-argument-hook'), we need to + ;; perform the parsing in the Eshell buffer. + (let ((begin (point)) end + (inhibit-point-motion-hooks t)) + (with-silent-modifications + (insert cmd) + (setq end (point)) + (unwind-protect + (save-restriction + (narrow-to-region begin end) + (goto-char begin) + ,@body) + (delete-region begin end)))) + (save-restriction + (narrow-to-region (car cmd) (cdr cmd)) + (goto-char (car cmd)) + ,@body)))) + (defun eshell-parse-command (command &optional args toplevel) "Parse the COMMAND, adding ARGS if given. COMMAND can either be a string, or a cons cell demarcating a buffer @@ -361,15 +391,9 @@ eshell-parse-command (append (if (consp command) (eshell-parse-arguments (car command) (cdr command)) - (let ((here (point)) - (inhibit-point-motion-hooks t)) - (with-silent-modifications - ;; FIXME: Why not use a temporary buffer and avoid this - ;; "insert&delete" business? --Stef - (insert command) - (prog1 - (eshell-parse-arguments here (point)) - (delete-region here (point)))))) + (eshell-with-temp-command command + (goto-char (point-max)) + (eshell-parse-arguments (point-min) (point-max)))) args)) (commands (mapcar -- 2.25.1