Merge remote-tracking branch 'origin/master' into feature/android
This commit is contained in:
commit
dc7ecc6e31
13 changed files with 168 additions and 45 deletions
|
@ -1545,9 +1545,9 @@ AC_DEFUN([gt_TYPE_WINT_T],
|
|||
[GNULIBHEADERS_OVERRIDE_WINT_T=0
|
||||
AC_SUBST([GNULIBHEADERS_OVERRIDE_WINT_T])])
|
||||
# Emacs does not need precise checks for the Solaris 10 MB_CUR_MAX bug.
|
||||
AC_DEFUN([gt_LOCALE_FR_UTF8],
|
||||
[LOCALE_FR_UTF8=none
|
||||
AC_SUBST([LOCALE_FR_UTF8])])
|
||||
AC_DEFUN_ONCE([gl_STDLIB_H],
|
||||
[AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
|
||||
gl_NEXT_HEADERS([stdlib.h])])
|
||||
|
||||
# Initialize gnulib right after choosing the compiler.
|
||||
dnl Amongst other things, this sets AR and ARFLAGS.
|
||||
|
@ -7191,6 +7191,7 @@ if test "$emacs_cv_struct_alignment" = yes; then
|
|||
structure to an N-byte boundary.])
|
||||
fi
|
||||
|
||||
AC_C_RESTRICT
|
||||
AC_C_TYPEOF
|
||||
|
||||
AC_CACHE_CHECK([for statement expressions],
|
||||
|
|
|
@ -3630,7 +3630,11 @@ be @code{root}.
|
|||
If @var{connected} is non-@code{nil}, this function returns @code{nil}
|
||||
even if @var{filename} is remote, if Emacs has no network connection
|
||||
to its host. This is useful when you want to avoid the delay of
|
||||
making connections when they don't exist.
|
||||
making connections when they don't exist. If @var{connected} is
|
||||
@code{never}, @emph{never} use an existing connection to return the
|
||||
identification, even if one is already present (this is otherwise like
|
||||
a value of @code{nil}). This lets you prevent any connection-specific
|
||||
logic, such as expanding the local part of the file name.
|
||||
@end defun
|
||||
|
||||
@defun unhandled-file-name-directory filename
|
||||
|
|
|
@ -207,6 +207,7 @@ that will be invoked, type this as the Eshell prompt:
|
|||
* Built-ins::
|
||||
* Variables::
|
||||
* Aliases::
|
||||
* Remote Access::
|
||||
* History::
|
||||
* Completion::
|
||||
* Control Flow::
|
||||
|
@ -266,7 +267,10 @@ As an ordinary Lisp function
|
|||
@vindex eshell-prefer-lisp-functions
|
||||
If you would prefer to use ordinary Lisp functions over external
|
||||
programs, set the option @code{eshell-prefer-lisp-functions} to
|
||||
@code{t}. This will swap the lookup order of the last two items.
|
||||
@code{t}. This will swap the lookup order of the last two items. You
|
||||
can also force Eshell to look for a command as an external program by
|
||||
prefixing its name with @kbd{*}, like @code{*@var{command}}
|
||||
(@pxref{Built-ins}).
|
||||
|
||||
You can also group command forms together into a subcommand with curly
|
||||
braces (@code{@{@}}). This lets you use the output of a subcommand as
|
||||
|
@ -1090,6 +1094,43 @@ create and switch to a directory called @samp{foo}.
|
|||
|
||||
@end table
|
||||
|
||||
@node Remote Access
|
||||
@section Remote Access
|
||||
@cmindex remote access
|
||||
|
||||
Since Eshell uses Emacs facilities for most of its functionality, you
|
||||
can access remote hosts transparently. To connect to a remote host,
|
||||
simply @code{cd} into it:
|
||||
|
||||
@example
|
||||
~ $ cd /ssh:user@@remote:
|
||||
/ssh:user@@remote:~ $
|
||||
@end example
|
||||
|
||||
Additionally, built-in Eshell commands (@pxref{Built-ins}) and
|
||||
ordinary Lisp functions accept remote file names, so you can access
|
||||
them even without explicitly connecting first. For example, to print
|
||||
the contents of a remote file, you could type @samp{cat
|
||||
/ssh:user@@remote:~/output.log}. However, this means that when using
|
||||
built-in commands or Lisp functions from a remote directory, you must
|
||||
be careful about specifying absolute file names: @samp{cat
|
||||
/var/output.log} will always print the contents of your @emph{local}
|
||||
@file{/var/output.log}, even from a remote directory. If you find
|
||||
this behavior annoying, you can enable the optional electric forward
|
||||
slash module (@pxref{Electric forward slash}).
|
||||
|
||||
@vindex eshell-explicit-remote-commands
|
||||
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
|
||||
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}.
|
||||
|
||||
@node History
|
||||
@section History
|
||||
@cmindex history
|
||||
|
|
9
etc/NEWS
9
etc/NEWS
|
@ -224,6 +224,15 @@ or get a sublist of elements 2 through 4 with '$my-list[2..5]'. For
|
|||
more information, see the "(eshell) Dollars Expansion" node in the
|
||||
Eshell manual.
|
||||
|
||||
+++
|
||||
*** Eshell commands can now be explicitly-remote (or local).
|
||||
By prefixing a command name in Eshell with a remote identifier, like
|
||||
"/ssh:user@remote:whoami", you can now runs 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"
|
||||
node in the Eshell manual.
|
||||
|
||||
+++
|
||||
*** Eshell's '$UID' and '$GID' variables are now connection-aware.
|
||||
Now, when expanding '$UID' or '$GID' in a remote directory, the value
|
||||
|
|
|
@ -1197,7 +1197,6 @@ LIB_WSOCK32 = @LIB_WSOCK32@
|
|||
LIB_XATTR = @LIB_XATTR@
|
||||
LIMITS_H = @LIMITS_H@
|
||||
LN_S_FILEONLY = @LN_S_FILEONLY@
|
||||
LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
|
||||
LTLIBGMP = @LTLIBGMP@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
|
|
|
@ -168,11 +168,23 @@ external version."
|
|||
:type 'character
|
||||
:group 'eshell-ext)
|
||||
|
||||
(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\"."
|
||||
:type 'boolean
|
||||
:group 'eshell-ext)
|
||||
|
||||
;;; Functions:
|
||||
|
||||
(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))
|
||||
(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)))
|
||||
|
||||
(defun eshell-explicit-command (command args)
|
||||
"If a command name begins with `*', call it externally always.
|
||||
|
@ -186,30 +198,36 @@ 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-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.
|
||||
|
||||
Note that this function is very crude at the moment. It gathers up
|
||||
all the output from the remote command, and sends it all at once,
|
||||
causing the user to wonder if anything's really going on..."
|
||||
(let ((outbuf (generate-new-buffer " *eshell remote output*"))
|
||||
(errbuf (generate-new-buffer " *eshell remote error*"))
|
||||
(command (file-local-name command))
|
||||
(exitcode 1))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setq exitcode
|
||||
(shell-command
|
||||
(mapconcat #'shell-quote-argument
|
||||
(append (list command) args) " ")
|
||||
outbuf errbuf))
|
||||
(eshell-print (with-current-buffer outbuf (buffer-string)))
|
||||
(eshell-error (with-current-buffer errbuf (buffer-string))))
|
||||
(eshell-close-handles exitcode 'nil)
|
||||
(kill-buffer outbuf)
|
||||
(kill-buffer errbuf))))
|
||||
An external command simply means external to Emacs."
|
||||
(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))
|
||||
;; 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))
|
||||
(eshell-external-command command-localname args)))
|
||||
|
||||
(defun eshell-external-command (command args)
|
||||
"Insert output from an external COMMAND, using ARGS."
|
||||
|
|
|
@ -1270,7 +1270,9 @@ there is an existing connection.
|
|||
|
||||
If CONNECTED is non-nil, return an identification only if FILE is
|
||||
located on a remote system and a connection is established to
|
||||
that remote system.
|
||||
that remote system. If CONNECTED is `never', never use an
|
||||
existing connection to return the identification (this is
|
||||
otherwise like a value of nil).
|
||||
|
||||
Tip: You can use this expansion of remote identifier components
|
||||
to derive a new remote file name from an existing one. For
|
||||
|
|
|
@ -4341,13 +4341,14 @@ Let-bind it when necessary.")
|
|||
(let ((tramp-verbose (min tramp-verbose 3)))
|
||||
(when (tramp-tramp-file-p filename)
|
||||
(let* ((o (tramp-dissect-file-name filename))
|
||||
(p (tramp-get-connection-process o))
|
||||
(p (and (not (eq connected 'never))
|
||||
(tramp-get-connection-process o)))
|
||||
(c (and (process-live-p p)
|
||||
(tramp-get-connection-property p "connected"))))
|
||||
;; We expand the file name only, if there is already a connection.
|
||||
(with-parsed-tramp-file-name
|
||||
(if c (expand-file-name filename) filename) nil
|
||||
(and (or (not connected) c)
|
||||
(and (or (memq connected '(nil never)) c)
|
||||
(cond
|
||||
((eq identification 'method) method)
|
||||
;; Domain and port are appended to user and host,
|
||||
|
|
|
@ -463,7 +463,7 @@ This can be useful when using docker to run a language server.")
|
|||
(eval-and-compile
|
||||
(defvar eglot--lsp-interface-alist
|
||||
`(
|
||||
(CodeAction (:title) (:kind :diagnostics :edit :command :isPreferred))
|
||||
(CodeAction (:title) (:kind :diagnostics :edit :command :isPreferred :data))
|
||||
(ConfigurationItem () (:scopeUri :section))
|
||||
(Command ((:title . string) (:command . string)) (:arguments))
|
||||
(CompletionItem (:label)
|
||||
|
@ -739,9 +739,12 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
|
|||
(server action) "Default implementation."
|
||||
(eglot--dcase action
|
||||
(((Command)) (eglot--request server :workspace/executeCommand action))
|
||||
(((CodeAction) edit command)
|
||||
(when edit (eglot--apply-workspace-edit edit))
|
||||
(when command (eglot--request server :workspace/executeCommand command))))))
|
||||
(((CodeAction) edit command data)
|
||||
(if (and (null edit) (null command) data
|
||||
(eglot--server-capable :codeActionProvider :resolveProvider))
|
||||
(eglot-execute server (eglot--request server :codeAction/resolve action))
|
||||
(when edit (eglot--apply-workspace-edit edit))
|
||||
(when command (eglot--request server :workspace/executeCommand command)))))))
|
||||
|
||||
(cl-defgeneric eglot-initialization-options (server)
|
||||
"JSON object to send under `initializationOptions'."
|
||||
|
@ -825,6 +828,7 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
|
|||
:documentHighlight `(:dynamicRegistration :json-false)
|
||||
:codeAction (list
|
||||
:dynamicRegistration :json-false
|
||||
:resolveSupport t :dataSupport t
|
||||
:codeActionLiteralSupport
|
||||
'(:codeActionKind
|
||||
(:valueSet
|
||||
|
@ -3197,11 +3201,25 @@ for which LSP on-type-formatting should be requested."
|
|||
sig
|
||||
(with-temp-buffer
|
||||
(insert siglabel)
|
||||
;; Ad-hoc attempt to parse label as <name>(<params>)
|
||||
;; Add documentation, indented so we can distinguish multiple signatures
|
||||
(when-let (doc (and (not briefp) sigdoc (eglot--format-markup sigdoc)))
|
||||
(goto-char (point-max))
|
||||
(insert "\n" (replace-regexp-in-string "^" " " doc)))
|
||||
;; Try to highlight function name only
|
||||
(let (first-parlabel)
|
||||
(cond ((and (cl-plusp (length parameters))
|
||||
(vectorp (setq first-parlabel
|
||||
(plist-get (aref parameters 0) :label))))
|
||||
(save-excursion
|
||||
(goto-char (elt first-parlabel 0))
|
||||
(skip-syntax-backward "^w")
|
||||
(add-face-text-property (point-min) (point)
|
||||
'font-lock-function-name-face)))
|
||||
((save-excursion
|
||||
(goto-char (point-min))
|
||||
(looking-at "\\([^(]*\\)([^)]*)"))
|
||||
(add-face-text-property (match-beginning 1) (match-end 1)
|
||||
'font-lock-function-name-face))))
|
||||
;; Now to the parameters
|
||||
(cl-loop
|
||||
with active-param = (or sig-active activeParameter)
|
||||
|
@ -3210,13 +3228,8 @@ for which LSP on-type-formatting should be requested."
|
|||
((:label parlabel))
|
||||
((:documentation pardoc)))
|
||||
parameter
|
||||
(when (zerop i)
|
||||
(goto-char (elt parlabel 0))
|
||||
(skip-syntax-backward "^w")
|
||||
(add-face-text-property (point-min) (point)
|
||||
'font-lock-function-name-face))
|
||||
;; ...perhaps highlight it in the formals list
|
||||
(when (= i active-param)
|
||||
(when (eq i active-param)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(pcase-let
|
||||
|
|
|
@ -1679,7 +1679,8 @@ It's also possible to enter an arbitrary directory not in the list."
|
|||
ret))
|
||||
;; XXX: Just using this for the category (for the substring
|
||||
;; completion style).
|
||||
(table (project--file-completion-table (cons dir-choice choices)))
|
||||
(table (project--file-completion-table
|
||||
(reverse (cons dir-choice choices))))
|
||||
(pr-name ""))
|
||||
(while (equal pr-name "")
|
||||
;; If the user simply pressed RET, do this again until they don't.
|
||||
|
|
|
@ -5056,7 +5056,7 @@ but that should be robust in the unexpected case that an error is signaled."
|
|||
;; The use without `format' is obsolete, let's warn when we bump
|
||||
;; into any such remaining uses.
|
||||
(macroexp-warn-and-return
|
||||
(format-message "Missing format argument in `with-demote-errors'")
|
||||
(format-message "Missing format argument in `with-demoted-errors'")
|
||||
exp nil nil
|
||||
orig-format))))
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'tramp)
|
||||
(require 'ert)
|
||||
(require 'esh-mode)
|
||||
(require 'esh-ext)
|
||||
|
@ -73,4 +74,35 @@
|
|||
(eshell-match-command-output "echo $PATH"
|
||||
(concat original-path "\n")))))
|
||||
|
||||
(ert-deftest esh-ext-test/explicitly-remote-command ()
|
||||
"Test that an explicitly-remote command is remote no matter the current dir."
|
||||
(skip-unless (and (eshell-tests-remote-accessible-p)
|
||||
(executable-find "sh")))
|
||||
(dolist (default-directory (list default-directory
|
||||
ert-remote-temporary-file-directory))
|
||||
(dolist (cmd (list "sh" (executable-find "sh")))
|
||||
(ert-info ((format "Directory: %s; executable: %s" default-directory cmd))
|
||||
(with-temp-eshell
|
||||
;; Check the value of $INSIDE_EMACS using `sh' in order to
|
||||
;; delay variable expansion.
|
||||
(eshell-match-command-output
|
||||
(format "%s%s -c 'echo $INSIDE_EMACS'"
|
||||
(file-remote-p ert-remote-temporary-file-directory) cmd)
|
||||
"eshell,tramp"))))))
|
||||
|
||||
(ert-deftest esh-ext-test/explicitly-local-command ()
|
||||
"Test that an explicitly-local command is local no matter the current dir."
|
||||
(skip-unless (and (eshell-tests-remote-accessible-p)
|
||||
(executable-find "sh")))
|
||||
(dolist (default-directory (list default-directory
|
||||
ert-remote-temporary-file-directory))
|
||||
(dolist (cmd (list "sh" (executable-find "sh")))
|
||||
(ert-info ((format "In directory: %s" default-directory))
|
||||
(with-temp-eshell
|
||||
;; 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)
|
||||
"eshell\n"))))))
|
||||
|
||||
;; esh-ext-tests.el ends here
|
||||
|
|
|
@ -6073,7 +6073,9 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
;; Unset the variable.
|
||||
(let ((tramp-remote-process-environment
|
||||
(cons (concat envvar "=foo") tramp-remote-process-environment)))
|
||||
;; Set the initial value, we want to unset below.
|
||||
;; Refill the cache; we don't want to run into timeouts.
|
||||
(file-truename default-directory)
|
||||
;; Check the initial value, we want to unset below.
|
||||
(should
|
||||
(string-match-p
|
||||
"foo"
|
||||
|
|
Loading…
Add table
Reference in a new issue