summaryrefslogtreecommitdiff
path: root/lisp/eshell/esh-var.el
diff options
context:
space:
mode:
authorJim Porter <jporterbugs@gmail.com>2022-03-01 18:36:08 -0800
committerLars Ingebrigtsen <larsi@gnus.org>2022-03-03 14:59:33 +0100
commit990f36fa108092c8b93692bb80c6fbd0b6b8f391 (patch)
tree726029d61639874422e89f5f1cd1be30c5aa7752 /lisp/eshell/esh-var.el
parentcccee7e840102488e01f9bb7c2220392d358f4f0 (diff)
downloademacs-990f36fa108092c8b93692bb80c6fbd0b6b8f391.tar.gz
emacs-990f36fa108092c8b93692bb80c6fbd0b6b8f391.tar.bz2
emacs-990f36fa108092c8b93692bb80c6fbd0b6b8f391.zip
Fix parsing of indices in Eshell expansions
Previously, more-complex index expansions, like '$var[":" 0]' or '$var[$(expr) 0]' failed to parse correctly. * lisp/eshell/esh-var.el (Commentary): Clarify indexing and length expansions. (eshell-parse-indices): Expand docstring and support parsing inside double-quotes. (eshell-eval-indices): New function. (eshell-parse-variable): Use it. * test/lisp/eshell/esh-var-tests.el (eshell-test-value): New defvar. (esh-var-test/interp-var-indices, (esh-var-test/interp-var-split-indices) (esh-var-test/interp-var-string-split-indices) (esh-var-test/interp-var-regexp-split-indices) (esh-var-test/interp-var-assoc, esh-var-test/interp-var-length-list) (esh-var-test/interp-var-length-string) (esh-var-test/interp-var-length-alist) (esh-var-test/quoted-interp-var-indices) (esh-var-test/quoted-interp-var-split-indices) (esh-var-test/quoted-interp-var-string-split-indices) (esh-var-test/quoted-interp-var-regexp-split-indices) (esh-var-test/quoted-interp-var-assoc) (esh-var-test/quoted-interp-var-length-list) (esh-var-test/quoted-interp-var-length-string) (esh-var-test/quoted-interp-var-length-alist): New tests. * doc/misc/eshell.texi (Dollars Expansion): Expand and reword documentation for indexing and length expansions.
Diffstat (limited to 'lisp/eshell/esh-var.el')
-rw-r--r--lisp/eshell/esh-var.el59
1 files changed, 31 insertions, 28 deletions
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 24fdbde3cfb..6f08a3fbc45 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -39,11 +39,6 @@
;;
;; Only "MYVAR" is part of the variable name in this case.
;;
-;; $#VARIABLE
-;;
-;; Returns the length of the value of VARIABLE. This could also be
-;; done using the `length' Lisp function.
-;;
;; $(lisp)
;;
;; Returns result of Lisp evaluation. Note: Used alone like this, it
@@ -61,38 +56,36 @@
;; Evaluates an eshell subcommand, redirecting the output to a
;; temporary file, and returning the file name.
;;
-;; $ANYVAR[10]
+;; $EXPR[10]
;;
-;; Return the 10th element of ANYVAR. If ANYVAR's value is a string,
-;; it will be split in order to make it a list. The splitting will
-;; occur at whitespace.
+;; Return the 10th element of $EXPR, which can be any dollar
+;; expression. If $EXPR's value is a string, it will be split in
+;; order to make it a list. The splitting will occur at whitespace.
;;
-;; $ANYVAR[: 10]
+;; $EXPR[10 20]
;;
-;; As above, except that splitting occurs at the colon now.
+;; As above, but instead of returning a single element, it now returns a
+;; list of two elements.
;;
-;; $ANYVAR[: 10 20]
+;; $EXPR[: 10]
;;
-;; As above, but instead of returning just a string, it now returns a
-;; list of two strings. If the result is being interpolated into a
-;; larger string, this list will be flattened into one big string,
-;; with each element separated by a space.
+;; Like $EXPR[10], except that splitting occurs at the colon now.
;;
-;; $ANYVAR["\\\\" 10]
+;; $EXPR["\\\\" 10]
;;
;; Separate on backslash characters. Actually, the first argument --
;; if it doesn't have the form of a number, or a plain variable name
;; -- can be any regular expression. So to split on numbers, use
-;; '$ANYVAR["[0-9]+" 10 20]'.
+;; '$EXPR["[0-9]+" 10 20]'.
;;
-;; $ANYVAR[hello]
+;; $EXPR[hello]
;;
-;; Calls `assoc' on ANYVAR with 'hello', expecting it to be an alist.
+;; Calls `assoc' on $EXPR with 'hello', expecting it to be an alist.
;;
-;; $#ANYVAR[hello]
+;; $#EXPR
;;
-;; Returns the length of the cdr of the element of ANYVAR who car is
-;; equal to "hello".
+;; Returns the length of the value of $EXPR. This could also be
+;; done using the `length' Lisp function.
;;
;; There are also a few special variables defined by Eshell. '$$' is
;; the value of the last command (t or nil, in the case of an external
@@ -416,7 +409,7 @@ process any indices that come after the variable reference."
(eshell-parse-indices))
;; This is an expression that will be evaluated by `eshell-do-eval',
;; which only support let-binding of dynamically-scoped vars
- value `(let ((indices ',indices)) ,value))
+ value `(let ((indices (eshell-eval-indices ',indices))) ,value))
(if get-len
`(length ,value)
value)))
@@ -504,19 +497,29 @@ Possible options are:
(defvar eshell-glob-function)
(defun eshell-parse-indices ()
- "Parse and return a list of list of indices."
+ "Parse and return a list of index-lists.
+
+For example, \"[0 1][2]\" becomes:
+ ((\"0\" \"1\") (\"2\")."
(let (indices)
(while (eq (char-after) ?\[)
(let ((end (eshell-find-delimiter ?\[ ?\])))
(if (not end)
(throw 'eshell-incomplete ?\[)
(forward-char)
- (let (eshell-glob-function)
- (setq indices (cons (eshell-parse-arguments (point) end)
- indices)))
+ (eshell-with-temp-command (or (eshell-parse-inner-double-quote end)
+ (cons (point) end))
+ (let (eshell-glob-function (eshell-current-quoted nil))
+ (setq indices (cons (eshell-parse-arguments
+ (point-min) (point-max))
+ indices))))
(goto-char (1+ end)))))
(nreverse indices)))
+(defun eshell-eval-indices (indices)
+ "Evaluate INDICES, a list of index-lists generated by `eshell-parse-indices'."
+ (mapcar (lambda (i) (mapcar #'eval i)) indices))
+
(defun eshell-get-variable (name &optional indices)
"Get the value for the variable NAME."
(let* ((alias (assoc name eshell-variable-aliases-list))