Use "/local:" prefix in Eshell to run local commands when cwd is remote
* lisp/eshell/esh-ext.el (eshell-explicit-remote-commands) (eshell-explicit-command): Update docstrings. (eshell--local-prefix): New constant. (eshell-handle-remote-command): Remove. (eshell-quoted-file-command): New function... (eshell-ext-initialize): ... add it as a hook. (eshell-remote-command): Support running commands on localhost. (eshell-connection-local-command): Rename from 'eshell-external-command'. (eshell-external-command): New implementation calling 'eshell-remote-command' or 'eshell-connection-local-command' as appropriate. * test/lisp/eshell/esh-ext-tests.el (esh-ext-test/explicitly-local-command): Update test. * doc/misc/eshell.texi (Remote Access): Update documentation. * etc/NEWS: Update announcement.
This commit is contained in:
parent
c85294a613
commit
e260bf1be7
4 changed files with 50 additions and 36 deletions
|
@ -1535,13 +1535,18 @@ slash module (@pxref{Electric forward slash}).
|
|||
When running commands, you can also make them explicitly remote by
|
||||
prefixing the command name with a remote identifier, e.g.@:
|
||||
@samp{/ssh:user@@remote:whoami}. This runs the command @code{whoami}
|
||||
over the SSH connection for @code{user@@remote}, no matter your
|
||||
current directory. If you want to explicitly run a @emph{local}
|
||||
command even when in a remote directory, you can prefix the command
|
||||
name with @kbd{/:}, like @samp{/:whoami}. In either case, you can
|
||||
over the SSH connection for @code{user@@remote}, no matter your current
|
||||
directory. If you want to explicitly run a command on your @emph{local}
|
||||
machine even when in a remote directory, you can prefix the command name
|
||||
with @kbd{/local:}, like @samp{/local:whoami}. In either case, you can
|
||||
also specify the absolute path to the program, e.g.@:
|
||||
@samp{/ssh:user@@remote:/usr/bin/whoami}. To disable this syntax, set
|
||||
the option @code{eshell-explicit-remote-commands} to @code{nil}.
|
||||
@samp{/ssh:user@@remote:/usr/bin/whoami}. If you need to refer to a
|
||||
program whose file name would be interpreted as an explicitly-remote
|
||||
command, you can use @kbd{/:} to quote the name, e.g.@:
|
||||
@samp{/:/ssh:user@@remote:whoami} (@pxref{Quoted File Names,,, emacs,
|
||||
The GNU Emacs Manual}). To disable explicity-remote commands entirely,
|
||||
you can set the option @code{eshell-explicit-remote-commands} to
|
||||
@code{nil}.
|
||||
|
||||
@node History
|
||||
@section History
|
||||
|
|
2
etc/NEWS
2
etc/NEWS
|
@ -915,7 +915,7 @@ By prefixing a command name in Eshell with a remote identifier, like
|
|||
"/ssh:user@remote:whoami", you can now run commands on a particular
|
||||
host no matter your current directory. Likewise, you can run a
|
||||
command on your local system no matter your current directory via
|
||||
"/:whoami". For more information, see the "(eshell) Remote Access"
|
||||
"/local:whoami". For more information, see the "(eshell) Remote Access"
|
||||
node in the Eshell manual.
|
||||
|
||||
+++
|
||||
|
|
|
@ -167,23 +167,23 @@ external version."
|
|||
(defcustom eshell-explicit-remote-commands t
|
||||
"If non-nil, support explicitly-remote commands.
|
||||
These are commands with a full remote file name, such as
|
||||
\"/ssh:host:whoami\". If this is enabled, you can also run
|
||||
explicitly-local commands by using a quoted file name, like
|
||||
\"/:whoami\"."
|
||||
\"/ssh:host:whoami\". If this is enabled, you can also explicitly run
|
||||
commands on your local host by using the \"/local:\" prefix, like
|
||||
\"/local:whoami\"."
|
||||
:type 'boolean
|
||||
:group 'eshell-ext)
|
||||
|
||||
;;; Functions:
|
||||
|
||||
(defconst eshell--local-prefix "/local:")
|
||||
|
||||
(defun eshell-ext-initialize () ;Called from `eshell-mode' via intern-soft!
|
||||
"Initialize the external command handling code."
|
||||
(add-hook 'eshell-named-command-hook #'eshell-explicit-command nil t)
|
||||
(when eshell-explicit-remote-commands
|
||||
(add-hook 'eshell-named-command-hook
|
||||
#'eshell-handle-remote-command nil t)))
|
||||
(add-hook 'eshell-named-command-hook #'eshell-quoted-file-command nil t)
|
||||
(add-hook 'eshell-named-command-hook #'eshell-explicit-command nil t))
|
||||
|
||||
(defun eshell-explicit-command (command args)
|
||||
"If a command name begins with `*', call it externally always.
|
||||
"If a command name begins with \"*\", always call it externally.
|
||||
This bypasses all Lisp functions and aliases."
|
||||
(when (and (> (length command) 1)
|
||||
(eq (aref command 0) eshell-explicit-command-char))
|
||||
|
@ -194,39 +194,35 @@ This bypasses all Lisp functions and aliases."
|
|||
(error "%s: external command not found"
|
||||
(substring command 1))))))
|
||||
|
||||
(defun eshell-handle-remote-command (command args)
|
||||
"Handle remote (or quoted) COMMAND names, using ARGS.
|
||||
This calls the appropriate function for commands that aren't on
|
||||
the connection associated with `default-directory'. (See
|
||||
`eshell-explicit-remote-commands'.)"
|
||||
(if (file-name-quoted-p command)
|
||||
(let ((default-directory (if (file-remote-p default-directory)
|
||||
(expand-file-name "~")
|
||||
default-directory)))
|
||||
(eshell-external-command (file-name-unquote command) args))
|
||||
(when (file-remote-p command)
|
||||
(eshell-remote-command command args))))
|
||||
(defun eshell-quoted-file-command (command args)
|
||||
"If a command name begins with \"/:\", always call it externally.
|
||||
Similar to `eshell-explicit-command', this bypasses all Lisp functions
|
||||
and aliases, but it also ignores file name handlers."
|
||||
(when (file-name-quoted-p command)
|
||||
(eshell-external-command (file-name-unquote command) args)))
|
||||
|
||||
(defun eshell-remote-command (command args)
|
||||
"Insert output from a remote COMMAND, using ARGS.
|
||||
A remote command is something that executes on a different machine.
|
||||
An external command simply means external to Emacs."
|
||||
A \"remote\" command in Eshell is something that executes on a different
|
||||
machine. If COMMAND is a remote file name, run it on the host for that
|
||||
file; if COMMAND is a local file name, run it locally."
|
||||
(let* ((cwd-connection (file-remote-p default-directory))
|
||||
(command-connection (file-remote-p command))
|
||||
(default-directory (if (equal cwd-connection command-connection)
|
||||
default-directory
|
||||
command-connection))
|
||||
(or command-connection (expand-file-name "~"))))
|
||||
;; Never use the remote connection here. We don't want to
|
||||
;; expand the local name! Instead, we want it as the user
|
||||
;; typed, so that if COMMAND is "/ssh:host:cat", we just get
|
||||
;; "cat" as the result.
|
||||
(command-localname (file-remote-p command 'localname 'never)))
|
||||
(unless command-connection
|
||||
(error "%s: not a remote command" command))
|
||||
(command-localname (or (file-remote-p command 'localname 'never)
|
||||
command)))
|
||||
(eshell-external-command command-localname args)))
|
||||
|
||||
(defun eshell-external-command (command args)
|
||||
"Insert output from an external COMMAND, using ARGS."
|
||||
(defun eshell-connection-local-command (command args)
|
||||
"Insert output from an external COMMAND, using ARGS.
|
||||
This always runs COMMAND using the connection associated with the
|
||||
current working directory."
|
||||
(setq args (eshell-stringify-list (flatten-tree args)))
|
||||
(let ((interp (eshell-find-interpreter
|
||||
command
|
||||
|
@ -243,6 +239,19 @@ An external command simply means external to Emacs."
|
|||
(eshell-gather-process-output
|
||||
(car interp) (append (cdr interp) args)))))
|
||||
|
||||
(defun eshell-external-command (command args)
|
||||
"Insert output from an external COMMAND, using ARGS."
|
||||
(cond
|
||||
((and eshell-explicit-remote-commands
|
||||
(file-remote-p command))
|
||||
(eshell-remote-command command args))
|
||||
((and eshell-explicit-remote-commands
|
||||
(string-prefix-p eshell--local-prefix command))
|
||||
(eshell-remote-command
|
||||
(substring command (length eshell--local-prefix)) args))
|
||||
(t
|
||||
(eshell-connection-local-command command args))))
|
||||
|
||||
(defun eshell/addpath (&rest args)
|
||||
"Add a set of paths to PATH."
|
||||
(eshell-eval-using-options
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
;; Check the value of $INSIDE_EMACS using `sh' in order to
|
||||
;; delay variable expansion.
|
||||
(eshell-match-command-output
|
||||
(format "/:%s -c 'echo $INSIDE_EMACS'" cmd)
|
||||
(format "/local:%s -c 'echo $INSIDE_EMACS'" cmd)
|
||||
"eshell\n"))))))
|
||||
|
||||
;; esh-ext-tests.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue