Subject: 29.0.50; [PATCH] When using $VAL[INDEX] in Eshell, allow symbols as the index
From: Jim Porter <[email-masked]>
To: [email-masked]
Date: Tue, 13 Sep 2022 16:23:26 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Eshell variable expansions let you use strings as indices, which will 
treat the outer value as an alist. For example:

   (setq foo '(("a" . 1) ("b" . 2)))
   M-x eshell
   ~ $ echo $foo[a]
   1

However, if the keys in the alist are symbols, that doesn't work:

   (setq foo '((a . 1) (b . 2)))
   M-x eshell
   ~ $ echo $foo[a]
   ;; no output

Attached is a patch to fix this. Now, in the latter case, you'd type:

   ~ $ echo $foo[#'a]
   ;; or
   ~ $ echo $foo[`a]

(Note: "#'a" looks like a sharp quote to denote a function, but the # is 
just Eshell's way of escaping the following single-quote. A bare 
single-quote is the start of a string literal in Eshell.)
From 0c60718681568f5512a639de80b99daf95f1fb9d Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Tue, 13 Sep 2022 16:14:00 -0700
Subject: [PATCH] Allow using a symbol as an index into an alist in Eshell

* lisp/eshell/esh-var.el (eshell-index-value): If INDEX is a symbol,
use 'assoc' for indexing.
* test/lisp/eshell/esh-var-tests.el (esh-var-test/interp-var-assoc)
(esh-var-test/quoted-interp-var-assoc): Add checks for indexing via
symbol.
---
 lisp/eshell/esh-var.el            | 35 ++++++++++++++++---------------
 test/lisp/eshell/esh-var-tests.el | 12 +++++++----
 2 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index a9df172e88..36e59cd5a4 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -646,23 +646,24 @@ eshell-index-value
   "Reference VALUE using the given INDEX."
   (when (and (stringp index) (get-text-property 0 'number index))
     (setq index (string-to-number index)))
-  (if (stringp index)
-      (cdr (assoc index value))
-    (cond
-     ((ring-p value)
-      (if (> index (ring-length value))
-	  (error "Index exceeds length of ring")
-	(ring-ref value index)))
-     ((listp value)
-      (if (> index (length value))
-	  (error "Index exceeds length of list")
-	(nth index value)))
-     ((vectorp value)
-      (if (> index (length value))
-	  (error "Index exceeds length of vector")
-	(aref value index)))
-     (t
-      (error "Invalid data type for indexing")))))
+  (if (integerp index)
+      (cond
+       ((ring-p value)
+        (if (> index (ring-length value))
+            (error "Index exceeds length of ring")
+          (ring-ref value index)))
+       ((listp value)
+        (if (> index (length value))
+            (error "Index exceeds length of list")
+          (nth index value)))
+       ((vectorp value)
+        (if (> index (length value))
+            (error "Index exceeds length of vector")
+          (aref value index)))
+       (t
+        (error "Invalid data type for indexing")))
+    ;; INDEX is some non-integer value, so treat VALUE as an alist.
+    (cdr (assoc index value))))
 
 ;;;_* Variable name completion
 
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index bebc57d359..cb5b1766bb 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -105,9 +105,11 @@ esh-var-test/interp-var-regexp-split-indices
 
 (ert-deftest esh-var-test/interp-var-assoc ()
   "Interpolate alist variable with index"
-  (let ((eshell-test-value '(("foo" . 1))))
+  (let ((eshell-test-value '(("foo" . 1) (bar . 2))))
     (eshell-command-result-equal "echo $eshell-test-value[foo]"
-                                 1)))
+                                 1)
+    (eshell-command-result-equal "echo $eshell-test-value[#'bar]"
+                                 2)))
 
 (ert-deftest esh-var-test/interp-var-length-list ()
   "Interpolate length of list variable"
@@ -257,9 +259,11 @@ esh-var-test/quoted-interp-var-regexp-split-indices
 
 (ert-deftest esh-var-test/quoted-interp-var-assoc ()
   "Interpolate alist variable with index inside double-quotes"
-  (let ((eshell-test-value '(("foo" . 1))))
+  (let ((eshell-test-value '(("foo" . 1) (bar . 2))))
     (eshell-command-result-equal "echo \"$eshell-test-value[foo]\""
-                                 "1")))
+                                 "1")
+    (eshell-command-result-equal "echo \"$eshell-test-value[#'bar]\""
+                                 "2")))
 
 (ert-deftest esh-var-test/quoted-interp-var-length-list ()
   "Interpolate length of list variable inside double-quotes"
-- 
2.25.1