From 1b6c988ed697de9c30690aa69c3fc5a5f305a342 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Mon, 20 Mar 2023 17:25:24 -0700 Subject: [PATCH 2/3] Simplify parsing subcommands slightly This mainly reduces some overly-deep indentation, but also fixes some minor issues with the "$" form: it unnecessarily added " > TEMP" (we already set this later via 'eshell-create-handles'), and it didn't properly unescape inner double quotes. * lisp/eshell/esh-cmd.el (eshell-parse-subcommand-argument): Simplify. * lisp/eshell/esh-var.el (eshell-parse-variable-ref): Simplify and fix edge cases in "$". --- lisp/eshell/esh-cmd.el | 14 +++---- lisp/eshell/esh-var.el | 95 +++++++++++++++++++++--------------------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index e0651b76249..1a458290dfe 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -675,13 +675,13 @@ eshell-parse-subcommand-argument (or (= (point-max) (1+ (point))) (not (eq (char-after (1+ (point))) ?\})))) (let ((end (eshell-find-delimiter ?\{ ?\}))) - (if (not end) - (throw 'eshell-incomplete "{") - (when (eshell-arg-delimiter (1+ end)) - (prog1 - `(eshell-as-subcommand - ,(eshell-parse-command (cons (1+ (point)) end))) - (goto-char (1+ end)))))))) + (unless end + (throw 'eshell-incomplete "{")) + (when (eshell-arg-delimiter (1+ end)) + (prog1 + `(eshell-as-subcommand + ,(eshell-parse-command (cons (1+ (point)) end))) + (goto-char (1+ end))))))) (defun eshell-parse-lisp-argument () "Parse a Lisp expression which is specified as an argument." diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index 5d6299af564..7dcaff1e24f 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -507,55 +507,56 @@ eshell-parse-variable-ref (cond ((eq (char-after) ?{) (let ((end (eshell-find-delimiter ?\{ ?\}))) - (if (not end) - (throw 'eshell-incomplete "${") - (forward-char) - (prog1 - `(eshell-apply-indices - (eshell-convert - (eshell-command-to-value - (eshell-as-subcommand - ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) - (cons (point) end))) - (eshell-current-quoted nil)) - (eshell-parse-command subcmd)))) - ;; If this is a simple double-quoted form like - ;; "${COMMAND}" (i.e. no indices after the subcommand - ;; and no `#' modifier before), ensure we convert to a - ;; single string. This avoids unnecessary work - ;; (e.g. splitting the output by lines) when it would - ;; just be joined back together afterwards. - ,(when (and (not modifier-p) eshell-current-quoted) - '(not indices))) - indices ,eshell-current-quoted) - (goto-char (1+ end)))))) + (unless end + (throw 'eshell-incomplete "${")) + (forward-char) + (prog1 + `(eshell-apply-indices + (eshell-convert + (eshell-command-to-value + (eshell-as-subcommand + ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) + (cons (point) end))) + (eshell-current-quoted nil)) + (eshell-parse-command subcmd)))) + ;; If this is a simple double-quoted form like + ;; "${COMMAND}" (i.e. no indices after the subcommand and + ;; no `#' modifier before), ensure we convert to a single + ;; string. This avoids unnecessary work (e.g. splitting + ;; the output by lines) when it would just be joined back + ;; together afterwards. + ,(when (and (not modifier-p) eshell-current-quoted) + '(not indices))) + indices ,eshell-current-quoted) + (goto-char (1+ end))))) ((eq (char-after) ?\<) (let ((end (eshell-find-delimiter ?\< ?\>))) - (if (not end) - (throw 'eshell-incomplete "$<") - (let* ((temp (make-temp-file temporary-file-directory)) - (cmd (concat (buffer-substring (1+ (point)) end) - " > " temp))) - (prog1 - `(let ((eshell-current-handles - (eshell-create-handles ,temp 'overwrite))) - (progn - (eshell-as-subcommand - ,(let ((eshell-current-quoted nil)) - (eshell-parse-command cmd))) - (ignore - (nconc eshell-this-command-hook - ;; Quote this lambda; it will be evaluated - ;; by `eshell-do-eval', which requires very - ;; particular forms in order to work - ;; properly. See bug#54190. - (list (function - (lambda () - (delete-file ,temp) - (when-let ((buffer (get-file-buffer ,temp))) - (kill-buffer buffer))))))) - (eshell-apply-indices ,temp indices ,eshell-current-quoted))) - (goto-char (1+ end))))))) + (unless end + (throw 'eshell-incomplete "$<")) + (forward-char) + (let* ((temp (make-temp-file temporary-file-directory)) + (subcmd (or (eshell-unescape-inner-double-quote end) + (cons (point) end)))) + (prog1 + `(let ((eshell-current-handles + (eshell-create-handles ,temp 'overwrite))) + (progn + (eshell-as-subcommand + ,(let ((eshell-current-quoted nil)) + (eshell-parse-command subcmd))) + (ignore + (nconc eshell-this-command-hook + ;; Quote this lambda; it will be evaluated by + ;; `eshell-do-eval', which requires very + ;; particular forms in order to work + ;; properly. See bug#54190. + (list (function + (lambda () + (delete-file ,temp) + (when-let ((buffer (get-file-buffer ,temp))) + (kill-buffer buffer))))))) + (eshell-apply-indices ,temp indices ,eshell-current-quoted))) + (goto-char (1+ end)))))) ((eq (char-after) ?\() (condition-case nil `(eshell-apply-indices -- 2.25.1