commit 112e71914a98cd21d222b9abe9d2fc52eb8852ea (HEAD, refs/remotes/origin/master) Author: Bill Wohler Date: Mon Jul 10 20:46:58 2023 -0700 Fix Wrong type argument: consp, nil error * lisp/mh-e/mh-folder.el (mh-update-sequences): Add cur sequence when missing diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el index dbed3c83994..68f72a6e0cf 100644 --- a/lisp/mh-e/mh-folder.el +++ b/lisp/mh-e/mh-folder.el @@ -1293,8 +1293,9 @@ mh-update-sequences (if new-cur (let ((seq-entry (mh-find-seq 'cur))) (mh-remove-cur-notation) - (setcdr seq-entry - (list new-cur)) ;delete-seq-locally, add-msgs-to-seq + (if seq-entry + (setcdr seq-entry (list new-cur)) + (mh-add-msgs-to-seq (list new-cur) 'cur)) (mh-define-sequence 'cur (list new-cur)) (beginning-of-line) (if (looking-at mh-scan-good-msg-regexp) commit a92ee5ca3cf20b9a6c38c86e7f151a2020500eff Author: Bill Wohler Date: Mon Jul 10 20:41:57 2023 -0700 Fix mh-show-msg: Symbol’s value as variable is void: mh-mm-inline-media-tests * lisp/mh-e/mh-show.el: Require mh-mime diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el index 54d986edc1e..8a26ab6d81e 100644 --- a/lisp/mh-e/mh-show.el +++ b/lisp/mh-e/mh-show.el @@ -29,6 +29,7 @@ ;;; Code: (require 'mh-e) +(require 'mh-mime) (require 'mh-scan) ;; Dynamically-created function not found in mh-loaddefs.el. commit 3b7273f4ae3623962c5d5fdc922a62af1136f448 Author: João Távora Date: Tue Jul 11 00:09:08 2023 +0100 Eglot: add support for :codeAction/resolve See https://github.com/emacs-grammarly/eglot-grammarly/issues/7. * lisp/progmodes/eglot.el (eglot--lsp-interface-alist): Augment CodeAction type. (eglot-execute): Consider :codeAction/resolve (eglot-client-capabilities): Advertise textDocument.codeAction.resolveSupport diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 537d8cac8ae..0c46e4a5290 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -463,7 +463,7 @@ eglot--accepted-formats (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 @@ eglot-execute (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 @@ eglot-client-capabilities :documentHighlight `(:dynamicRegistration :json-false) :codeAction (list :dynamicRegistration :json-false + :resolveSupport t :dataSupport t :codeActionLiteralSupport '(:codeActionKind (:valueSet commit a6e88dc72692a7a361cebdceb63851dc2427958d Author: Jim Porter Date: Sun Jul 9 12:06:13 2023 -0700 Add support for explicitly-remote commands in Eshell * lisp/files.el (file-remote-p): * doc/lispref/files.texi (Magic File Names): Document 'never' for CONNECTED argument. * lisp/net/tramp.el (tramp-handle-file-remote-p): Handle CONNECTED value of 'never'. * lisp/eshell/esh-ext.el (eshell-explicit-remote-commands): New option. (eshell-ext-initialize): Apply 'eshell-handle-remote-command' when requested. (eshell-handle-remote-command): New function. (eshell-remote-command): Reimplement this function and dispatch to 'eshell-external-command', which can handle remote processes on its own. * test/lisp/eshell/esh-ext-tests.el (esh-ext-test/explicitly-remote-command) (esh-ext-test/explicitly-local-command): New tests. * doc/misc/eshell.texi (Remote Access): Document explicitly-remote commands. * etc/NEWS: Announce this change. diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 66de0f036c4..31d4aaca507 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -3630,7 +3630,11 @@ Magic File Names 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 diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index cd0aaf69add..ecc12035650 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -1119,6 +1119,18 @@ Remote Access 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 diff --git a/etc/NEWS b/etc/NEWS index 246e6b21838..5d5ea990b92 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -202,6 +202,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 diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el index f350622e78c..38579d7ef1c 100644 --- a/lisp/eshell/esh-ext.el +++ b/lisp/eshell/esh-ext.el @@ -168,11 +168,23 @@ eshell-explicit-command-char :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 @@ eshell-explicit-command (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." diff --git a/lisp/files.el b/lisp/files.el index 2fffd2e6c35..377ed1b8a0b 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1270,7 +1270,9 @@ file-remote-p 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 diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 8c9023d004a..538cc4252db 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -4336,13 +4336,14 @@ tramp-handle-file-remote-p (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, diff --git a/test/lisp/eshell/esh-ext-tests.el b/test/lisp/eshell/esh-ext-tests.el index ef073d3487d..aae297cd413 100644 --- a/test/lisp/eshell/esh-ext-tests.el +++ b/test/lisp/eshell/esh-ext-tests.el @@ -23,6 +23,7 @@ ;;; Code: +(require 'tramp) (require 'ert) (require 'esh-mode) (require 'esh-ext) @@ -73,4 +74,35 @@ esh-ext-test/addpath/set-locally (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 commit 438921161acaf3f4494f8866302c339e13c88cdb Author: Jim Porter Date: Sun Jul 9 12:04:01 2023 -0700 Add documentation about remote access in Eshell * doc/misc/eshell.texi (Invocation): Mention the '*' prefix. (Remote Access): New section... (Commands): ... link to it. diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index c6376882542..cd0aaf69add 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -207,6 +207,7 @@ Commands * Built-ins:: * Variables:: * Aliases:: +* Remote Access:: * History:: * Completion:: * Control Flow:: @@ -266,7 +267,10 @@ Invocation @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,31 @@ Aliases @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}). + @node History @section History @cmindex history commit d8238df35a31cb9e065c2d243df77ce55735ed02 Author: Juri Linkov Date: Mon Jul 10 20:43:13 2023 +0300 * lisp/progmodes/project.el (project-prompt-project-name): Fix order. Reverse choices in this recently added new command to follow exactly the same order as in the old function 'project-prompt-project-dir'. diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 56c524bcab5..1d5a5fa5c63 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1679,7 +1679,8 @@ project-prompt-project-name 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. commit 845ff9563d47568ddd5cb37c62a53deade2d4693 Author: Paul Eggert Date: Mon Jul 10 09:53:07 2023 -0700 Further simplify configure-time locale testing * configure.ac (gl_STDLIB_H): Replace this, not gt_LOCALE_FR_UTF8, as this lets us also omit MB_CUR_MAX checking that will never be executed, and also lets us remove testing for ecvt, fcvt, gcvt that Emacs doesn’t need. (AC_C_RESTRICT): Invoke explicitly, as Emacs uses ‘restrict’ directly. Also, simplifies the replacement for gl_STDLIB_H, which would otherwise need to AC_REQUIRE AC_C_RESTRICT. * lib/gnulib.mk.in: Regenerate via admin/merge-gnulib. diff --git a/configure.ac b/configure.ac index 890b06905c1..a51aa44cf2c 100644 --- a/configure.ac +++ b/configure.ac @@ -902,9 +902,9 @@ AC_DEFUN [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. @@ -6305,6 +6305,7 @@ AC_DEFUN structure to an N-byte boundary.]) fi +AC_C_RESTRICT AC_C_TYPEOF AC_CACHE_CHECK([for statement expressions], diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index a25bee25aae..3ef36bf8af6 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -961,7 +961,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@ commit 31cae9d9d6a00a33fb4a18d9725ff4d6b103c176 Author: Michael Albinus Date: Mon Jul 10 18:11:24 2023 +0200 Adapt Tramp test * test/lisp/net/tramp-tests.el (tramp-test33-environment-variables): Adapt test. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 51980e335e7..16afc0f477a 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -6073,7 +6073,9 @@ tramp-test33-environment-variables ;; 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" commit d1a2c2edc2c15d9018c143ad3f9c1131e0dfd5dd Author: Mattias Engdegård Date: Mon Jul 10 16:31:28 2023 +0200 ; * lisp/subr.el (with-demoted-errors): warning message typo diff --git a/lisp/subr.el b/lisp/subr.el index 483083b29c3..fac5fd58092 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -5018,7 +5018,7 @@ with-demoted-errors ;; 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)))) commit b56f46c9deeb782297695e39baf8f3c65c85281b Author: João Távora Date: Mon Jul 10 14:06:42 2023 +0100 Eglot: fix eglot--sig-info again See https://github.com/joaotavora/eglot/issues/1253 * lisp/progmodes/eglot.el (eglot--sig-info): Fall back to regexp technique if no parameters or poor parameter information. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 95e9a30a372..537d8cac8ae 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3197,11 +3197,25 @@ eglot--sig-info sig (with-temp-buffer (insert siglabel) - ;; Ad-hoc attempt to parse label as () ;; 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,11 +3224,6 @@ eglot--sig-info ((: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 (eq i active-param) (save-excursion commit d0f65fbdbbba945a97c97b4b34ba8f9671e68f35 Author: João Távora Date: Mon Jul 10 13:09:48 2023 +0100 Eglot: fix eglot--sig-info See https://github.com/joaotavora/eglot/issues/1253 * lisp/progmodes/eglot.el (eglot--sig-info): Fix. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index f09c348143d..95e9a30a372 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3216,7 +3216,7 @@ eglot--sig-info (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