Add support for running commands via Eshell's "env" command
* (eshell-handle-local-variables): Move most of the code to... (eshell-parse-local-variables): ... here. (eshell/env): Call 'eshell-parse-local-variables'. * test/lisp/eshell/esh-var-tests.el (esh-var-test/local-variables/env): New test. * doc/misc/eshell.texi (Built-ins): Describe the new behavior. * etc/NEWS: Announce this change.
This commit is contained in:
parent
f897b82ab1
commit
723b097351
4 changed files with 50 additions and 22 deletions
|
@ -624,9 +624,11 @@ each argument as a string, separated by a space.
|
|||
|
||||
@item env
|
||||
@cmindex env
|
||||
Prints the current environment variables. Unlike in Bash, this
|
||||
command does not yet support running commands with a modified
|
||||
environment.
|
||||
With no arguments, print the current environment variables. If you
|
||||
pass arguments to this command, then @command{env} will execute the
|
||||
arguments as a command. If you pass any initial arguments of the form
|
||||
@samp{@var{var}=@var{value}}, @command{env} will first set @var{var}
|
||||
to @var{value} before running the command.
|
||||
|
||||
@item eshell-debug
|
||||
@cmindex eshell-debug
|
||||
|
|
7
etc/NEWS
7
etc/NEWS
|
@ -656,6 +656,13 @@ appropriate, but still allow piping the output elsewhere if desired.
|
|||
For more information, see the "(eshell) Built-ins" node in the Eshell
|
||||
manual.
|
||||
|
||||
+++
|
||||
*** Eshell's 'env' command now supports running commands.
|
||||
Like in many other shells, Eshell's 'env' command now lets you run a
|
||||
command passed as arguments to 'env'. If you pass any initial
|
||||
arguments of the form 'VAR=VALUE', 'env' will first set 'VAR' to
|
||||
'VALUE' before running the command.
|
||||
|
||||
+++
|
||||
*** New special reference type '#<marker POSITION BUFFER>'.
|
||||
This special reference type returns a marker at 'POSITION' in
|
||||
|
|
|
@ -304,27 +304,36 @@ This is set to t in `eshell-local-variable-bindings' (which see).")
|
|||
(add-hook 'pcomplete-try-first-hook
|
||||
#'eshell-complete-variable-assignment nil t)))
|
||||
|
||||
(defun eshell-handle-local-variables ()
|
||||
"Allow for the syntax `VAR=val <command> <args>'."
|
||||
(defun eshell-parse-local-variables (args)
|
||||
"Parse a list of ARGS, looking for variable assignments.
|
||||
Variable assignments are of the form \"VAR=value\". If ARGS
|
||||
begins with any such assignments, throw `eshell-replace-command'
|
||||
with a form that will temporarily set those variables.
|
||||
Otherwise, return nil."
|
||||
;; Handle local variable settings by let-binding the entries in
|
||||
;; `eshell-local-variable-bindings' and calling `eshell-set-variable'
|
||||
;; for each variable before the command is invoked.
|
||||
(let ((setvar "\\`\\([A-Za-z_][A-Za-z0-9_]*\\)=\\(.*\\)\\'")
|
||||
(command eshell-last-command-name)
|
||||
(args eshell-last-arguments))
|
||||
(when (and (stringp command) (string-match setvar command))
|
||||
(head (car args))
|
||||
(rest (cdr args)))
|
||||
(when (and (stringp head) (string-match setvar head))
|
||||
(throw 'eshell-replace-command
|
||||
`(let ,eshell-local-variable-bindings
|
||||
,@(let (locals)
|
||||
(while (and (stringp command)
|
||||
(string-match setvar command))
|
||||
(while (and (stringp head)
|
||||
(string-match setvar head))
|
||||
(push `(eshell-set-variable
|
||||
,(match-string 1 command)
|
||||
,(match-string 2 command))
|
||||
,(match-string 1 head)
|
||||
,(match-string 2 head))
|
||||
locals)
|
||||
(setq command (pop args)))
|
||||
(setq head (pop rest)))
|
||||
(nreverse locals))
|
||||
(eshell-named-command ,command ,(list 'quote args)))))))
|
||||
(eshell-named-command ,head ',rest))))))
|
||||
|
||||
(defun eshell-handle-local-variables ()
|
||||
"Allow for the syntax `VAR=val <command> <args>'."
|
||||
(eshell-parse-local-variables (cons eshell-last-command-name
|
||||
eshell-last-arguments)))
|
||||
|
||||
(defun eshell-interpolate-variable ()
|
||||
"Parse a variable interpolation.
|
||||
|
@ -414,19 +423,22 @@ the values of nil for each."
|
|||
obarray #'boundp))
|
||||
(pcomplete-here))))
|
||||
|
||||
;; FIXME the real "env" command does more than this, it runs a program
|
||||
;; in a modified environment.
|
||||
(defun eshell/env (&rest args)
|
||||
"Implementation of `env' in Lisp."
|
||||
(eshell-init-print-buffer)
|
||||
(eshell-eval-using-options
|
||||
"env" args
|
||||
'((?h "help" nil nil "show this usage screen")
|
||||
'(;; FIXME: Support more "env" options, like "--unset".
|
||||
(?h "help" nil nil "show this usage screen")
|
||||
:external "env"
|
||||
:usage "<no arguments>")
|
||||
(dolist (setting (sort (eshell-environment-variables) 'string-lessp))
|
||||
(eshell-buffered-print setting "\n"))
|
||||
(eshell-flush)))
|
||||
:parse-leading-options-only
|
||||
:usage "[NAME=VALUE]... [COMMAND [ARG]...]")
|
||||
(if args
|
||||
(or (eshell-parse-local-variables args)
|
||||
(eshell-named-command (car args) (cdr args)))
|
||||
(eshell-init-print-buffer)
|
||||
(dolist (setting (sort (eshell-environment-variables) 'string-lessp))
|
||||
(eshell-buffered-print setting "\n"))
|
||||
(eshell-flush))))
|
||||
|
||||
(defun eshell-insert-envvar (envvar-name)
|
||||
"Insert ENVVAR-NAME into the current buffer at point."
|
||||
|
|
|
@ -661,6 +661,13 @@ nil, use FUNCTION instead."
|
|||
(eshell-insert-command "VAR=hello cd ..")
|
||||
(should (equal default-directory parent-directory)))))
|
||||
|
||||
(ert-deftest esh-var-test/local-variables/env ()
|
||||
"Test that \"env VAR=value command\" temporarily sets variables."
|
||||
(with-temp-eshell
|
||||
(push "VAR=value" process-environment)
|
||||
(eshell-match-command-output "env VAR=hello env" "VAR=hello\n")
|
||||
(should (equal (getenv "VAR") "value"))))
|
||||
|
||||
|
||||
;; Variable aliases
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue