diff options
| author | Jim Porter | 2022-09-25 21:47:26 -0700 |
|---|---|---|
| committer | Jim Porter | 2022-10-17 18:48:52 -0700 |
| commit | 7c41016fca5ab0638f1e2fed260e2ee41f3400c2 (patch) | |
| tree | 11fe29e20ed60074578e2f2f10d47ed8bd65d404 | |
| parent | f1caa10f04c980034f5ee6e0748cf3b03f460b2b (diff) | |
| download | emacs-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.texi | 49 | ||||
| -rw-r--r-- | lisp/eshell/esh-cmd.el | 4 | ||||
| -rw-r--r-- | lisp/eshell/esh-var.el | 141 | ||||
| -rw-r--r-- | test/lisp/eshell/esh-var-tests.el | 145 |
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. | |||
| 694 | This command can be loaded as part of the eshell-xtra module, which is | 694 | This command can be loaded as part of the eshell-xtra module, which is |
| 695 | disabled by default. | 695 | disabled by default. |
| 696 | 696 | ||
| 697 | @item set | ||
| 698 | @cmindex set | ||
| 699 | Set variable values, using the function @code{set} like a command | ||
| 700 | (@pxref{Setting Variables,,, elisp, GNU Emacs Lisp Reference Manual}). | ||
| 701 | A variable name can be a symbol, in which case it refers to a Lisp | ||
| 702 | variable, or a string, referring to an environment variable | ||
| 703 | (@pxref{Arguments}). | ||
| 704 | |||
| 697 | @item setq | 705 | @item setq |
| 698 | @cmindex setq | 706 | @cmindex setq |
| 699 | Set variable values, using the function @code{setq} like a command. | 707 | Set 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 |
| 746 | Unset an environment variable. | 754 | Unset one or more variables. As with @command{set}, a variable name |
| 755 | can be a symbol, in which case it refers to a Lisp variable, or a | ||
| 756 | string, 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 |
| 884 | Since Eshell is just an Emacs @acronym{REPL}@footnote{ | 894 | @vindex eshell-prefer-lisp-variables |
| 895 | Since Eshell is a combination of an Emacs @acronym{REPL}@footnote{ | ||
| 885 | Short for ``Read-Eval-Print Loop''. | 896 | Short 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 | 898 | sources: ordinary Emacs Lisp variables, as well as environment |
| 888 | you would in an Elisp program. Eshell provides a command version of | 899 | variables. By default, when using a variable in Eshell, it will first |
| 889 | @code{setq} for convenience. | 900 | look in the list of built-in variables, then in the list of |
| 901 | environment variables, and finally in the list of Lisp variables. If | ||
| 902 | you would prefer to use Lisp variables over environment variables, you | ||
| 903 | can set @code{eshell-prefer-lisp-variables} to @code{t}. | ||
| 904 | |||
| 905 | You can set variables in a few different ways. To set a Lisp | ||
| 906 | variable, you can use the command @samp{setq @var{name} @var{value}}, | ||
| 907 | which works much like its Lisp counterpart (@pxref{Setting Variables, | ||
| 908 | , , elisp, The Emacs Lisp Reference Manual}). To set an environment | ||
| 909 | variable, 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 | ||
| 912 | string (@pxref{Arguments}). Finally, you can temporarily set | ||
| 913 | environment variables for a single command with | ||
| 914 | @samp{@var{name}=@var{value} @var{command} @dots{}}. This is | ||
| 915 | equivalent 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 |
| 892 | Eshell knows a few built-in variables: | 925 | Eshell 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. |
| 181 | Each member is of the following form: | 181 | Each 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 | |||
| 186 | compute the string value that will be returned when the variable is | 186 | compute the string value that will be returned when the variable is |
| 187 | accessed via the syntax `$NAME'. | 187 | accessed via the syntax `$NAME'. |
| 188 | 188 | ||
| 189 | If VALUE is a cons (GET . SET), then variable references to NAME | ||
| 190 | will use GET to get the value, and SET to set it. GET and SET | ||
| 191 | can be one of the forms described below. If SET is nil, the | ||
| 192 | variable is read-only. | ||
| 193 | |||
| 189 | If VALUE is a function, its behavior depends on the value of | 194 | If VALUE is a function, its behavior depends on the value of |
| 190 | SIMPLE-FUNCTION. If SIMPLE-FUNCTION is nil, call VALUE with two | 195 | SIMPLE-FUNCTION. If SIMPLE-FUNCTION is nil, call VALUE with two |
| 191 | arguments: the list of the indices that were used in the reference, | 196 | arguments: 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 | |||
| 193 | quoted with double quotes. For example, if `NAME' were aliased | 198 | quoted with double quotes. For example, if `NAME' were aliased |
| 194 | to a function, a reference of `$NAME[10][20]' would result in that | 199 | to a function, a reference of `$NAME[10][20]' would result in that |
| 195 | function being called with the arguments `((\"10\") (\"20\"))' and | 200 | function being called with the arguments `((\"10\") (\"20\"))' and |
| 196 | nil. | 201 | nil. If SIMPLE-FUNCTION is non-nil, call the function with no |
| 197 | If SIMPLE-FUNCTION is non-nil, call the function with no arguments | 202 | arguments and then pass its return value to `eshell-apply-indices'. |
| 198 | and then pass its return value to `eshell-apply-indices'. | 203 | |
| 204 | When VALUE is a function, it's read-only by default. To make it | ||
| 205 | writeable, use the (GET . SET) form described above. If SET is a | ||
| 206 | function, it takes two arguments: a list of indices (currently | ||
| 207 | always nil, but reserved for future enhancement), and the new | ||
| 208 | value to set. | ||
| 199 | 209 | ||
| 200 | If VALUE is a string, return the value for the variable with that | 210 | If VALUE is a string, get/set the value for the variable with |
| 201 | name in the current environment. If no variable with that name exists | 211 | that name in the current environment. When getting the value, if |
| 202 | in the environment, but if a symbol with that same name exists and has | 212 | no variable with that name exists in the environment, but if a |
| 203 | a value bound to it, return that symbol's value instead. You can | 213 | symbol with that same name exists and has a value bound to it, |
| 204 | prefer symbol values over environment values by setting the value | 214 | return that symbol's value instead. You can prefer symbol values |
| 205 | of `eshell-prefer-lisp-variables' to t. | 215 | over environment values by setting the value of |
| 216 | `eshell-prefer-lisp-variables' to t. | ||
| 206 | 217 | ||
| 207 | If VALUE is a symbol, return the value bound to it. | 218 | If VALUE is a symbol, get/set the value bound to it. |
| 208 | 219 | ||
| 209 | If VALUE has any other type, signal an error. | 220 | If VALUE has any other type, signal an error. |
| 210 | 221 | ||
| 211 | Additionally, if COPY-TO-ENVIRONMENT is non-nil, the alias should be | 222 | Additionally, if COPY-TO-ENVIRONMENT is non-nil, the alias should be |
| 212 | copied (a.k.a. \"exported\") to the environment of created subprocesses." | 223 | copied (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 | 363 | This is equivalent to calling `eshell/set' for all of ARGS with |
| 348 | (if (stringp (car args)) | 364 | the 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'). | |||
| 566 | If QUOTED is non-nil, this was invoked inside double-quotes." | 594 | If 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. | ||
| 630 | NAME can be a string (in which case it refers to an environment | ||
| 631 | variable or variable alias) or a symbol (in which case it refers | ||
| 632 | to 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. |
| 599 | The format of INDICES is: | 668 | The 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. | ||
| 521 | This 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. | ||
| 533 | This sets `eshell-prefer-lisp-variables' to t and should get/set | ||
| 534 | the 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. | ||
| 547 | This 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. | ||
| 557 | This should get the value bound to the symbol, but fail to set | ||
| 558 | it, 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 () |