aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Porter2022-09-25 21:47:26 -0700
committerJim Porter2022-10-17 18:48:52 -0700
commit7c41016fca5ab0638f1e2fed260e2ee41f3400c2 (patch)
tree11fe29e20ed60074578e2f2f10d47ed8bd65d404
parentf1caa10f04c980034f5ee6e0748cf3b03f460b2b (diff)
downloademacs-7c41016fca5ab0638f1e2fed260e2ee41f3400c2.tar.gz
emacs-7c41016fca5ab0638f1e2fed260e2ee41f3400c2.zip
Allow setting the values of variable aliases in Eshell
This makes commands like "COLUMNS=40 some-command" work as expected. * lisp/eshell/esh-cmd.el (eshell-subcommand-bindings): Remove 'process-environment' from here... * lisp/eshell/esh-var.el (eshell-var-initialize): ... and add to here, along with 'eshell-variable-aliases-list'. (eshell-inside-emacs): Convert to a 'defvar-local' to make it settable in a particular Eshell buffer. (eshell-variable-aliases-list): Make $?, $$, and $* read-only and update docstring. (eshell-set-variable): New function... (eshell-handle-local-variables, eshell/export, eshell/unset): ... use it. (eshell/set, pcomplete/eshell-mode/set): New functions. (eshell-get-variable): Get the variable alias's getter function when appropriate and use a safer method for checking function arity. * test/lisp/eshell/esh-var-tests.el (esh-var-test/set/env-var) (esh-var-test/set/symbol, esh-var-test/unset/env-var) (esh-var-test/unset/symbol, esh-var-test/setq, esh-var-test/export) (esh-var-test/local-variables, esh-var-test/alias/function) (esh-var-test/alias/function-pair, esh-var-test/alias/string) (esh-var-test/alias/string/prefer-lisp, esh-var-test/alias/symbol) (esh-var-test/alias/symbol-pair, esh-var-test/alias/export) (esh-var-test/alias/local-variables): New tests. * doc/misc/eshell.texi (Built-ins): Add 'set' and update 'unset' documentation. (Variables): Expand documentation of how to get/set variables.
-rw-r--r--doc/misc/eshell.texi49
-rw-r--r--lisp/eshell/esh-cmd.el4
-rw-r--r--lisp/eshell/esh-var.el141
-rw-r--r--test/lisp/eshell/esh-var-tests.el145
4 files changed, 293 insertions, 46 deletions
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 8036bbd83ae..21c1671a212 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -694,10 +694,18 @@ used for comparing lists of strings.
694This command can be loaded as part of the eshell-xtra module, which is 694This command can be loaded as part of the eshell-xtra module, which is
695disabled by default. 695disabled by default.
696 696
697@item set
698@cmindex set
699Set variable values, using the function @code{set} like a command
700(@pxref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}).
701A variable name can be a symbol, in which case it refers to a Lisp
702variable, or a string, referring to an environment variable
703(@pxref{Arguments}).
704
697@item setq 705@item setq
698@cmindex setq 706@cmindex setq
699Set variable values, using the function @code{setq} like a command. 707Set variable values, using the function @code{setq} like a command
700@xref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}. 708(@pxref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}).
701 709
702@item source 710@item source
703@cmindex source 711@cmindex source
@@ -743,7 +751,9 @@ disabled by default.
743 751
744@item unset 752@item unset
745@cmindex unset 753@cmindex unset
746Unset an environment variable. 754Unset one or more variables. As with @command{set}, a variable name
755can be a symbol, in which case it refers to a Lisp variable, or a
756string, referring to an environment variable.
747 757
748@item wait 758@item wait
749@cmindex wait 759@cmindex wait
@@ -881,12 +891,35 @@ For example, you could handle a subset of the options for the
881 891
882@node Variables 892@node Variables
883@section Variables 893@section Variables
884Since Eshell is just an Emacs @acronym{REPL}@footnote{ 894@vindex eshell-prefer-lisp-variables
895Since Eshell is a combination of an Emacs @acronym{REPL}@footnote{
885Short for ``Read-Eval-Print Loop''. 896Short for ``Read-Eval-Print Loop''.
886} 897} and a command shell, it can refer to variables from two different
887, it does not have its own scope, and simply stores variables the same 898sources: ordinary Emacs Lisp variables, as well as environment
888you would in an Elisp program. Eshell provides a command version of 899variables. By default, when using a variable in Eshell, it will first
889@code{setq} for convenience. 900look in the list of built-in variables, then in the list of
901environment variables, and finally in the list of Lisp variables. If
902you would prefer to use Lisp variables over environment variables, you
903can set @code{eshell-prefer-lisp-variables} to @code{t}.
904
905You can set variables in a few different ways. To set a Lisp
906variable, you can use the command @samp{setq @var{name} @var{value}},
907which works much like its Lisp counterpart (@pxref{Setting Variables,
908, , elisp, The Emacs Lisp Reference Manual}). To set an environment
909variable, use @samp{export @var{name}=@var{value}}. You can also use
910@samp{set @var{variable} @var{value}}, which sets a Lisp variable if
911@var{variable} is a symbol, or an environment variable if it's a
912string (@pxref{Arguments}). Finally, you can temporarily set
913environment variables for a single command with
914@samp{@var{name}=@var{value} @var{command} @dots{}}. This is
915equivalent to:
916
917@example
918@{
919 export @var{name}=@var{value}
920 @var{command} @dots{}
921@}
922@end example
890 923
891@subsection Built-in variables 924@subsection Built-in variables
892Eshell knows a few built-in variables: 925Eshell knows a few built-in variables:
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 3f3a1616eee..c5ceb3ffd17 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -261,9 +261,9 @@ the command."
261(defcustom eshell-subcommand-bindings 261(defcustom eshell-subcommand-bindings
262 '((eshell-in-subcommand-p t) 262 '((eshell-in-subcommand-p t)
263 (eshell-in-pipeline-p nil) 263 (eshell-in-pipeline-p nil)
264 (default-directory default-directory) 264 (default-directory default-directory))
265 (process-environment (eshell-copy-environment)))
266 "A list of `let' bindings for subcommand environments." 265 "A list of `let' bindings for subcommand environments."
266 :version "29.1" ; removed `process-environment'
267 :type 'sexp 267 :type 'sexp
268 :risky t) 268 :risky t)
269 269
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 3c09fc52fb5..caf143e1a1a 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -113,7 +113,7 @@
113(require 'pcomplete) 113(require 'pcomplete)
114(require 'ring) 114(require 'ring)
115 115
116(defconst eshell-inside-emacs (format "%s,eshell" emacs-version) 116(defvar-local eshell-inside-emacs (format "%s,eshell" emacs-version)
117 "Value for the `INSIDE_EMACS' environment variable.") 117 "Value for the `INSIDE_EMACS' environment variable.")
118 118
119(defgroup eshell-var nil 119(defgroup eshell-var nil
@@ -162,8 +162,8 @@ if they are quoted with a backslash."
162 (car (last eshell-last-arguments)) 162 (car (last eshell-last-arguments))
163 (eshell-apply-indices eshell-last-arguments 163 (eshell-apply-indices eshell-last-arguments
164 indices quoted)))) 164 indices quoted))))
165 ("?" eshell-last-command-status) 165 ("?" (eshell-last-command-status . nil))
166 ("$" eshell-last-command-result) 166 ("$" (eshell-last-command-result . nil))
167 167
168 ;; for em-alias.el and em-script.el 168 ;; for em-alias.el and em-script.el
169 ("0" eshell-command-name) 169 ("0" eshell-command-name)
@@ -176,7 +176,7 @@ if they are quoted with a backslash."
176 ("7" ,(lambda () (nth 6 eshell-command-arguments)) nil t) 176 ("7" ,(lambda () (nth 6 eshell-command-arguments)) nil t)
177 ("8" ,(lambda () (nth 7 eshell-command-arguments)) nil t) 177 ("8" ,(lambda () (nth 7 eshell-command-arguments)) nil t)
178 ("9" ,(lambda () (nth 8 eshell-command-arguments)) nil t) 178 ("9" ,(lambda () (nth 8 eshell-command-arguments)) nil t)
179 ("*" eshell-command-arguments)) 179 ("*" (eshell-command-arguments . nil)))
180 "This list provides aliasing for variable references. 180 "This list provides aliasing for variable references.
181Each member is of the following form: 181Each member is of the following form:
182 182
@@ -186,6 +186,11 @@ NAME defines the name of the variable, VALUE is a Lisp value used to
186compute the string value that will be returned when the variable is 186compute the string value that will be returned when the variable is
187accessed via the syntax `$NAME'. 187accessed via the syntax `$NAME'.
188 188
189If VALUE is a cons (GET . SET), then variable references to NAME
190will use GET to get the value, and SET to set it. GET and SET
191can be one of the forms described below. If SET is nil, the
192variable is read-only.
193
189If VALUE is a function, its behavior depends on the value of 194If VALUE is a function, its behavior depends on the value of
190SIMPLE-FUNCTION. If SIMPLE-FUNCTION is nil, call VALUE with two 195SIMPLE-FUNCTION. If SIMPLE-FUNCTION is nil, call VALUE with two
191arguments: the list of the indices that were used in the reference, 196arguments: the list of the indices that were used in the reference,
@@ -193,23 +198,30 @@ and either t or nil depending on whether or not the variable was
193quoted with double quotes. For example, if `NAME' were aliased 198quoted with double quotes. For example, if `NAME' were aliased
194to a function, a reference of `$NAME[10][20]' would result in that 199to a function, a reference of `$NAME[10][20]' would result in that
195function being called with the arguments `((\"10\") (\"20\"))' and 200function being called with the arguments `((\"10\") (\"20\"))' and
196nil. 201nil. If SIMPLE-FUNCTION is non-nil, call the function with no
197If SIMPLE-FUNCTION is non-nil, call the function with no arguments 202arguments and then pass its return value to `eshell-apply-indices'.
198and then pass its return value to `eshell-apply-indices'. 203
204When VALUE is a function, it's read-only by default. To make it
205writeable, use the (GET . SET) form described above. If SET is a
206function, it takes two arguments: a list of indices (currently
207always nil, but reserved for future enhancement), and the new
208value to set.
199 209
200If VALUE is a string, return the value for the variable with that 210If VALUE is a string, get/set the value for the variable with
201name in the current environment. If no variable with that name exists 211that name in the current environment. When getting the value, if
202in the environment, but if a symbol with that same name exists and has 212no variable with that name exists in the environment, but if a
203a value bound to it, return that symbol's value instead. You can 213symbol with that same name exists and has a value bound to it,
204prefer symbol values over environment values by setting the value 214return that symbol's value instead. You can prefer symbol values
205of `eshell-prefer-lisp-variables' to t. 215over environment values by setting the value of
216`eshell-prefer-lisp-variables' to t.
206 217
207If VALUE is a symbol, return the value bound to it. 218If VALUE is a symbol, get/set the value bound to it.
208 219
209If VALUE has any other type, signal an error. 220If VALUE has any other type, signal an error.
210 221
211Additionally, if COPY-TO-ENVIRONMENT is non-nil, the alias should be 222Additionally, if COPY-TO-ENVIRONMENT is non-nil, the alias should be
212copied (a.k.a. \"exported\") to the environment of created subprocesses." 223copied (a.k.a. \"exported\") to the environment of created subprocesses."
224 :version "29.1"
213 :type '(repeat (list string sexp 225 :type '(repeat (list string sexp
214 (choice (const :tag "Copy to environment" t) 226 (choice (const :tag "Copy to environment" t)
215 (const :tag "Use only in Eshell" nil)) 227 (const :tag "Use only in Eshell" nil))
@@ -234,6 +246,11 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
234 ;; changing a variable will affect all of Emacs. 246 ;; changing a variable will affect all of Emacs.
235 (unless eshell-modify-global-environment 247 (unless eshell-modify-global-environment
236 (setq-local process-environment (eshell-copy-environment))) 248 (setq-local process-environment (eshell-copy-environment)))
249 (setq-local eshell-subcommand-bindings
250 (append
251 '((process-environment (eshell-copy-environment))
252 (eshell-variable-aliases-list eshell-variable-aliases-list))
253 eshell-subcommand-bindings))
237 254
238 (setq-local eshell-special-chars-inside-quoting 255 (setq-local eshell-special-chars-inside-quoting
239 (append eshell-special-chars-inside-quoting '(?$))) 256 (append eshell-special-chars-inside-quoting '(?$)))
@@ -282,9 +299,9 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
282 (while (string-match setvar command) 299 (while (string-match setvar command)
283 (nconc 300 (nconc
284 l (list 301 l (list
285 (list 'setenv (match-string 1 command) 302 (list 'eshell-set-variable
286 (match-string 2 command) 303 (match-string 1 command)
287 (= (length (match-string 2 command)) 0)))) 304 (match-string 2 command))))
288 (setq command (eshell-stringify (car args)) 305 (setq command (eshell-stringify (car args))
289 args (cdr args))) 306 args (cdr args)))
290 (cdr l)) 307 (cdr l))
@@ -328,12 +345,11 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
328 345
329(defun eshell/export (&rest sets) 346(defun eshell/export (&rest sets)
330 "This alias allows the `export' command to act as bash users expect." 347 "This alias allows the `export' command to act as bash users expect."
331 (while sets 348 (dolist (set sets)
332 (if (and (stringp (car sets)) 349 (when (and (stringp set)
333 (string-match "^\\([^=]+\\)=\\(.*\\)" (car sets))) 350 (string-match "^\\([^=]+\\)=\\(.*\\)" set))
334 (setenv (match-string 1 (car sets)) 351 (eshell-set-variable (match-string 1 set)
335 (match-string 2 (car sets)))) 352 (match-string 2 set)))))
336 (setq sets (cdr sets))))
337 353
338(defun pcomplete/eshell-mode/export () 354(defun pcomplete/eshell-mode/export ()
339 "Completion function for Eshell's `export'." 355 "Completion function for Eshell's `export'."
@@ -343,16 +359,28 @@ This function is explicit for adding to `eshell-parse-argument-hook'."
343 (eshell-envvar-names))))) 359 (eshell-envvar-names)))))
344 360
345(defun eshell/unset (&rest args) 361(defun eshell/unset (&rest args)
346 "Unset an environment variable." 362 "Unset one or more variables.
347 (while args 363This is equivalent to calling `eshell/set' for all of ARGS with
348 (if (stringp (car args)) 364the values of nil for each."
349 (setenv (car args) nil t)) 365 (dolist (arg args)
350 (setq args (cdr args)))) 366 (eshell-set-variable arg nil)))
351 367
352(defun pcomplete/eshell-mode/unset () 368(defun pcomplete/eshell-mode/unset ()
353 "Completion function for Eshell's `unset'." 369 "Completion function for Eshell's `unset'."
354 (while (pcomplete-here (eshell-envvar-names)))) 370 (while (pcomplete-here (eshell-envvar-names))))
355 371
372(defun eshell/set (&rest args)
373 "Allow command-ish use of `set'."
374 (let (last-value)
375 (while args
376 (setq last-value (eshell-set-variable (car args) (cadr args))
377 args (cddr args)))
378 last-value))
379
380(defun pcomplete/eshell-mode/set ()
381 "Completion function for Eshell's `set'."
382 (while (pcomplete-here (eshell-envvar-names))))
383
356(defun eshell/setq (&rest args) 384(defun eshell/setq (&rest args)
357 "Allow command-ish use of `setq'." 385 "Allow command-ish use of `setq'."
358 (let (last-value) 386 (let (last-value)
@@ -566,18 +594,21 @@ INDICES is a list of index-lists (see `eshell-parse-indices').
566If QUOTED is non-nil, this was invoked inside double-quotes." 594If QUOTED is non-nil, this was invoked inside double-quotes."
567 (if-let ((alias (assoc name eshell-variable-aliases-list))) 595 (if-let ((alias (assoc name eshell-variable-aliases-list)))
568 (let ((target (nth 1 alias))) 596 (let ((target (nth 1 alias)))
597 (when (and (not (functionp target))
598 (consp target))
599 (setq target (car target)))
569 (cond 600 (cond
570 ((functionp target) 601 ((functionp target)
571 (if (nth 3 alias) 602 (if (nth 3 alias)
572 (eshell-apply-indices (funcall target) indices quoted) 603 (eshell-apply-indices (funcall target) indices quoted)
573 (condition-case nil 604 (let ((max-arity (cdr (func-arity target))))
574 (funcall target indices quoted) 605 (if (or (eq max-arity 'many) (>= max-arity 2))
575 (wrong-number-of-arguments 606 (funcall target indices quoted)
576 (display-warning 607 (display-warning
577 :warning (concat "Function for `eshell-variable-aliases-list' " 608 :warning (concat "Function for `eshell-variable-aliases-list' "
578 "entry should accept two arguments: INDICES " 609 "entry should accept two arguments: INDICES "
579 "and QUOTED.'")) 610 "and QUOTED.'"))
580 (funcall target indices))))) 611 (funcall target indices)))))
581 ((symbolp target) 612 ((symbolp target)
582 (eshell-apply-indices (symbol-value target) indices quoted)) 613 (eshell-apply-indices (symbol-value target) indices quoted))
583 (t 614 (t
@@ -594,6 +625,44 @@ If QUOTED is non-nil, this was invoked inside double-quotes."
594 (getenv name))) 625 (getenv name)))
595 indices quoted))) 626 indices quoted)))
596 627
628(defun eshell-set-variable (name value)
629 "Set the variable named NAME to VALUE.
630NAME can be a string (in which case it refers to an environment
631variable or variable alias) or a symbol (in which case it refers
632to a Lisp variable)."
633 (if-let ((alias (assoc name eshell-variable-aliases-list)))
634 (let ((target (nth 1 alias)))
635 (cond
636 ((functionp target)
637 (setq target nil))
638 ((consp target)
639 (setq target (cdr target))))
640 (cond
641 ((functionp target)
642 (funcall target nil value))
643 ((null target)
644 (unless eshell-in-subcommand-p
645 (error "Variable `%s' is not settable" (eshell-stringify name)))
646 (push `(,name ,(lambda () value) t t)
647 eshell-variable-aliases-list)
648 value)
649 ;; Since getting a variable alias with a string target and
650 ;; `eshell-prefer-lisp-variables' non-nil gets the
651 ;; corresponding Lisp variable, make sure setting does the
652 ;; same.
653 ((and eshell-prefer-lisp-variables
654 (stringp target))
655 (eshell-set-variable (intern target) value))
656 (t
657 (eshell-set-variable target value))))
658 (cond
659 ((stringp name)
660 (setenv name value))
661 ((symbolp name)
662 (set name value))
663 (t
664 (error "Unknown variable `%s'" (eshell-stringify name))))))
665
597(defun eshell-apply-indices (value indices &optional quoted) 666(defun eshell-apply-indices (value indices &optional quoted)
598 "Apply to VALUE all of the given INDICES, returning the sub-result. 667 "Apply to VALUE all of the given INDICES, returning the sub-result.
599The format of INDICES is: 668The format of INDICES is:
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index ad695e45d7e..a7ac52ed24a 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -25,6 +25,7 @@
25 25
26(require 'ert) 26(require 'ert)
27(require 'esh-mode) 27(require 'esh-mode)
28(require 'esh-var)
28(require 'eshell) 29(require 'eshell)
29 30
30(require 'eshell-tests-helpers 31(require 'eshell-tests-helpers
@@ -440,6 +441,150 @@ inside double-quotes"
440 "000")) 441 "000"))
441 442
442 443
444;; Variable-related commands
445
446(ert-deftest esh-var-test/set/env-var ()
447 "Test that `set' with a string variable name sets an environment variable."
448 (with-temp-eshell
449 (eshell-match-command-output "set VAR hello" "hello\n")
450 (should (equal (getenv "VAR") "hello")))
451 (should-not (equal (getenv "VAR") "hello")))
452
453(ert-deftest esh-var-test/set/symbol ()
454 "Test that `set' with a symbol variable name sets a Lisp variable."
455 (let (eshell-test-value)
456 (eshell-command-result-equal "set #'eshell-test-value hello"
457 "hello")
458 (should (equal eshell-test-value "hello"))))
459
460(ert-deftest esh-var-test/unset/env-var ()
461 "Test that `unset' with a string variable name unsets an env var."
462 (let ((process-environment (cons "VAR=value" process-environment)))
463 (with-temp-eshell
464 (eshell-match-command-output "unset VAR" "\\`\\'")
465 (should (equal (getenv "VAR") nil)))
466 (should (equal (getenv "VAR") "value"))))
467
468(ert-deftest esh-var-test/unset/symbol ()
469 "Test that `unset' with a symbol variable name unsets a Lisp variable."
470 (let ((eshell-test-value "value"))
471 (eshell-command-result-equal "unset #'eshell-test-value" nil)
472 (should (equal eshell-test-value nil))))
473
474(ert-deftest esh-var-test/setq ()
475 "Test that `setq' sets Lisp variables."
476 (let (eshell-test-value)
477 (eshell-command-result-equal "setq eshell-test-value hello"
478 "hello")
479 (should (equal eshell-test-value "hello"))))
480
481(ert-deftest esh-var-test/export ()
482 "Test that `export' sets environment variables."
483 (with-temp-eshell
484 (eshell-match-command-output "export VAR=hello" "\\`\\'")
485 (should (equal (getenv "VAR") "hello"))))
486
487(ert-deftest esh-var-test/local-variables ()
488 "Test that \"VAR=value command\" temporarily sets variables."
489 (with-temp-eshell
490 (push "VAR=value" process-environment)
491 (eshell-match-command-output "VAR=hello env" "VAR=hello\n")
492 (should (equal (getenv "VAR") "value"))))
493
494
495;; Variable aliases
496
497(ert-deftest esh-var-test/alias/function ()
498 "Test using a variable alias defined as a function."
499 (with-temp-eshell
500 (push `("ALIAS" ,(lambda () "value") nil t) eshell-variable-aliases-list)
501 (eshell-match-command-output "echo $ALIAS" "value\n")
502 (eshell-match-command-output "set ALIAS hello"
503 "Variable `ALIAS' is not settable\n"
504 nil t)))
505
506(ert-deftest esh-var-test/alias/function-pair ()
507 "Test using a variable alias defined as a pair of getter/setter functions."
508 (with-temp-eshell
509 (let ((eshell-test-value "value"))
510 (push `("ALIAS" (,(lambda () eshell-test-value)
511 . (lambda (_ value)
512 (setq eshell-test-value (upcase value))))
513 nil t)
514 eshell-variable-aliases-list)
515 (eshell-match-command-output "echo $ALIAS" "value\n")
516 (eshell-match-command-output "set ALIAS hello" "HELLO\n")
517 (should (equal eshell-test-value "HELLO")))))
518
519(ert-deftest esh-var-test/alias/string ()
520 "Test using a variable alias defined as a string.
521This should get/set the aliased environment variable."
522 (with-temp-eshell
523 (let ((eshell-test-value "lisp-value"))
524 (push "eshell-test-value=env-value" process-environment)
525 (push `("ALIAS" "eshell-test-value") eshell-variable-aliases-list)
526 (eshell-match-command-output "echo $ALIAS" "env-value\n")
527 (eshell-match-command-output "set ALIAS hello" "hello\n")
528 (should (equal (getenv "eshell-test-value") "hello"))
529 (should (equal eshell-test-value "lisp-value")))))
530
531(ert-deftest esh-var-test/alias/string/prefer-lisp ()
532 "Test using a variable alias defined as a string.
533This sets `eshell-prefer-lisp-variables' to t and should get/set
534the aliased Lisp variable."
535 (with-temp-eshell
536 (let ((eshell-test-value "lisp-value")
537 (eshell-prefer-lisp-variables t))
538 (push "eshell-test-value=env-value" process-environment)
539 (push `("ALIAS" "eshell-test-value") eshell-variable-aliases-list)
540 (eshell-match-command-output "echo $ALIAS" "lisp-value\n")
541 (eshell-match-command-output "set ALIAS hello" "hello\n")
542 (should (equal (car process-environment) "eshell-test-value=env-value"))
543 (should (equal eshell-test-value "hello")))))
544
545(ert-deftest esh-var-test/alias/symbol ()
546 "Test using a variable alias defined as a symbol.
547This should get/set the value bound to the symbol."
548 (with-temp-eshell
549 (let ((eshell-test-value "value"))
550 (push '("ALIAS" eshell-test-value) eshell-variable-aliases-list)
551 (eshell-match-command-output "echo $ALIAS" "value\n")
552 (eshell-match-command-output "set ALIAS hello" "hello\n")
553 (should (equal eshell-test-value "hello")))))
554
555(ert-deftest esh-var-test/alias/symbol-pair ()
556 "Test using a variable alias defined as a pair of symbols.
557This should get the value bound to the symbol, but fail to set
558it, since the setter is nil."
559 (with-temp-eshell
560 (let ((eshell-test-value "value"))
561 (push '("ALIAS" (eshell-test-value . nil)) eshell-variable-aliases-list)
562 (eshell-match-command-output "echo $ALIAS" "value\n")
563 (eshell-match-command-output "set ALIAS hello"
564 "Variable `ALIAS' is not settable\n"
565 nil t))))
566
567(ert-deftest esh-var-test/alias/export ()
568 "Test that `export' properly sets variable aliases."
569 (with-temp-eshell
570 (let ((eshell-test-value "value"))
571 (push `("ALIAS" (,(lambda () eshell-test-value)
572 . (lambda (_ value) (setq eshell-test-value value)))
573 nil t)
574 eshell-variable-aliases-list)
575 (eshell-match-command-output "export ALIAS=hello" "\\`\\'")
576 (should (equal eshell-test-value "hello")))))
577
578(ert-deftest esh-var-test/alias/local-variables ()
579 "Test that \"VAR=value cmd\" temporarily sets read-only variable aliases."
580 (with-temp-eshell
581 (let ((eshell-test-value "value"))
582 (push `("ALIAS" ,(lambda () eshell-test-value) t t)
583 eshell-variable-aliases-list)
584 (eshell-match-command-output "ALIAS=hello env" "ALIAS=hello\n")
585 (should (equal eshell-test-value "value")))))
586
587
443;; Built-in variables 588;; Built-in variables
444 589
445(ert-deftest esh-var-test/lines-var () 590(ert-deftest esh-var-test/lines-var ()