aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/eshell/esh-arg.el24
-rw-r--r--lisp/eshell/esh-var.el27
-rw-r--r--test/lisp/eshell/esh-var-tests.el49
3 files changed, 91 insertions, 9 deletions
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 1a2f2a57e8e..e19481c4ba9 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -354,6 +354,30 @@ after are both returned."
354 (list 'eshell-escape-arg arg)))) 354 (list 'eshell-escape-arg arg))))
355 (goto-char (1+ end))))))) 355 (goto-char (1+ end)))))))
356 356
357(defun eshell-parse-inner-double-quote (bound)
358 "Parse the inner part of a double quoted string.
359The string to parse starts at point and ends at BOUND.
360
361If Eshell is currently parsing a quoted string and there are any
362backslash-escaped characters, this will return the unescaped
363string, updating point to BOUND. Otherwise, this returns nil and
364leaves point where it was."
365 (when eshell-current-quoted
366 (let (strings
367 (start (point))
368 (special-char
369 (rx-to-string
370 `(seq "\\" (group (any ,@eshell-special-chars-inside-quoting))))))
371 (while (re-search-forward special-char bound t)
372 (push (concat (buffer-substring start (match-beginning 0))
373 (match-string 1))
374 strings)
375 (setq start (match-end 0)))
376 (when strings
377 (push (buffer-substring start bound) strings)
378 (goto-char bound)
379 (apply #'concat (nreverse strings))))))
380
357(defun eshell-parse-special-reference () 381(defun eshell-parse-special-reference ()
358 "Parse a special syntax reference, of the form `#<args>'. 382 "Parse a special syntax reference, of the form `#<args>'.
359 383
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index ee3ffbc6475..24fdbde3cfb 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -440,18 +440,16 @@ Possible options are:
440 (let ((end (eshell-find-delimiter ?\{ ?\}))) 440 (let ((end (eshell-find-delimiter ?\{ ?\})))
441 (if (not end) 441 (if (not end)
442 (throw 'eshell-incomplete ?\{) 442 (throw 'eshell-incomplete ?\{)
443 (forward-char)
443 (prog1 444 (prog1
444 `(eshell-convert 445 `(eshell-convert
445 (eshell-command-to-value 446 (eshell-command-to-value
446 (eshell-as-subcommand 447 (eshell-as-subcommand
447 ,(eshell-parse-command (cons (1+ (point)) end))))) 448 ,(let ((subcmd (or (eshell-parse-inner-double-quote end)
449 (cons (point) end)))
450 (eshell-current-quoted nil))
451 (eshell-parse-command subcmd)))))
448 (goto-char (1+ end)))))) 452 (goto-char (1+ end))))))
449 ((memq (char-after) '(?\' ?\"))
450 (let ((name (if (eq (char-after) ?\')
451 (eshell-parse-literal-quote)
452 (eshell-parse-double-quote))))
453 (if name
454 `(eshell-get-variable ,(eval name) indices))))
455 ((eq (char-after) ?\<) 453 ((eq (char-after) ?\<)
456 (let ((end (eshell-find-delimiter ?\< ?\>))) 454 (let ((end (eshell-find-delimiter ?\< ?\>)))
457 (if (not end) 455 (if (not end)
@@ -463,7 +461,9 @@ Possible options are:
463 `(let ((eshell-current-handles 461 `(let ((eshell-current-handles
464 (eshell-create-handles ,temp 'overwrite))) 462 (eshell-create-handles ,temp 'overwrite)))
465 (progn 463 (progn
466 (eshell-as-subcommand ,(eshell-parse-command cmd)) 464 (eshell-as-subcommand
465 ,(let ((eshell-current-quoted nil))
466 (eshell-parse-command cmd)))
467 (ignore 467 (ignore
468 (nconc eshell-this-command-hook 468 (nconc eshell-this-command-hook
469 ;; Quote this lambda; it will be evaluated 469 ;; Quote this lambda; it will be evaluated
@@ -478,9 +478,18 @@ Possible options are:
478 (condition-case nil 478 (condition-case nil
479 `(eshell-command-to-value 479 `(eshell-command-to-value
480 (eshell-lisp-command 480 (eshell-lisp-command
481 ',(read (current-buffer)))) 481 ',(read (or (eshell-parse-inner-double-quote (point-max))
482 (current-buffer)))))
482 (end-of-file 483 (end-of-file
483 (throw 'eshell-incomplete ?\()))) 484 (throw 'eshell-incomplete ?\())))
485 ((looking-at (rx (or "'" "\"" "\\\"")))
486 (eshell-with-temp-command (or (eshell-parse-inner-double-quote (point-max))
487 (cons (point) (point-max)))
488 (let ((name (if (eq (char-after) ?\')
489 (eshell-parse-literal-quote)
490 (eshell-parse-double-quote))))
491 (when name
492 `(eshell-get-variable ,(eval name) indices)))))
484 ((assoc (char-to-string (char-after)) 493 ((assoc (char-to-string (char-after))
485 eshell-variable-aliases-list) 494 eshell-variable-aliases-list)
486 (forward-char) 495 (forward-char)
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index 8d803e5ca49..7ec6a975198 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -37,6 +37,25 @@
37 37
38;; Variable interpolation 38;; Variable interpolation
39 39
40(ert-deftest esh-var-test/interp-var ()
41 "Interpolate variable"
42 (should (equal (eshell-test-command-result "echo $user-login-name")
43 user-login-name)))
44
45(ert-deftest esh-var-test/interp-quoted-var ()
46 "Interpolate quoted variable"
47 (should (equal (eshell-test-command-result "echo $'user-login-name'")
48 user-login-name))
49 (should (equal (eshell-test-command-result "echo $\"user-login-name\"")
50 user-login-name)))
51
52(ert-deftest esh-var-test/interp-quoted-var-concat ()
53 "Interpolate and concat quoted variable"
54 (should (equal (eshell-test-command-result "echo $'user-login-name'-foo")
55 (concat user-login-name "-foo")))
56 (should (equal (eshell-test-command-result "echo $\"user-login-name\"-foo")
57 (concat user-login-name "-foo"))))
58
40(ert-deftest esh-var-test/interp-lisp () 59(ert-deftest esh-var-test/interp-lisp ()
41 "Interpolate Lisp form evaluation" 60 "Interpolate Lisp form evaluation"
42 (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6))) 61 (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6)))
@@ -79,6 +98,36 @@
79 (eshell-command-result-p "echo ${echo hi}-${*echo there}" 98 (eshell-command-result-p "echo ${echo hi}-${*echo there}"
80 "hi-there\n"))) 99 "hi-there\n")))
81 100
101(ert-deftest esh-var-test/quoted-interp-var ()
102 "Interpolate variable inside double-quotes"
103 (should (equal (eshell-test-command-result "echo \"$user-login-name\"")
104 user-login-name)))
105
106(ert-deftest esh-var-test/quoted-interp-quoted-var ()
107 "Interpolate quoted variable inside double-quotes"
108 (should (equal (eshell-test-command-result
109 "echo \"hi, $'user-login-name'\"")
110 (concat "hi, " user-login-name)))
111 (should (equal (eshell-test-command-result
112 "echo \"hi, $\\\"user-login-name\\\"\"")
113 (concat "hi, " user-login-name))))
114
115(ert-deftest esh-var-test/quoted-interp-lisp ()
116 "Interpolate Lisp form evaluation inside double-quotes"
117 (should (equal (eshell-test-command-result
118 "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"")
119 "hi there")))
120
121(ert-deftest esh-var-test/quoted-interp-cmd ()
122 "Interpolate command result inside double-quotes"
123 (should (equal (eshell-test-command-result
124 "echo \"hi ${echo \\\"there\\\"}\"")
125 "hi there")))
126
127(ert-deftest esh-var-test/quoted-interp-temp-cmd ()
128 "Interpolate command result redirected to temp file inside double-quotes"
129 (should (equal (eshell-test-command-result "cat \"$<echo hi>\"") "hi")))
130
82 131
83;; Built-in variables 132;; Built-in variables
84 133