diff options
| author | Jim Porter | 2023-08-22 13:13:45 -0700 |
|---|---|---|
| committer | Jim Porter | 2023-10-24 11:36:27 -0700 |
| commit | 1c2cb9cd6192e97a29fbe338fd1a639f6dfae2d2 (patch) | |
| tree | 8ffa80dc0de1013094e9e33e052693b7a19d83a7 | |
| parent | f7d88f4a0478d89f70243456af8c4d4817d6b251 (diff) | |
| download | emacs-1c2cb9cd6192e97a29fbe338fd1a639f6dfae2d2.tar.gz emacs-1c2cb9cd6192e97a29fbe338fd1a639f6dfae2d2.zip | |
Support arbitrary Eshell arguments inside special references
* lisp/eshell/esh-arg.el (eshell-current-argument-plain): New variable.
(eshell-parse-special-reference): Use 'eshell-parse-arguments'.
(eshell-get-buffer): New function.
(eshell-insert-buffer-name): Properly quote the buffer name.
* lisp/eshell/esh-proc.el (eshell-read-process-name): Move to "Special
references" section.
(eshell-insert-process): Properly quote the process name.
* lisp/eshell/em-extpipe.el (eshell-parse-external-pipeline):
* lisp/eshell/esh-io.el (eshell-parse-redirection): Don't do anything
when 'eshell-argument-plain' is non-nil.
* test/lisp/eshell/esh-arg-tests.el
(esh-arg-test/special-reference/quoted)
(esh-arg-test/special-reference/var-expansion): New tests.
(esh-arg-test/special-reference/special): Rename to...
(esh-arg-test/special-reference/special-characters): ... this.
* test/lisp/eshell/em-extpipe-tests.el (em-extpipe-tests--deftest):
Properly quote the buffer name.
(em-extpipe-test-4, em-extpipe-test-7): Use 'eshell-get-buffer'.
| -rw-r--r-- | lisp/eshell/em-extpipe.el | 161 | ||||
| -rw-r--r-- | lisp/eshell/esh-arg.el | 87 | ||||
| -rw-r--r-- | lisp/eshell/esh-io.el | 3 | ||||
| -rw-r--r-- | lisp/eshell/esh-proc.el | 38 | ||||
| -rw-r--r-- | test/lisp/eshell/em-extpipe-tests.el | 8 | ||||
| -rw-r--r-- | test/lisp/eshell/esh-arg-tests.el | 25 |
6 files changed, 178 insertions, 144 deletions
diff --git a/lisp/eshell/em-extpipe.el b/lisp/eshell/em-extpipe.el index 5c9a0a85934..0d5c217f5f0 100644 --- a/lisp/eshell/em-extpipe.el +++ b/lisp/eshell/em-extpipe.el | |||
| @@ -118,86 +118,87 @@ as though it were Eshell syntax." | |||
| 118 | ;; other members of `eshell-parse-argument-hook'. We must avoid | 118 | ;; other members of `eshell-parse-argument-hook'. We must avoid |
| 119 | ;; misinterpreting a quoted `*|', `*<' or `*>' as indicating an | 119 | ;; misinterpreting a quoted `*|', `*<' or `*>' as indicating an |
| 120 | ;; external pipeline, hence the structure of the loop in `findbeg1'. | 120 | ;; external pipeline, hence the structure of the loop in `findbeg1'. |
| 121 | (cl-flet | 121 | (unless eshell-current-argument-plain |
| 122 | ((findbeg1 (pat &optional go (bound (point-max))) | 122 | (cl-flet |
| 123 | (let* ((start (point)) | 123 | ((findbeg1 (pat &optional go (bound (point-max))) |
| 124 | (result | 124 | (let* ((start (point)) |
| 125 | (catch 'found | 125 | (result |
| 126 | (while (> bound (point)) | 126 | (catch 'found |
| 127 | (let* ((found | 127 | (while (> bound (point)) |
| 128 | (save-excursion | 128 | (let* ((found |
| 129 | (re-search-forward | 129 | (save-excursion |
| 130 | "\\(?:#?'\\|\"\\|\\\\\\)" bound t))) | 130 | (re-search-forward |
| 131 | (next (or (and found (match-beginning 0)) | 131 | "\\(?:#?'\\|\"\\|\\\\\\)" bound t))) |
| 132 | bound))) | 132 | (next (or (and found (match-beginning 0)) |
| 133 | (if (re-search-forward pat next t) | 133 | bound))) |
| 134 | (throw 'found (match-beginning 1)) | 134 | (if (re-search-forward pat next t) |
| 135 | (goto-char next) | 135 | (throw 'found (match-beginning 1)) |
| 136 | (while (eshell-extpipe--or-with-catch | 136 | (goto-char next) |
| 137 | (eshell-parse-lisp-argument) | 137 | (while (eshell-extpipe--or-with-catch |
| 138 | (eshell-parse-backslash) | 138 | (eshell-parse-lisp-argument) |
| 139 | (eshell-parse-double-quote) | 139 | (eshell-parse-backslash) |
| 140 | (eshell-parse-literal-quote))) | 140 | (eshell-parse-double-quote) |
| 141 | ;; Guard against an infinite loop if none of | 141 | (eshell-parse-literal-quote))) |
| 142 | ;; the parsers moved us forward. | 142 | ;; Guard against an infinite loop if none of |
| 143 | (unless (or (> (point) next) (eobp)) | 143 | ;; the parsers moved us forward. |
| 144 | (forward-char 1)))))))) | 144 | (unless (or (> (point) next) (eobp)) |
| 145 | (goto-char (if (and result go) (match-end 0) start)) | 145 | (forward-char 1)))))))) |
| 146 | result))) | 146 | (goto-char (if (and result go) (match-end 0) start)) |
| 147 | (unless (or eshell-current-argument eshell-current-quoted) | 147 | result))) |
| 148 | (let ((beg (point)) end | 148 | (unless (or eshell-current-argument eshell-current-quoted) |
| 149 | (next-marked (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)")) | 149 | (let ((beg (point)) end |
| 150 | (next-unmarked | 150 | (next-marked (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)")) |
| 151 | (or (findbeg1 "\\(?:\\=\\|[^*]\\|\\S-\\*\\)\\(|\\)") | 151 | (next-unmarked |
| 152 | (point-max)))) | 152 | (or (findbeg1 "\\(?:\\=\\|[^*]\\|\\S-\\*\\)\\(|\\)") |
| 153 | (when (and next-marked (> next-unmarked next-marked) | 153 | (point-max)))) |
| 154 | (or (> next-marked (point)) | 154 | (when (and next-marked (> next-unmarked next-marked) |
| 155 | (looking-back "\\`\\|\\s-" nil))) | 155 | (or (> next-marked (point)) |
| 156 | ;; Skip to the final segment of the external pipeline. | 156 | (looking-back "\\`\\|\\s-" nil))) |
| 157 | (while (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*|\\)" t)) | 157 | ;; Skip to the final segment of the external pipeline. |
| 158 | ;; Find output redirections. | 158 | (while (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*|\\)" t)) |
| 159 | (while (findbeg1 | 159 | ;; Find output redirections. |
| 160 | "\\([0-9]?>+&?[0-9]?\\s-*\\S-\\)" t next-unmarked) | 160 | (while (findbeg1 |
| 161 | ;; Is the output redirection Eshell-specific? We have our | 161 | "\\([0-9]?>+&?[0-9]?\\s-*\\S-\\)" t next-unmarked) |
| 162 | ;; own logic, rather than calling `eshell-parse-argument', | 162 | ;; Is the output redirection Eshell-specific? We have our |
| 163 | ;; to avoid specifying here all the possible cars of | 163 | ;; own logic, rather than calling `eshell-parse-argument', |
| 164 | ;; parsed special references -- `get-buffer-create' etc. | 164 | ;; to avoid specifying here all the possible cars of |
| 165 | (forward-char -1) | 165 | ;; parsed special references -- `get-buffer-create' etc. |
| 166 | (let ((this-end | 166 | (forward-char -1) |
| 167 | (save-match-data | 167 | (let ((this-end |
| 168 | (cond ((looking-at "#<") | 168 | (save-match-data |
| 169 | (forward-char 1) | 169 | (cond ((looking-at "#<") |
| 170 | (1+ (eshell-find-delimiter ?\< ?\>))) | 170 | (forward-char 1) |
| 171 | ((and (looking-at "/\\S-+") | 171 | (1+ (eshell-find-delimiter ?\< ?\>))) |
| 172 | (assoc (match-string 0) | 172 | ((and (looking-at "/\\S-+") |
| 173 | eshell-virtual-targets)) | 173 | (assoc (match-string 0) |
| 174 | (match-end 0)))))) | 174 | eshell-virtual-targets)) |
| 175 | (cond ((and this-end end) | 175 | (match-end 0)))))) |
| 176 | (goto-char this-end)) | 176 | (cond ((and this-end end) |
| 177 | (this-end | 177 | (goto-char this-end)) |
| 178 | (goto-char this-end) | 178 | (this-end |
| 179 | (setq end (match-beginning 0))) | 179 | (goto-char this-end) |
| 180 | (t | 180 | (setq end (match-beginning 0))) |
| 181 | (setq end nil))))) | 181 | (t |
| 182 | ;; We've moved past all Eshell-specific output redirections | 182 | (setq end nil))))) |
| 183 | ;; we could find. If there is only whitespace left, then | 183 | ;; We've moved past all Eshell-specific output redirections |
| 184 | ;; `end' is right before redirections we should exclude; | 184 | ;; we could find. If there is only whitespace left, then |
| 185 | ;; otherwise, we must include everything. | 185 | ;; `end' is right before redirections we should exclude; |
| 186 | (unless (and end (skip-syntax-forward "\s" next-unmarked) | 186 | ;; otherwise, we must include everything. |
| 187 | (= next-unmarked (point))) | 187 | (unless (and end (skip-syntax-forward "\s" next-unmarked) |
| 188 | (setq end next-unmarked)) | 188 | (= next-unmarked (point))) |
| 189 | (let ((cmd (string-trim | 189 | (setq end next-unmarked)) |
| 190 | (buffer-substring-no-properties beg end)))) | 190 | (let ((cmd (string-trim |
| 191 | (goto-char end) | 191 | (buffer-substring-no-properties beg end)))) |
| 192 | ;; We must now drop the asterisks, unless quoted/escaped. | 192 | (goto-char end) |
| 193 | (with-temp-buffer | 193 | ;; We must now drop the asterisks, unless quoted/escaped. |
| 194 | (insert cmd) | 194 | (with-temp-buffer |
| 195 | (goto-char (point-min)) | 195 | (insert cmd) |
| 196 | (cl-loop | 196 | (goto-char (point-min)) |
| 197 | for next = (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)" t) | 197 | (cl-loop |
| 198 | while next do (forward-char -2) (delete-char 1)) | 198 | for next = (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)" t) |
| 199 | (eshell-finish-arg | 199 | while next do (forward-char -2) (delete-char 1)) |
| 200 | `(eshell-external-pipeline ,(buffer-string)))))))))) | 200 | (eshell-finish-arg |
| 201 | `(eshell-external-pipeline ,(buffer-string))))))))))) | ||
| 201 | 202 | ||
| 202 | (defun eshell-rewrite-external-pipeline (terms) | 203 | (defun eshell-rewrite-external-pipeline (terms) |
| 203 | "Rewrite an external pipeline in TERMS as parsed by | 204 | "Rewrite an external pipeline in TERMS as parsed by |
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el index e7b5eef11db..c3d3347e888 100644 --- a/lisp/eshell/esh-arg.el +++ b/lisp/eshell/esh-arg.el | |||
| @@ -49,6 +49,8 @@ yield the values intended." | |||
| 49 | (defvar eshell-arg-listified nil) | 49 | (defvar eshell-arg-listified nil) |
| 50 | (defvar eshell-nested-argument nil) | 50 | (defvar eshell-nested-argument nil) |
| 51 | (defvar eshell-current-quoted nil) | 51 | (defvar eshell-current-quoted nil) |
| 52 | (defvar eshell-current-argument-plain nil | ||
| 53 | "If non-nil, the current argument is \"plain\", and not part of a command.") | ||
| 52 | (defvar eshell-inside-quote-regexp nil) | 54 | (defvar eshell-inside-quote-regexp nil) |
| 53 | (defvar eshell-outside-quote-regexp nil) | 55 | (defvar eshell-outside-quote-regexp nil) |
| 54 | 56 | ||
| @@ -184,11 +186,6 @@ treated as a literal character." | |||
| 184 | (add-hook 'pcomplete-try-first-hook | 186 | (add-hook 'pcomplete-try-first-hook |
| 185 | #'eshell-complete-special-reference nil t))) | 187 | #'eshell-complete-special-reference nil t))) |
| 186 | 188 | ||
| 187 | (defun eshell-insert-buffer-name (buffer-name) | ||
| 188 | "Insert BUFFER-NAME into the current buffer at point." | ||
| 189 | (interactive "BName of buffer: ") | ||
| 190 | (insert-and-inherit "#<buffer " buffer-name ">")) | ||
| 191 | |||
| 192 | (defsubst eshell-escape-arg (string) | 189 | (defsubst eshell-escape-arg (string) |
| 193 | "Return STRING with the `escaped' property on it." | 190 | "Return STRING with the `escaped' property on it." |
| 194 | (if (stringp string) | 191 | (if (stringp string) |
| @@ -505,42 +502,6 @@ leaves point where it was." | |||
| 505 | (goto-char bound) | 502 | (goto-char bound) |
| 506 | (apply #'concat (nreverse strings)))))) | 503 | (apply #'concat (nreverse strings)))))) |
| 507 | 504 | ||
| 508 | (defun eshell-parse-special-reference () | ||
| 509 | "Parse a special syntax reference, of the form `#<args>'. | ||
| 510 | |||
| 511 | args := `type' `whitespace' `arbitrary-args' | `arbitrary-args' | ||
| 512 | type := \"buffer\" or \"process\" | ||
| 513 | arbitrary-args := any string of characters. | ||
| 514 | |||
| 515 | If the form has no `type', the syntax is parsed as if `type' were | ||
| 516 | \"buffer\"." | ||
| 517 | (when (and (not eshell-current-argument) | ||
| 518 | (not eshell-current-quoted) | ||
| 519 | (looking-at (rx "#<" (? (group (or "buffer" "process")) | ||
| 520 | space)))) | ||
| 521 | (let ((here (point))) | ||
| 522 | (goto-char (match-end 0)) ;; Go to the end of the match. | ||
| 523 | (let ((buffer-p (if (match-beginning 1) | ||
| 524 | (equal (match-string 1) "buffer") | ||
| 525 | t)) ; With no type keyword, assume we want a buffer. | ||
| 526 | (end (eshell-find-delimiter ?\< ?\>))) | ||
| 527 | (when (not end) | ||
| 528 | (when (match-beginning 1) | ||
| 529 | (goto-char (match-beginning 1))) | ||
| 530 | (throw 'eshell-incomplete "#<")) | ||
| 531 | (if (eshell-arg-delimiter (1+ end)) | ||
| 532 | (prog1 | ||
| 533 | (list (if buffer-p #'get-buffer-create #'get-process) | ||
| 534 | ;; FIXME: We should probably parse this as a | ||
| 535 | ;; real Eshell argument so that we get the | ||
| 536 | ;; benefits of quoting, variable-expansion, etc. | ||
| 537 | (string-trim-right | ||
| 538 | (replace-regexp-in-string | ||
| 539 | (rx "\\" (group anychar)) "\\1" | ||
| 540 | (buffer-substring-no-properties (point) end)))) | ||
| 541 | (goto-char (1+ end))) | ||
| 542 | (ignore (goto-char here))))))) | ||
| 543 | |||
| 544 | (defun eshell-parse-delimiter () | 505 | (defun eshell-parse-delimiter () |
| 545 | "Parse an argument delimiter, which is essentially a command operator." | 506 | "Parse an argument delimiter, which is essentially a command operator." |
| 546 | ;; this `eshell-operator' keyword gets parsed out by | 507 | ;; this `eshell-operator' keyword gets parsed out by |
| @@ -591,7 +552,38 @@ If no argument requested a splice, return nil." | |||
| 591 | (when splicep | 552 | (when splicep |
| 592 | grouped-args))) | 553 | grouped-args))) |
| 593 | 554 | ||
| 594 | ;;;_* Special ref completion | 555 | ;;; Special references |
| 556 | |||
| 557 | (defun eshell-parse-special-reference () | ||
| 558 | "Parse a special syntax reference, of the form `#<args>'. | ||
| 559 | |||
| 560 | args := `type' `whitespace' `arbitrary-args' | `arbitrary-args' | ||
| 561 | type := \"buffer\" or \"process\" | ||
| 562 | arbitrary-args := any number of Eshell arguments | ||
| 563 | |||
| 564 | If the form has no `type', the syntax is parsed as if `type' were | ||
| 565 | \"buffer\"." | ||
| 566 | (when (and (not eshell-current-argument) | ||
| 567 | (not eshell-current-quoted) | ||
| 568 | (looking-at (rx "#<" (? (group (or "buffer" "process")) | ||
| 569 | space)))) | ||
| 570 | (let ((here (point))) | ||
| 571 | (goto-char (match-end 0)) ;; Go to the end of the match. | ||
| 572 | (let ((buffer-p (if (match-beginning 1) | ||
| 573 | (equal (match-string 1) "buffer") | ||
| 574 | t)) ; With no type keyword, assume we want a buffer. | ||
| 575 | (end (eshell-find-delimiter ?\< ?\>))) | ||
| 576 | (when (not end) | ||
| 577 | (when (match-beginning 1) | ||
| 578 | (goto-char (match-beginning 1))) | ||
| 579 | (throw 'eshell-incomplete "#<")) | ||
| 580 | (if (eshell-arg-delimiter (1+ end)) | ||
| 581 | (prog1 | ||
| 582 | (cons (if buffer-p #'eshell-get-buffer #'get-process) | ||
| 583 | (let ((eshell-current-argument-plain t)) | ||
| 584 | (eshell-parse-arguments (point) end))) | ||
| 585 | (goto-char (1+ end))) | ||
| 586 | (ignore (goto-char here))))))) | ||
| 595 | 587 | ||
| 596 | (defun eshell-complete-special-reference () | 588 | (defun eshell-complete-special-reference () |
| 597 | "If there is a special reference, complete it." | 589 | "If there is a special reference, complete it." |
| @@ -627,5 +619,16 @@ If no argument requested a splice, return nil." | |||
| 627 | (throw 'pcomplete-completions | 619 | (throw 'pcomplete-completions |
| 628 | (all-completions pcomplete-stub all-results)))))) | 620 | (all-completions pcomplete-stub all-results)))))) |
| 629 | 621 | ||
| 622 | (defun eshell-get-buffer (buffer-or-name) | ||
| 623 | "Return the buffer specified by BUFFER-OR-NAME, creating a new one if needed. | ||
| 624 | This is equivalent to `get-buffer-create', but only accepts a | ||
| 625 | single argument." | ||
| 626 | (get-buffer-create buffer-or-name)) | ||
| 627 | |||
| 628 | (defun eshell-insert-buffer-name (buffer-name) | ||
| 629 | "Insert BUFFER-NAME into the current buffer at point." | ||
| 630 | (interactive "BName of buffer: ") | ||
| 631 | (insert-and-inherit "#<buffer " (eshell-quote-argument buffer-name) ">")) | ||
| 632 | |||
| 630 | (provide 'esh-arg) | 633 | (provide 'esh-arg) |
| 631 | ;;; esh-arg.el ends here | 634 | ;;; esh-arg.el ends here |
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el index d0f1e04e925..c29b96dd711 100644 --- a/lisp/eshell/esh-io.el +++ b/lisp/eshell/esh-io.el | |||
| @@ -196,7 +196,8 @@ describing the mode, e.g. for using with `eshell-get-target'.") | |||
| 196 | 196 | ||
| 197 | (defun eshell-parse-redirection () | 197 | (defun eshell-parse-redirection () |
| 198 | "Parse an output redirection, such as `2>' or `>&'." | 198 | "Parse an output redirection, such as `2>' or `>&'." |
| 199 | (when (not eshell-current-quoted) | 199 | (unless (or eshell-current-quoted |
| 200 | eshell-current-argument-plain) | ||
| 200 | (cond | 201 | (cond |
| 201 | ;; Copying a handle (e.g. `2>&1'). | 202 | ;; Copying a handle (e.g. `2>&1'). |
| 202 | ((looking-at (rx (? (group digit)) | 203 | ((looking-at (rx (? (group digit)) |
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index 3c946c22bdc..ea5896461b4 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el | |||
| @@ -227,23 +227,6 @@ and signal names." | |||
| 227 | 227 | ||
| 228 | (put 'eshell/kill 'eshell-no-numeric-conversions t) | 228 | (put 'eshell/kill 'eshell-no-numeric-conversions t) |
| 229 | 229 | ||
| 230 | (defun eshell-read-process-name (prompt) | ||
| 231 | "Read the name of a process from the minibuffer, using completion. | ||
| 232 | The prompt will be set to PROMPT." | ||
| 233 | (completing-read prompt | ||
| 234 | (mapcar | ||
| 235 | (lambda (proc) | ||
| 236 | (cons (process-name proc) t)) | ||
| 237 | (process-list)) | ||
| 238 | nil t)) | ||
| 239 | |||
| 240 | (defun eshell-insert-process (process) | ||
| 241 | "Insert the name of PROCESS into the current buffer at point." | ||
| 242 | (interactive | ||
| 243 | (list (get-process | ||
| 244 | (eshell-read-process-name "Name of process: ")))) | ||
| 245 | (insert-and-inherit "#<process " (process-name process) ">")) | ||
| 246 | |||
| 247 | (defsubst eshell-record-process-object (object) | 230 | (defsubst eshell-record-process-object (object) |
| 248 | "Record OBJECT as now running." | 231 | "Record OBJECT as now running." |
| 249 | (when (and eshell-subjob-messages | 232 | (when (and eshell-subjob-messages |
| @@ -695,5 +678,26 @@ everything." | |||
| 695 | ; ;; `eshell-resume-eval'. | 678 | ; ;; `eshell-resume-eval'. |
| 696 | ; (eshell--reset-after-signal "continue\n"))) | 679 | ; (eshell--reset-after-signal "continue\n"))) |
| 697 | 680 | ||
| 681 | ;;; Special references | ||
| 682 | |||
| 683 | (defun eshell-read-process-name (prompt) | ||
| 684 | "Read the name of a process from the minibuffer, using completion. | ||
| 685 | The prompt will be set to PROMPT." | ||
| 686 | (completing-read prompt | ||
| 687 | (mapcar | ||
| 688 | (lambda (proc) | ||
| 689 | (cons (process-name proc) t)) | ||
| 690 | (process-list)) | ||
| 691 | nil t)) | ||
| 692 | |||
| 693 | (defun eshell-insert-process (process) | ||
| 694 | "Insert the name of PROCESS into the current buffer at point." | ||
| 695 | (interactive | ||
| 696 | (list (get-process | ||
| 697 | (eshell-read-process-name "Name of process: ")))) | ||
| 698 | (insert-and-inherit "#<process " | ||
| 699 | (eshell-quote-argument (process-name process)) | ||
| 700 | ">")) | ||
| 701 | |||
| 698 | (provide 'esh-proc) | 702 | (provide 'esh-proc) |
| 699 | ;;; esh-proc.el ends here | 703 | ;;; esh-proc.el ends here |
diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el index bdffcd9b320..6984ec2de59 100644 --- a/test/lisp/eshell/em-extpipe-tests.el +++ b/test/lisp/eshell/em-extpipe-tests.el | |||
| @@ -55,7 +55,9 @@ | |||
| 55 | "temp\\([^>]\\|\\'\\)" temp | 55 | "temp\\([^>]\\|\\'\\)" temp |
| 56 | (string-replace | 56 | (string-replace |
| 57 | "#<buffer temp>" | 57 | "#<buffer temp>" |
| 58 | (concat "#<buffer " (buffer-name temp-buffer) ">") | 58 | (format "#<buffer %s>" |
| 59 | (eshell-quote-argument | ||
| 60 | (buffer-name temp-buffer))) | ||
| 59 | input)))) | 61 | input)))) |
| 60 | ,@body) | 62 | ,@body) |
| 61 | (when (buffer-name temp-buffer) | 63 | (when (buffer-name temp-buffer) |
| @@ -110,7 +112,7 @@ | |||
| 110 | '(progn | 112 | '(progn |
| 111 | (ignore | 113 | (ignore |
| 112 | (eshell-set-output-handle 1 'overwrite | 114 | (eshell-set-output-handle 1 'overwrite |
| 113 | (get-buffer-create "temp"))) | 115 | (eshell-get-buffer "temp"))) |
| 114 | (eshell-named-command "sh" | 116 | (eshell-named-command "sh" |
| 115 | (list "-c" "echo \"bar\" | rev")))) | 117 | (list "-c" "echo \"bar\" | rev")))) |
| 116 | (with-substitute-for-temp | 118 | (with-substitute-for-temp |
| @@ -133,7 +135,7 @@ | |||
| 133 | '(progn | 135 | '(progn |
| 134 | (ignore | 136 | (ignore |
| 135 | (eshell-set-output-handle 1 'overwrite | 137 | (eshell-set-output-handle 1 'overwrite |
| 136 | (get-buffer-create "quux"))) | 138 | (eshell-get-buffer "quux"))) |
| 137 | (ignore | 139 | (ignore |
| 138 | (eshell-set-output-handle 1 'append | 140 | (eshell-set-output-handle 1 'append |
| 139 | (get-process "other"))) | 141 | (get-process "other"))) |
diff --git a/test/lisp/eshell/esh-arg-tests.el b/test/lisp/eshell/esh-arg-tests.el index c883db3907f..0e07d107562 100644 --- a/test/lisp/eshell/esh-arg-tests.el +++ b/test/lisp/eshell/esh-arg-tests.el | |||
| @@ -118,7 +118,30 @@ treated literally, as a backslash and a newline." | |||
| 118 | (format "echo #<buffer %s>" (buffer-name)) | 118 | (format "echo #<buffer %s>" (buffer-name)) |
| 119 | (current-buffer)))) | 119 | (current-buffer)))) |
| 120 | 120 | ||
| 121 | (ert-deftest esh-arg-test/special-reference/special () | 121 | (ert-deftest esh-arg-test/special-reference/quoted () |
| 122 | "Test that '#<buffer \"foo bar\">' refers to the buffer \"foo bar\"." | ||
| 123 | (with-temp-buffer | ||
| 124 | (rename-buffer "foo bar" t) | ||
| 125 | (eshell-command-result-equal | ||
| 126 | (format "echo #<buffer \"%s\">" (buffer-name)) | ||
| 127 | (current-buffer)) | ||
| 128 | (eshell-command-result-equal | ||
| 129 | (format "echo #<buffer '%s'>" (buffer-name)) | ||
| 130 | (current-buffer)))) | ||
| 131 | |||
| 132 | (ert-deftest esh-arg-test/special-reference/var-expansion () | ||
| 133 | "Test that variable expansion inside special references works." | ||
| 134 | (with-temp-buffer | ||
| 135 | (rename-buffer "my-buffer" t) | ||
| 136 | (let ((eshell-test-value (buffer-name))) | ||
| 137 | (eshell-command-result-equal | ||
| 138 | "echo #<buffer $eshell-test-value>" | ||
| 139 | (current-buffer)) | ||
| 140 | (eshell-command-result-equal | ||
| 141 | "echo #<buffer \"$eshell-test-value\">" | ||
| 142 | (current-buffer))))) | ||
| 143 | |||
| 144 | (ert-deftest esh-arg-test/special-reference/special-characters () | ||
| 122 | "Test that \"#<...>\" works correctly when escaping special characters." | 145 | "Test that \"#<...>\" works correctly when escaping special characters." |
| 123 | (with-temp-buffer | 146 | (with-temp-buffer |
| 124 | (rename-buffer "<my buffer>" t) | 147 | (rename-buffer "<my buffer>" t) |