commit 8125d4cfc5605ead9102b7d823c4241029eb76cc (HEAD, refs/remotes/origin/master) Author: João Távora Date: Mon Apr 3 01:40:30 2023 +0100 Eglot: Bump to 1.14 * lisp/progmodes/eglot.el (Version): Bump to 1.14 (Package-Requires): Require ElDoc 1.14.0 * etc/EGLOT-NEWS: Update. diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index 2872cdd05cf..7369b3bf545 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -18,7 +18,7 @@ to look up issue github#1234, go to https://github.com/joaotavora/eglot/issues/1234. -* Changes in upcoming Eglot 1.14 +* Changes in Eglot 1.14 (3/4/2023) ** Faster, more responsive completion diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 93af5f2123b..10b6c0cc2ca 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2,12 +2,12 @@ ;; Copyright (C) 2018-2023 Free Software Foundation, Inc. -;; Version: 1.13 +;; Version: 1.14 ;; Author: João Távora ;; Maintainer: João Távora ;; URL: https://github.com/joaotavora/eglot ;; Keywords: convenience, languages -;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.11.0") (seq "2.23") (external-completion "0.1")) +;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1")) ;; This is a GNU ELPA :core package. Avoid adding functionality ;; that is not available in the version of Emacs recorded above or any commit c108132d3bb69d0cc8d2e0222a781dff9abca087 Merge: f886ae5cf07 3bdbb66efb9 Author: João Távora Date: Mon Apr 3 00:33:03 2023 +0100 Merge from origin/emacs-29 3bdbb66efb9 ; CONTRIBUTE: Minor stylistic changes. d0eb12e8d3c Fix typo in section 14.1 of Emacs Manual b2fbec37f39 ; * etc/EGLOT-NEWS: Clarify scope of topmost section 131ec049db0 Eglot: unbreak eglot-extend-to-xref on w32 0622e1f29f6 Eglot: ensure server shutdown turns off eglot-inlay-hints... 59f66ea3027 ; * lisp/emacs-lisp/package-vc.el: Remove completed item ... d23dc3dd7e3 ; * lisp/emacs-lisp/package-vc.el (package-vc): Fix manua... 4508a024e81 ; Clarify documentation of 'cursor' text property d2e82817a3f Add two typescript-ts-mode faces (bug#62429) 10918fc9d24 Fix scrolling window when point moves up 9b32bc134c4 Improve documentation of 'defcustom's :set keyword ab4273056e0 Comp fix calls to redefined primtives with op-bytecode (b... c98929c7e18 ; Fix last change a14c3f62a67 ; Fix last change 09fece5722f Fix duplicate defcustom in eww.el e45bd10a3d9 Fix indentation regression in 'C-h l' 46fd10a7600 * doc/misc/tramp.texi (Remote shell setup): Clarify use o... commit f886ae5cf07bb40ad3fd0262942bdc74efca0277 Author: João Távora Date: Mon Apr 3 00:00:18 2023 +0100 ; * etc/EGLOT-NEWS (Upcoming 1.14): Update. diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index 09772a1e71a..2872cdd05cf 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -39,6 +39,32 @@ run into problems, disable this mechanism like so: (add-hook 'c-common-mode-hook (lambda () (setq-local eglot-cache-session-completions nil))) +** At-point documentation less obtrusive in echo area + +Eglot takes advantage of new features of ElDoc to separate short +documentation strings from large ones, sending the former to be shown in +the ElDoc's echo area and the latter to be shown in other outlets, +such as the *eldoc* buffer obtainable with 'C-h .'. + +** New variable 'eglot-prefer-plaintext' + +Customize this to t to opt-in to docstrings in plain text instead of +Markdown. + +(bug#61373) + +** Progress indicators inhabit the mode-line by default + +To switch to the echo area, customize 'eglot-report-progress' to +'messages'. To switch off progress reporting completely, set to nil. + +** Snippet support is easier to enable + +The user needn't manually activate 'yas-minor-mode' or +'yas-global-mode'. If YASnippet is installed and the server supports +snippets, it is used automatically, unless the symbol 'yasnippet' has +been added to 'eglot-stay-out-of'. + * Changes in Eglot 1.13 (15/03/2023) commit f2357df91f0262949618bd4da571d3267c1b1dfa Author: João Távora Date: Sun Apr 2 23:40:31 2023 +0100 Eldoc: bump package version to 1.14.0 * lisp/emacs-lisp/eldoc.el (Version): Bump to 1.14.0 diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 8b427d6a825..1eb0d38c5ce 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -5,7 +5,7 @@ ;; Author: Noah Friedman ;; Keywords: extensions ;; Created: 1995-10-06 -;; Version: 1.13.0 +;; Version: 1.14.0 ;; Package-Requires: ((emacs "26.3")) ;; This is a GNU ELPA :core package. Avoid functionality that is not commit 87f025117b8bafc0780a6ef4a6308dfdc2be0859 Author: João Távora Date: Sun Apr 2 23:38:37 2023 +0100 ; Eldoc: fix doc of e-d-functions w.r.t. :origin keyword * lisp/emacs-lisp/eldoc.el (eldoc-documentation-functions): Fix. diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index ef4cda4650f..8b427d6a825 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -448,17 +448,17 @@ eldoc-documentation-functions `eldoc-display-in-echo-area' and `eldoc-display-in-buffer' will use when displaying `:thing''s value. -* `:origin', VALUE being the member of - `eldoc-documentation-functions' where DOCSTRING - originated. `eldoc-display-in-buffer' may use this organize the - documentation buffer accordingly. - * `:echo', controlling how `eldoc-display-in-echo-area' should present this documentation item in the echo area, to save space. If VALUE is a string, echo it instead of DOCSTRING. If a number, only echo DOCSTRING up to that character position. If `skip', don't echo DOCSTRING at all. +The additional KEY `:origin' is always added by ElDoc, its VALUE +being the member of `eldoc-documentation-functions' where +DOCSTRING originated. `eldoc-display-functions' may use this +information to organize display of multiple docstrings. + Finally, major modes should modify this hook locally, for example: (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t) commit ecf53a50037e66d0f1775c7046d54e218ddd26af Author: João Távora Date: Sun Apr 2 23:33:23 2023 +0100 ; Eglot: removed unused dependency on 'array.el' * lisp/progmodes/eglot.el (array): Don't require diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index ae2ba1351dc..0112af52c01 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -107,7 +107,6 @@ (require 'subr-x)) (require 'filenotify) (require 'ert) -(require 'array) ;; These dependencies are also GNU ELPA core packages. Because of ;; bug#62576, since there is a risk that M-x package-install, despite commit bdb400912e01b9cfd06d393c14d8ceb08b6838ed Author: João Távora Date: Sun Apr 2 23:31:10 2023 +0100 Eglot: load built-in GNU ELPA dependencies explicitly Because of outstanding bug#62576, it's way to easy for users to get confused by the M-x package-install process for Eglot. Whenever an Eglot release depends on a new version of a GNU ELPA :core package which is _also_ provided built-in, M-x package-install will install that dependency, but will not always load it on top of the built-in one. The solution is to not use "require" for now. This may potentially lead to double "loads", but that should in principle be idempotent. * lisp/progmodes/eglot.el (project, eldoc, seq, flymake, xref, jsonrpc) (external-completion): Load, don't require. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 7e329d2e26a..ae2ba1351dc 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -97,34 +97,30 @@ (require 'imenu) (require 'cl-lib) -(require 'project) + (require 'url-parse) (require 'url-util) (require 'pcase) (require 'compile) ; for some faces (require 'warnings) -(require 'flymake) -(require 'xref) (eval-when-compile (require 'subr-x)) -(require 'jsonrpc) (require 'filenotify) (require 'ert) (require 'array) -(require 'external-completion) - -;; ElDoc is preloaded in Emacs, so `require'-ing won't guarantee we are -;; using the latest version from GNU Elpa when we load eglot.el. Use an -;; heuristic to see if we need to `load' it in Emacs < 28. -(if (and (< emacs-major-version 28) - (not (boundp 'eldoc-documentation-strategy))) - (load "eldoc") - (require 'eldoc)) - -;; Similar issue as above for Emacs 26.3 and seq.el. -(if (< emacs-major-version 27) - (load "seq") - (require 'seq)) + +;; These dependencies are also GNU ELPA core packages. Because of +;; bug#62576, since there is a risk that M-x package-install, despite +;; having installed them, didn't correctly re-load them over the +;; built-in versions. +(eval-and-compile + (load "project") + (load "eldoc") + (load "seq") + (load "flymake") + (load "xref") + (load "jsonrpc") + (load "external-completion")) ;; forward-declare, but don't require (Emacs 28 doesn't seem to care) (defvar markdown-fontify-code-blocks-natively) commit ad1efe5e675216e1f1f342fc9d48018fac718b5e Author: João Távora Date: Wed Mar 29 19:30:04 2023 +0100 Eglot: improve caching in eglot-completion-at-point When answering the :textDocument/completion request, LSP servers provide a :isIncomplete flag in the response, which allows Eglot to know if "further typing should result in recomputing [the completions] list. If :isIncomplete is false (i.e. the full set was returned), Eglot caches the response in a global variable eglot--capf-cache that persists for the duration of the "completion session", taken to be the interval between two calls to completion-in-region-mode. If the cache has been set, and Eglot detects that "further typing" has happened, it is safe to use the cache instead of making a request to the server. Thus eglot--capf-cache-flush, added to completion-in-region-mode-hook, is used to flush this cache. Since the popular Company completion package doesn't use completion-in-region-mode, eglot--capf-cache-flush is also added to its company-after-completion-hook. * lisp/progmodes/eglot.el (eglot--managed-mode): Set 'completion-in-region-mode-hook and company-after-completion-hook. (eglot--capf-cache): New variable. (eglot--capf-cache-flush): New function. (eglot-completion-at-point): Rework. * etc/EGLOT-NEWS: Update. diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index dd04e677285..09772a1e71a 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -17,6 +17,28 @@ This refers to https://github.com/joaotavora/eglot/issues/. That is, to look up issue github#1234, go to https://github.com/joaotavora/eglot/issues/1234. + +* Changes in upcoming Eglot 1.14 + +** Faster, more responsive completion + +Eglot takes advantage of LSP's "isIncomplete" flag in responses to +completion requests to drive new completion-caching mechanism for the +duration of each completion session. Once a full set of completions +is obtained for a given position, the server needn't be contacted in +many scenarios, resulting in significantly less communication +overhead. This works with the popular Company package and stock +completion-at-point interfaces. + +A variable 'eglot-cache-session-completions', t by default, controls +this. The mechanism was tested with ccls, jdtls, pylsp, golsp and +clangd. Notably, the C/C++ language server Clangd version 15 has a +bug in its "isIcomplete" flag (it is fixed in later versions). If you +run into problems, disable this mechanism like so: + +(add-hook 'c-common-mode-hook + (lambda () (setq-local eglot-cache-session-completions nil))) + * Changes in Eglot 1.13 (15/03/2023) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 04fc7235919..7e329d2e26a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1863,6 +1863,8 @@ eglot--managed-mode (unless (eglot--stay-out-of-p 'xref) (add-hook 'xref-backend-functions 'eglot-xref-backend nil t)) (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t) + (add-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush nil t) + (add-hook 'company-after-completion-hook #'eglot--capf-session-flush nil t) (add-hook 'change-major-mode-hook #'eglot--managed-mode-off nil t) (add-hook 'post-self-insert-hook 'eglot--post-self-insert-hook nil t) (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t) @@ -1894,6 +1896,8 @@ eglot--managed-mode (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t) (remove-hook 'xref-backend-functions 'eglot-xref-backend t) (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t) + (remove-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush t) + (remove-hook 'company-after-completion-hook #'eglot--capf-session-flush t) (remove-hook 'change-major-mode-hook #'eglot--managed-mode-off t) (remove-hook 'post-self-insert-hook 'eglot--post-self-insert-hook t) (remove-hook 'pre-command-hook 'eglot--pre-command-hook t) @@ -2896,6 +2900,13 @@ eglot-format :trimFinalNewlines (if delete-trailing-lines t :json-false)) args))))) +(defvar eglot-cache-session-completions t + "If non-nil Eglot caches data during completion sessions.") + +(defvar eglot--capf-session :none "A cache used by `eglot-completion-at-point'.") + +(defun eglot--capf-session-flush (&optional _) (setq eglot--capf-session :none)) + (defun eglot-completion-at-point () "Eglot's `completion-at-point' function." ;; Commit logs for this function help understand what's going on. @@ -2911,40 +2922,50 @@ eglot-completion-at-point :sortText))))) (metadata `(metadata (category . eglot) (display-sort-function . ,sort-completions))) - resp items (cached-proxies :none) + (local-cache :none) + (bounds (bounds-of-thing-at-point 'symbol)) + (orig-pos (point)) + (resolved (make-hash-table)) (proxies (lambda () - (if (listp cached-proxies) cached-proxies - (setq resp - (eglot--request server - :textDocument/completion - (eglot--CompletionParams) - :cancel-on-input t)) - (setq items (append - (if (vectorp resp) resp (plist-get resp :items)) - nil)) - (setq cached-proxies - (mapcar - (jsonrpc-lambda - (&rest item &key label insertText insertTextFormat - textEdit &allow-other-keys) - (let ((proxy - ;; Snippet or textEdit, it's safe to - ;; display/insert the label since - ;; it'll be adjusted. If no usable - ;; insertText at all, label is best, - ;; too. - (cond ((or (eql insertTextFormat 2) - textEdit - (null insertText) - (string-empty-p insertText)) - (string-trim-left label)) - (t insertText)))) - (unless (zerop (length proxy)) - (put-text-property 0 1 'eglot--lsp-item item proxy)) - proxy)) - items))))) - (resolved (make-hash-table)) + (if (listp local-cache) local-cache + (let* ((resp (eglot--request server + :textDocument/completion + (eglot--CompletionParams) + :cancel-on-input t)) + (items (append + (if (vectorp resp) resp (plist-get resp :items)) + nil)) + (cachep (and (listp resp) items + eglot-cache-session-completions + (eq (plist-get resp :isIncomplete) :json-false))) + (bounds (or bounds + (cons (point) (point)))) + (proxies + (mapcar + (jsonrpc-lambda + (&rest item &key label insertText insertTextFormat + textEdit &allow-other-keys) + (let ((proxy + ;; Snippet or textEdit, it's safe to + ;; display/insert the label since + ;; it'll be adjusted. If no usable + ;; insertText at all, label is best, + ;; too. + (cond ((or (eql insertTextFormat 2) + textEdit + (null insertText) + (string-empty-p insertText)) + (string-trim-left label)) + (t insertText)))) + (unless (zerop (length proxy)) + (put-text-property 0 1 'eglot--lsp-item item proxy)) + proxy)) + items))) + ;; (trace-values "Requested" (length proxies) cachep bounds) + (setq eglot--capf-session + (if cachep (list bounds proxies resolved orig-pos) :none)) + (setq local-cache proxies))))) (resolve-maybe ;; Maybe completion/resolve JSON object `lsp-comp' into ;; another JSON object, if at all possible. Otherwise, @@ -2957,11 +2978,19 @@ eglot-completion-at-point (plist-get lsp-comp :data)) (eglot--request server :completionItem/resolve lsp-comp :cancel-on-input t) - lsp-comp))))) - (bounds (bounds-of-thing-at-point 'symbol))) + lsp-comp)))))) + (unless bounds (setq bounds (cons (point) (point)))) + (when (and (consp eglot--capf-session) + (= (car bounds) (car (nth 0 eglot--capf-session))) + (>= (cdr bounds) (cdr (nth 0 eglot--capf-session)))) + (setq local-cache (nth 1 eglot--capf-session) + resolved (nth 2 eglot--capf-session) + orig-pos (nth 3 eglot--capf-session)) + ;; (trace-values "Recalling cache" (length local-cache) bounds orig-pos) + ) (list - (or (car bounds) (point)) - (or (cdr bounds) (point)) + (car bounds) + (cdr bounds) (lambda (probe pred action) (cond ((eq action 'metadata) metadata) ; metadata @@ -3032,7 +3061,7 @@ eglot-completion-at-point :company-require-match 'never :company-prefix-length (save-excursion - (when (car bounds) (goto-char (car bounds))) + (goto-char (car bounds)) (when (listp completion-capability) (looking-back (regexp-opt @@ -3040,6 +3069,7 @@ eglot-completion-at-point (eglot--bol)))) :exit-function (lambda (proxy status) + (eglot--capf-session-flush) (when (memq status '(finished exact)) ;; To assist in using this whole `completion-at-point' ;; function inside `completion-in-region', ensure the exit @@ -3063,17 +3093,12 @@ eglot-completion-at-point (let ((snippet-fn (and (eql insertTextFormat 2) (eglot--snippet-expansion-fn)))) (cond (textEdit - ;; Undo (yes, undo) the newly inserted completion. - ;; If before completion the buffer was "foo.b" and - ;; now is "foo.bar", `proxy' will be "bar". We - ;; want to delete only "ar" (`proxy' minus the - ;; symbol whose bounds we've calculated before) - ;; (github#160). - (delete-region (+ (- (point) (length proxy)) - (if bounds - (- (cdr bounds) (car bounds)) - 0)) - (point)) + ;; Revert buffer back to state when the edit + ;; was obtained from server. If a `proxy' + ;; "bar" was obtained from a buffer with + ;; "foo.b", the LSP edit applies to that' + ;; state, _not_ the current "foo.bar". + (delete-region orig-pos (point)) (eglot--dbind ((TextEdit) range newText) textEdit (pcase-let ((`(,beg . ,end) (eglot--range-region range))) commit d00e05daa96700860dbb9dc6527105e464ffb960 Author: João Távora Date: Sat Mar 25 19:53:14 2023 +0000 Eglot: take advantage of new Eldoc options for signature doc Only echo the "active signature", send all the other signatures for the *eldoc* buffer. * lisp/progmodes/eglot.el (eglot--sig-info): Rework protocol. (eglot-signature-eldoc-function): Rework. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 8e47c397ca8..04fc7235919 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3096,62 +3096,57 @@ eglot--hover-info (mapconcat #'eglot--format-markup (if (vectorp contents) contents (list contents)) "\n")) -(defun eglot--sig-info (sigs active-sig sig-help-active-param) - (cl-loop - for (sig . moresigs) on (append sigs nil) for i from 0 - concat - (eglot--dbind ((SignatureInformation) label documentation parameters activeParameter) sig - (with-temp-buffer - (save-excursion (insert label)) - (let ((active-param (or activeParameter sig-help-active-param)) - params-start params-end) - ;; Ad-hoc attempt to parse label as () - (when (looking-at "\\([^(]*\\)(\\([^)]+\\))") - (setq params-start (match-beginning 2) params-end (match-end 2)) - (add-face-text-property (match-beginning 1) (match-end 1) - 'font-lock-function-name-face)) - (when (eql i active-sig) - ;; Decide whether to add one-line-summary to signature line - (when (and (stringp documentation) - (string-match "[[:space:]]*\\([^.\r\n]+[.]?\\)" - documentation)) - (setq documentation (match-string 1 documentation)) - (unless (string-prefix-p (string-trim documentation) label) - (goto-char (point-max)) - (insert ": " (eglot--format-markup documentation)))) - ;; Decide what to do with the active parameter... - (when (and (eql i active-sig) active-param - (< -1 active-param (length parameters))) - (eglot--dbind ((ParameterInformation) label documentation) - (aref parameters active-param) - ;; ...perhaps highlight it in the formals list - (when params-start - (goto-char params-start) - (pcase-let - ((`(,beg ,end) +(defun eglot--sig-info (sig &optional _activep sig-help-active-param) + (eglot--dbind ((SignatureInformation) label documentation parameters activeParameter) + sig + (with-temp-buffer + (save-excursion (insert label)) + (let ((active-param (or activeParameter sig-help-active-param)) + params-start params-end) + ;; Ad-hoc attempt to parse label as () + (when (looking-at "\\([^(]*\\)(\\([^)]+\\))") + (setq params-start (match-beginning 2) params-end (match-end 2)) + (add-face-text-property (match-beginning 1) (match-end 1) + 'font-lock-function-name-face)) + ;; Decide whether to add one-line-summary to signature line + (when (and (stringp documentation) + (string-match "[[:space:]]*\\([^.\r\n]+[.]?\\)" + documentation)) + (setq documentation (match-string 1 documentation)) + (unless (string-prefix-p (string-trim documentation) label) + (goto-char (point-max)) + (insert ": " (eglot--format-markup documentation)))) + ;; Decide what to do with the active parameter... + (when (and active-param (< -1 active-param (length parameters))) + (eglot--dbind ((ParameterInformation) label documentation) + (aref parameters active-param) + ;; ...perhaps highlight it in the formals list + (when params-start + (goto-char params-start) + (pcase-let + ((`(,beg ,end) + (if (stringp label) + (let ((case-fold-search nil)) + (and (re-search-forward + (concat "\\<" (regexp-quote label) "\\>") + params-end t) + (list (match-beginning 0) (match-end 0)))) + (mapcar #'1+ (append label nil))))) + (if (and beg end) + (add-face-text-property + beg end + 'eldoc-highlight-function-argument)))) + ;; ...and/or maybe add its doc on a line by its own. + (when documentation + (goto-char (point-max)) + (insert "\n" + (propertize (if (stringp label) - (let ((case-fold-search nil)) - (and (re-search-forward - (concat "\\<" (regexp-quote label) "\\>") - params-end t) - (list (match-beginning 0) (match-end 0)))) - (mapcar #'1+ (append label nil))))) - (if (and beg end) - (add-face-text-property - beg end - 'eldoc-highlight-function-argument)))) - ;; ...and/or maybe add its doc on a line by its own. - (when documentation - (goto-char (point-max)) - (insert "\n" - (propertize - (if (stringp label) - label - (apply #'buffer-substring (mapcar #'1+ label))) - 'face 'eldoc-highlight-function-argument) - ": " (eglot--format-markup documentation)))))) - (buffer-string)))) - when moresigs concat "\n")) + label + (apply #'buffer-substring (mapcar #'1+ label))) + 'face 'eldoc-highlight-function-argument) + ": " (eglot--format-markup documentation)))))) + (buffer-string)))) (defun eglot-signature-eldoc-function (cb) "A member of `eldoc-documentation-functions', for signatures." @@ -3164,11 +3159,12 @@ eglot-signature-eldoc-function (eglot--lambda ((SignatureHelp) signatures activeSignature activeParameter) (eglot--when-buffer-window buf - (funcall cb - (unless (seq-empty-p signatures) - (eglot--sig-info signatures - activeSignature - activeParameter))))) + (let ((active-sig (and (cl-plusp (length signatures)) + (aref signatures (or activeSignature 0))))) + (if (not active-sig) (funcall cb nil) + (funcall cb + (mapconcat #'eglot--sig-info signatures "\n") + :echo (eglot--sig-info active-sig t activeParameter)))))) :deferred :textDocument/signatureHelp)) t)) commit d69d0b1a296c17508663afc9d0301b8ccaa7115e Author: João Távora Date: Fri Mar 24 22:17:44 2023 +0000 Eglot: declare support for markdown also for signatures * lisp/progmodes/eglot.el (eglot--accepted-formats): new helper. (eglot-client-capabilities): use it. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3458fbc7cb2..8e47c397ca8 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -452,6 +452,10 @@ eglot--executable-find (if (>= emacs-major-version 27) (executable-find command remote) (executable-find command))) +(defun eglot--accepted-formats () + (if (and (not eglot-prefer-plaintext) (fboundp 'gfm-view-mode)) + ["markdown" "plaintext"] ["plaintext"])) + ;;; Message verification helpers ;;; @@ -782,15 +786,12 @@ eglot-client-capabilities :tagSupport (:valueSet [1])) :contextSupport t) :hover (list :dynamicRegistration :json-false - :contentFormat - (if (and (not eglot-prefer-plaintext) - (fboundp 'gfm-view-mode)) - ["markdown" "plaintext"] - ["plaintext"])) + :contentFormat (eglot--accepted-formats)) :signatureHelp (list :dynamicRegistration :json-false :signatureInformation `(:parameterInformation (:labelOffsetSupport t) + :documentationFormat ,(eglot--accepted-formats) :activeParameterSupport t)) :references `(:dynamicRegistration :json-false) :definition (list :dynamicRegistration :json-false commit 66c48f9e46abab869333eaf1de574711bcaf601e Author: João Távora Date: Fri Mar 24 22:16:49 2023 +0000 Eglot: define eglot--ensure-list with defalias This avoids annoying obsoletion warnings when compiling the whole buffer. * lisp/progmodes/eglot.el (eglot--ensure-list): define with defalias. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index e52a40b7f22..3458fbc7cb2 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1779,9 +1779,9 @@ eglot--trampish-p (defun eglot--plist-keys (plist) "Get keys of a plist." (cl-loop for (k _v) on plist by #'cddr collect k)) -(defun eglot--ensure-list (x) (if (listp x) x (list x))) -(when (fboundp 'ensure-list) ; Emacs 28 or later - (define-obsolete-function-alias 'eglot--ensure-list #'ensure-list "29.1")) +(defalias 'eglot--ensure-list + (if (fboundp 'ensure-list) #'ensure-list + (lambda (x) (if (listp x) x (list x))))) ;;; Minor modes commit a8c1559a663d9bc21776e33303251e244f86f0d7 Author: João Távora Date: Wed Mar 29 22:48:54 2023 +0100 Eglot: remove hacky advice of jsonrpc-request The vast majority of Eglot sync requests to the server need to inform the server of any pending changes to the buffer beforehand, so that the server has up-to-date information to do its job. But doing so at the expense of ugly advice of jsonrpc-request is ill advised. Introduce eglot--request helper instead and use that. Use this opportunity to conduct a review of Eglot sync requests and come to the conclusion that all need to send any changes beforehand. Nevertheless, an IMMEDIATE kwarg to eglot--request was added to bypassing this. * lisp/progmodes/eglot.el (eglot--request): New helper. (eglot-shutdown) (eglot-execute-command) (eglot-workspace-configuration) (eglot--signal-textDocument/willSave) (eglot--workspace-symbols) (eglot--lsp-xrefs-for-method) (xref-backend-apropos) (eglot-format) (eglot-completion-at-point) (eglot-imenu) (eglot-rename) (eglot-code-actions): Use eglot--request. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3072095aeb2..e52a40b7f22 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -916,7 +916,7 @@ eglot-shutdown (unwind-protect (progn (setf (eglot--shutdown-requested server) t) - (jsonrpc-request server :shutdown nil :timeout (or timeout 1.5)) + (eglot--request server :shutdown nil :timeout (or timeout 1.5)) (jsonrpc-notify server :exit nil)) ;; Now ask jsonrpc.el to shut down the server. (jsonrpc-shutdown server (not preserve-buffers)) @@ -1469,6 +1469,18 @@ 'eglot--bol (line-beginning-position n)))) "Return position of first character in current line.") +(cl-defun eglot--request (server method params &key + immediate + timeout cancel-on-input + cancel-on-input-retval) + "Like `jsonrpc-request', but for Eglot LSP requests. +Unless IMMEDIATE, send pending changes before making request." + (unless immediate (eglot--signal-textDocument/didChange)) + (jsonrpc-request server method params + :timeout timeout + :cancel-on-input cancel-on-input + :cancel-on-input-retval cancel-on-input-retval)) + ;;; Encoding fever ;;; @@ -2148,8 +2160,8 @@ eglot-execute-command (server command arguments) "Execute COMMAND on SERVER with `:workspace/executeCommand'. COMMAND is a symbol naming the command." - (jsonrpc-request server :workspace/executeCommand - `(:command ,(format "%s" command) :arguments ,arguments))) + (eglot--request server :workspace/executeCommand + `(:command ,(format "%s" command) :arguments ,arguments))) (cl-defmethod eglot-handle-notification (_server (_method (eql window/showMessage)) &key type message) @@ -2453,16 +2465,6 @@ eglot--after-change (run-hooks 'eglot--document-changed-hook) (setq eglot--change-idle-timer nil)))))))) -;; HACK! Launching a deferred sync request with outstanding changes is a -;; bad idea, since that might lead to the request never having a -;; chance to run, because `jsonrpc-connection-ready-p'. -(advice-add #'jsonrpc-request :before - (cl-function (lambda (_proc _method _params &key - deferred &allow-other-keys) - (when (and eglot--managed-mode deferred) - (eglot--signal-textDocument/didChange)))) - '((name . eglot--signal-textDocument/didChange))) - (defvar-local eglot-workspace-configuration () "Configure LSP servers specifically for a given project. @@ -2615,8 +2617,8 @@ eglot--signal-textDocument/willSave (when (eglot--server-capable :textDocumentSync :willSaveWaitUntil) (ignore-errors (eglot--apply-text-edits - (jsonrpc-request server :textDocument/willSaveWaitUntil params - :timeout 0.5)))))) + (eglot--request server :textDocument/willSaveWaitUntil params + :timeout 0.5)))))) (defun eglot--signal-textDocument/didSave () "Maybe send textDocument/didSave to server." @@ -2728,8 +2730,8 @@ eglot--workspace-symbols (propertize (alist-get kind eglot--symbol-kind-names "Unknown") 'face 'shadow)) 'eglot--lsp-workspaceSymbol wss))) - (jsonrpc-request (eglot--current-server-or-lose) :workspace/symbol - `(:query ,pat))))) + (eglot--request (eglot--current-server-or-lose) :workspace/symbol + `(:query ,pat))))) (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot))) "Yet another tricky connection between LSP and Elisp completion semantics." @@ -2785,7 +2787,7 @@ eglot--lsp-xrefs-for-method (cadr (split-string (symbol-name method) "/")))))) (let ((response - (jsonrpc-request + (eglot--request (eglot--current-server-or-lose) method (append (eglot--TextDocumentPositionParams) extra-params)))) (eglot--collecting-xrefs (collect) @@ -2848,9 +2850,9 @@ xref-backend-apropos (eglot--lambda ((SymbolInformation) name location) (eglot--dbind ((Location) uri range) location (collect (eglot--xref-make-match name uri range)))) - (jsonrpc-request (eglot--current-server-or-lose) - :workspace/symbol - `(:query ,pattern)))))) + (eglot--request (eglot--current-server-or-lose) + :workspace/symbol + `(:query ,pattern)))))) (defun eglot-format-buffer () "Format contents of current buffer." @@ -2882,7 +2884,7 @@ eglot-format '(:textDocument/formatting :documentFormattingProvider nil))))) (eglot--server-capable-or-lose cap) (eglot--apply-text-edits - (jsonrpc-request + (eglot--request (eglot--current-server-or-lose) method (cl-list* @@ -2891,8 +2893,7 @@ eglot-format :insertSpaces (if indent-tabs-mode :json-false t) :insertFinalNewline (if require-final-newline t :json-false) :trimFinalNewlines (if delete-trailing-lines t :json-false)) - args) - :deferred method)))) + args))))) (defun eglot-completion-at-point () "Eglot's `completion-at-point' function." @@ -2914,10 +2915,9 @@ eglot-completion-at-point (lambda () (if (listp cached-proxies) cached-proxies (setq resp - (jsonrpc-request server + (eglot--request server :textDocument/completion (eglot--CompletionParams) - :deferred :textDocument/completion :cancel-on-input t)) (setq items (append (if (vectorp resp) resp (plist-get resp :items)) @@ -2954,8 +2954,8 @@ eglot-completion-at-point (if (and (eglot--server-capable :completionProvider :resolveProvider) (plist-get lsp-comp :data)) - (jsonrpc-request server :completionItem/resolve - lsp-comp :cancel-on-input t) + (eglot--request server :completionItem/resolve + lsp-comp :cancel-on-input t) lsp-comp))))) (bounds (bounds-of-thing-at-point 'symbol))) (list @@ -3255,11 +3255,11 @@ eglot-imenu (seq-group-by (lambda (obj) (plist-get obj :kind)) (mapcan #'unfurl - (jsonrpc-request (eglot--current-server-or-lose) - :textDocument/documentSymbol - `(:textDocument - ,(eglot--TextDocumentIdentifier)) - :cancel-on-input non-essential)))))) + (eglot--request (eglot--current-server-or-lose) + :textDocument/documentSymbol + `(:textDocument + ,(eglot--TextDocumentIdentifier)) + :cancel-on-input non-essential)))))) (cl-defun eglot--apply-text-edits (edits &optional version) "Apply EDITS for current buffer if at VERSION, or if it's nil." @@ -3330,9 +3330,9 @@ eglot-rename (symbol-name (symbol-at-point))))) (eglot--server-capable-or-lose :renameProvider) (eglot--apply-workspace-edit - (jsonrpc-request (eglot--current-server-or-lose) - :textDocument/rename `(,@(eglot--TextDocumentPositionParams) - :newName ,newname)) + (eglot--request (eglot--current-server-or-lose) + :textDocument/rename `(,@(eglot--TextDocumentPositionParams) + :newName ,newname)) current-prefix-arg)) (defun eglot--region-bounds () @@ -3358,7 +3358,7 @@ eglot-code-actions (eglot--server-capable-or-lose :codeActionProvider) (let* ((server (eglot--current-server-or-lose)) (actions - (jsonrpc-request + (eglot--request server :textDocument/codeAction (list :textDocument (eglot--TextDocumentIdentifier) @@ -3370,8 +3370,7 @@ eglot-code-actions when (cdr (assoc 'eglot-lsp-diag (eglot--diag-data diag))) collect it)] - ,@(when action-kind `(:only [,action-kind])))) - :deferred t)) + ,@(when action-kind `(:only [,action-kind])))))) ;; Redo filtering, in case the `:only' didn't go through. (actions (cl-loop for a across actions when (or (not action-kind) commit 093a360251afdbdc6fe6cf22e72ccbc79fc22e2e Author: Jim Porter Date: Thu Mar 30 19:38:30 2023 -0700 Use the 'interactive' spec to set arguments for 'eshell-command' * lisp/eshell/eshell.el (eshell-read-command): New function... (eshell-command): ... use it. Additionally, require the COMMAND argument, and rename ARG to TO-CURRENT-BUFFER. diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el index b71f283bf9f..15fc2ae6310 100644 --- a/lisp/eshell/eshell.el +++ b/lisp/eshell/eshell.el @@ -272,26 +272,28 @@ eshell-non-interactive-p (declare-function eshell-add-input-to-history "em-hist" (input)) -;;;###autoload -(defun eshell-command (&optional command arg) - "Execute the Eshell command string COMMAND. -With prefix ARG, insert output into the current buffer at point." - (interactive) - (unless arg - (setq arg current-prefix-arg)) - (let ((eshell-non-interactive-p t)) +(defun eshell-read-command (&optional prompt) + "Read an Eshell command from the minibuffer, prompting with PROMPT." + (let ((prompt (or prompt "Emacs shell command: ")) + (eshell-non-interactive-p t)) ;; Enable `eshell-mode' only in this minibuffer. (minibuffer-with-setup-hook (lambda () (eshell-mode) (eshell-command-mode +1)) - (unless command - (setq command (read-from-minibuffer "Emacs shell command: ")) - (if (eshell-using-module 'eshell-hist) - (eshell-add-input-to-history command))))) - (unless command - (error "No command specified!")) + (let ((command (read-from-minibuffer prompt))) + (when (eshell-using-module 'eshell-hist) + (eshell-add-input-to-history command)) + command)))) + +;;;###autoload +(defun eshell-command (command &optional to-current-buffer) + "Execute the Eshell command string COMMAND. +If TO-CURRENT-BUFFER is non-nil (interactively, with the prefix +argument), then insert output into the current buffer at point." + (interactive (list (eshell-read-command) + current-prefix-arg)) (save-excursion - (let ((stdout (if arg (current-buffer) t)) + (let ((stdout (if to-current-buffer (current-buffer) t)) (buf (set-buffer (generate-new-buffer " *eshell cmd*"))) (eshell-non-interactive-p t)) (eshell-mode) @@ -319,7 +321,7 @@ eshell-command (while (and (bolp) (not (bobp))) (delete-char -1))) (cl-assert (and buf (buffer-live-p buf))) - (unless arg + (unless to-current-buffer (let ((len (if (not intr) 2 (count-lines (point-min) (point-max))))) (cond commit 267fca267fe858d8a8f34d15de21051e3b6fff41 Author: Jim Porter Date: Thu Mar 30 19:31:30 2023 -0700 Fix using background commands in 'eshell-command' This regressed due to the patch for bug#53715, which changed how Eshell pipelines return the processes in the pipeline (bug#62556). * lisp/eshell/esh-cmd.el (eshell-parse-command): When creating background commands, wrap the process(es) in a cons cell whose CAR is ':eshell-background'. This lets us use fewer heuristics... (eshell-eval-command): ... here. Additionally, keep the result and the incomplete delimiter separate. * lisp/eshell/eshell.el (eshell-command): Check ':eshell-background' and use a more-robust method for setting the output target. * test/lisp/eshell/eshell-tests.el (eshell-test/eshell-command/simple) (eshell-test/eshell-command/pipeline) (eshell-test/eshell-command/background) (eshell-test/eshell-command/background-pipeline): New tests. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index a96ce9fab51..94aa2ed8906 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -421,7 +421,8 @@ eshell-parse-command (string= (car eshell--sep-terms) ";")) (eshell-parse-pipeline cmd) `(eshell-do-subjob - (list ,(eshell-parse-pipeline cmd))))) + (cons :eshell-background + ,(eshell-parse-pipeline cmd))))) (setq eshell--sep-terms (cdr eshell--sep-terms)) (if eshell-in-pipeline-p cmd @@ -1036,7 +1037,12 @@ eshell-eval-argument (cadr result))) (defun eshell-eval-command (command &optional input) - "Evaluate the given COMMAND iteratively." + "Evaluate the given COMMAND iteratively. +Return the process (or head and tail processes) created by +COMMAND, if any. If COMMAND is a background command, return the +process(es) in a cons cell like: + + (:eshell-background . PROCESS)" (if eshell-current-command ;; We can just stick the new command at the end of the current ;; one, and everything will happen as it should. @@ -1052,20 +1058,12 @@ eshell-eval-command (erase-buffer) (insert "command: \"" input "\"\n"))) (setq eshell-current-command command) - (let* ((delim (catch 'eshell-incomplete - (eshell-resume-eval))) - (val (car-safe delim))) - ;; If the return value of `eshell-resume-eval' is wrapped in a - ;; list, it indicates that the command was run asynchronously. - ;; In that case, unwrap the value before checking the delimiter - ;; value. - (if (and val - (not (eshell-processp val)) - (not (eq val t))) - (error "Unmatched delimiter: %S" val) - ;; Eshell-command expect a list like () to know if the - ;; command should be async or not. - (or (and (eshell-processp val) delim) val))))) + (let* (result + (delim (catch 'eshell-incomplete + (ignore (setq result (eshell-resume-eval)))))) + (when delim + (error "Unmatched delimiter: %S" delim)) + result))) (defun eshell-resume-command (proc status) "Resume the current command when a process ends." diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el index 7d2c0335db2..b71f283bf9f 100644 --- a/lisp/eshell/eshell.el +++ b/lisp/eshell/eshell.el @@ -290,25 +290,18 @@ eshell-command (eshell-add-input-to-history command))))) (unless command (error "No command specified!")) - ;; redirection into the current buffer is achieved by adding an - ;; output redirection to the end of the command, of the form - ;; 'COMMAND >>> #'. This will not interfere with - ;; other redirections, since multiple redirections merely cause the - ;; output to be copied to multiple target locations - (if arg - (setq command - (concat command - (format " >>> #" - (buffer-name (current-buffer)))))) (save-excursion - (let ((buf (set-buffer (generate-new-buffer " *eshell cmd*"))) + (let ((stdout (if arg (current-buffer) t)) + (buf (set-buffer (generate-new-buffer " *eshell cmd*"))) (eshell-non-interactive-p t)) (eshell-mode) (let* ((proc (eshell-eval-command - (list 'eshell-commands - (eshell-parse-command command)))) + `(let ((eshell-current-handles + (eshell-create-handles ,stdout 'insert)) + (eshell-current-subjob-p)) + ,(eshell-parse-command command)))) intr - (bufname (if (and proc (listp proc)) + (bufname (if (eq (car-safe proc) :eshell-background) "*Eshell Async Command Output*" (setq intr t) "*Eshell Command Output*"))) diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el index 743cc28b9b5..390f75cfbb9 100644 --- a/test/lisp/eshell/eshell-tests.el +++ b/test/lisp/eshell/eshell-tests.el @@ -107,6 +107,50 @@ eshell-test/lisp-reset-in-pipeline (format template "format \"%s\" eshell-in-pipeline-p") "nil"))) +(ert-deftest eshell-test/eshell-command/simple () + "Test that the `eshell-command' function writes to the current buffer." + (skip-unless (executable-find "echo")) + (ert-with-temp-directory eshell-directory-name + (let ((eshell-history-file-name nil)) + (with-temp-buffer + (eshell-command "*echo hi" t) + (should (equal (buffer-string) "hi\n")))))) + +(ert-deftest eshell-test/eshell-command/pipeline () + "Test that the `eshell-command' function writes to the current buffer. +This test uses a pipeline for the command." + (skip-unless (and (executable-find "echo") + (executable-find "cat"))) + (ert-with-temp-directory eshell-directory-name + (let ((eshell-history-file-name nil)) + (with-temp-buffer + (eshell-command "*echo hi | *cat" t) + (should (equal (buffer-string) "hi\n")))))) + +(ert-deftest eshell-test/eshell-command/background () + "Test that `eshell-command' works for background commands." + (skip-unless (executable-find "echo")) + (ert-with-temp-directory eshell-directory-name + (let ((orig-processes (process-list)) + (eshell-history-file-name nil)) + (with-temp-buffer + (eshell-command "*echo hi &" t) + (eshell-wait-for (lambda () (equal (process-list) orig-processes))) + (should (equal (buffer-string) "hi\n")))))) + +(ert-deftest eshell-test/eshell-command/background-pipeline () + "Test that `eshell-command' works for background commands. +This test uses a pipeline for the command." + (skip-unless (and (executable-find "echo") + (executable-find "cat"))) + (ert-with-temp-directory eshell-directory-name + (let ((orig-processes (copy-tree (process-list))) + (eshell-history-file-name nil)) + (with-temp-buffer + (eshell-command "*echo hi | *cat &" t) + (eshell-wait-for (lambda () (equal (process-list) orig-processes))) + (should (equal (buffer-string) "hi\n")))))) + (ert-deftest eshell-test/command-running-p () "Modeline should show no command running" (with-temp-eshell commit 6df2941c1b0d965afc40f8c50ce08e45e060d64c Author: Stefan Monnier Date: Sun Apr 2 17:54:02 2023 -0400 lisp/simple.el (inhibit-auto-fill): New var * lisp/simple.el (inhibit-auto-fill): New var. (internal-auto-fill): Obey it. (newline): Use it instead of binding `auto-fill-function`, so as to avoid messing up the state if something wants to enable/disable `auto-fill-mode` during the course of the let binding (bug#62419). diff --git a/etc/NEWS b/etc/NEWS index 67e1a02d587..d20d9f65ac9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -319,6 +319,8 @@ hooks named after the feature name, like 'esh-mode-unload-hook'. * Lisp Changes in Emacs 30.1 +** New var 'inhibit-auto-fill' to temporarily prevent auto-fill. + ** Functions and variables to transpose sexps +++ diff --git a/lisp/simple.el b/lisp/simple.el index 1447c7e53ff..b621e1603bd 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -623,7 +623,7 @@ newline (beforepos (point)) (last-command-event ?\n) ;; Don't auto-fill if we have a prefix argument. - (auto-fill-function (if arg nil auto-fill-function)) + (inhibit-auto-fill (or inhibit-auto-fill arg)) (arg (prefix-numeric-value arg)) (procsym (make-symbol "newline-postproc")) ;(bug#46326) (postproc @@ -8919,11 +8919,15 @@ default-indent-new-line ;; If we're not inside a comment, just try to indent. (t (indent-according-to-mode)))))) +(defvar inhibit-auto-fill nil + "Non-nil means to do as if `auto-fill-mode' was disabled.") + (defun internal-auto-fill () "The function called by `self-insert-command' to perform auto-filling." - (when (or (not comment-start) - (not comment-auto-fill-only-comments) - (nth 4 (syntax-ppss))) + (unless (or inhibit-auto-fill + (and comment-start + comment-auto-fill-only-comments + (not (nth 4 (syntax-ppss))))) (funcall auto-fill-function))) (defvar normal-auto-fill-function 'do-auto-fill commit 5223762e02ac84eee984cd1f7a17865766cdad9a Author: Stefan Monnier Date: Sun Apr 2 17:45:58 2023 -0400 src/eval.c: Fix bug#62419 Yup, almost 40 years after ELisp first combined them, buffer-local and let bindings still don't work quite right :-( The "automatically buffer-local if set" semantics should follow the principle that it becomes buffer-local iff the var's current binding refers to the top-level/global/non-let binding. * src/eval.c (let_shadows_buffer_binding_p): Disregard non-global let-bindings. * test/src/eval-tests.el (eval-test--bug62419): New test. diff --git a/src/eval.c b/src/eval.c index eb40c953f96..1a4d3ad0307 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3400,7 +3400,7 @@ DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode, return object; } -/* Return true if SYMBOL currently has a let-binding +/* Return true if SYMBOL's default currently has a let-binding which was made in the buffer that is now current. */ bool @@ -3415,6 +3415,7 @@ let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol) struct Lisp_Symbol *let_bound_symbol = XSYMBOL (specpdl_symbol (p)); eassert (let_bound_symbol->u.s.redirect != SYMBOL_VARALIAS); if (symbol == let_bound_symbol + && p->kind != SPECPDL_LET_LOCAL /* bug#62419 */ && EQ (specpdl_where (p), buf)) return 1; } diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el index 1e7edca3bac..e0a27439ba2 100644 --- a/test/src/eval-tests.el +++ b/test/src/eval-tests.el @@ -247,4 +247,23 @@ eval-tests/funcall-with-delayed-message (should (equal (string-trim (buffer-string)) expected-messages)))))))) +(defvar-local eval-test--local-var 'global) + +(ert-deftest eval-test--bug62419 () + (with-temp-buffer + (setq eval-test--local-var 'first-local) + (let ((eval-test--local-var t)) + (kill-local-variable 'eval-test--local-var) + (setq eval-test--local-var 'second-local) + (should (eq eval-test--local-var 'second-local))) + ;; FIXME: It's not completely clear if exiting the above `let' + ;; should restore the buffer-local binding to `first-local' + ;; (i.e. reset the value of the second buffer-local binding to the + ;; first's initial value) or should do nothing (on the principle that + ;; the first buffer-local binding doesn't exists any more so there's + ;; nothing to restore). I think both semantics make sense. + ;;(should (eq eval-test--local-var 'first-local)) + ) + (should (eq eval-test--local-var 'global))) + ;;; eval-tests.el ends here commit 00144fa287eb168c1ba8e411e43fe13b9d2732ac Author: Jim Porter Date: Fri Mar 31 21:32:44 2023 -0700 ; Add tests for synchronous processes in Eshell Normally, Eshell only uses synchronous processes on MS-DOS, so this is hard to test. To get around this, let the tests explicitly request synchronous processes. * lisp/eshell/esh-proc.el (eshell-supports-asynchronous-processes): New variable... (eshell-gather-process-output): ... use it, and remove some incorrect code updating Eshell's internal markers (the async code path doesn't do this, so neither should the sync path). * lisp/eshell/esh-cmd.el (eshell-execute-pipeline): Use 'eshell-supports-asynchronous-processes'. * test/lisp/eshell/esh-proc-tests.el (esh-proc-test/emacs-command): New function. (esh-proc-test/emacs-echo, esh-proc-test/emacs-upcase): New variables. (esh-proc-test/synchronous-proc/simple/interactive) (esh-proc-test/synchronous-proc/simple/command-result) (esh-proc-test/synchronous-proc/pipeline/interactive) (esh-proc-test/synchronous-proc/pipeline/command-result): New tests. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index f0c6a146dfd..a96ce9fab51 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -893,7 +893,7 @@ eshell-execute-pipeline (set headproc nil) (set tailproc nil) (progn - ,(if (fboundp 'make-process) + ,(if eshell-supports-asynchronous-processes `(eshell-do-pipelines ,pipeline) `(let ((tail-handles (eshell-duplicate-handles eshell-current-handles))) diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index a86e7502795..00e0c8014e1 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el @@ -97,6 +97,9 @@ eshell-kill-hook ;;; Internal Variables: +(defvar eshell-supports-asynchronous-processes (fboundp 'make-process) + "Non-nil if Eshell can create asynchronous processes.") + (defvar eshell-current-subjob-p nil) (defvar eshell-process-list nil @@ -296,7 +299,7 @@ eshell-gather-process-output (coding-system-change-eol-conversion locale-coding-system 'unix)))) (cond - ((fboundp 'make-process) + (eshell-supports-asynchronous-processes (unless (or ;; FIXME: It's not currently possible to use a ;; stderr process for remote files. (file-remote-p default-directory) @@ -367,6 +370,8 @@ eshell-gather-process-output (erase-buffer) (set-buffer oldbuf) (run-hook-with-args 'eshell-exec-hook command) + ;; XXX: This doesn't support sending stdout and stderr to + ;; separate places. (setq exit-status (apply #'call-process-region (append (list eshell-last-sync-output-start (point) @@ -392,10 +397,6 @@ eshell-gather-process-output (setq lbeg lend) (set-buffer proc-buf)) (set-buffer oldbuf)) - (require 'esh-mode) - (declare-function eshell-update-markers "esh-mode" (pmark)) - (defvar eshell-last-output-end) ;Defined in esh-mode.el. - (eshell-update-markers eshell-last-output-end) ;; Simulate the effect of eshell-sentinel. (eshell-close-handles (if (numberp exit-status) exit-status -1) diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el index 8e02fbb5497..fa20efa71e1 100644 --- a/test/lisp/eshell/esh-proc-tests.el +++ b/test/lisp/eshell/esh-proc-tests.el @@ -191,6 +191,59 @@ esh-proc-test/pipeline-connection-type/last (unless (eq system-type 'windows-nt) "stdout\nstderr\n")))) + +;; Synchronous processes + +;; These tests check that synchronous subprocesses (only used on +;; MS-DOS by default) work correctly. To help them run on MS-DOS as +;; well, we use the Emacs executable as our subprocess to test +;; against; that way, users don't need to have GNU coreutils (or +;; similar) installed. + +(defsubst esh-proc-test/emacs-command (command) + "Evaluate COMMAND in a new Emacs batch instance." + (mapconcat #'shell-quote-argument + `(,(expand-file-name invocation-name invocation-directory) + "-Q" "--batch" "--eval" ,(prin1-to-string command)) + " ")) + +(defvar esh-proc-test/emacs-echo + (esh-proc-test/emacs-command '(princ "hello\n")) + "A command that prints \"hello\" to stdout using Emacs.") + +(defvar esh-proc-test/emacs-upcase + (esh-proc-test/emacs-command + '(princ (upcase (concat (read-string "") "\n")))) + "A command that upcases the text from stdin using Emacs.") + +(ert-deftest esh-proc-test/synchronous-proc/simple/interactive () + "Test that synchronous processes work in an interactive shell." + (let ((eshell-supports-asynchronous-processes nil)) + (with-temp-eshell + (eshell-match-command-output esh-proc-test/emacs-echo + "\\`hello\n")))) + +(ert-deftest esh-proc-test/synchronous-proc/simple/command-result () + "Test that synchronous processes work via `eshell-command-result'." + (let ((eshell-supports-asynchronous-processes nil)) + (eshell-command-result-equal esh-proc-test/emacs-echo + "hello\n"))) + +(ert-deftest esh-proc-test/synchronous-proc/pipeline/interactive () + "Test that synchronous pipelines work in an interactive shell." + (let ((eshell-supports-asynchronous-processes nil)) + (with-temp-eshell + (eshell-match-command-output (concat esh-proc-test/emacs-echo " | " + esh-proc-test/emacs-upcase) + "\\`HELLO\n")))) + +(ert-deftest esh-proc-test/synchronous-proc/pipeline/command-result () + "Test that synchronous pipelines work via `eshell-command-result'." + (let ((eshell-supports-asynchronous-processes nil)) + (eshell-command-result-equal (concat esh-proc-test/emacs-echo " | " + esh-proc-test/emacs-upcase) + "HELLO\n"))) + ;; Killing processes commit 97e35b149874a105a9975853a7fcd6f0034ddeab Author: Jim Porter Date: Sat Mar 18 19:18:28 2023 -0700 Avoid shadowing variables in some Eshell command forms * lisp/eshell/esh-cmd.el (eshell-rewrite-for-command): Make 'for-items' an uninterned symbol. (eshell-as-subcommand): Correct docstring. (eshell-do-command-to-value): Mark obsolete. (eshell-command-to-value): Move binding of 'value' outside of the macro's result, and remove call to 'eshell-do-command-to-value'. * test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/subcommand-shadow-value) (esh-cmd-test/for-loop-for-items-shadow): New tests. (esh-cmd-test/for-name-loop, esh-cmd-test/for-name-shadow-loop): Rename to... (esh-cmd-test/for-loop-name, esh-cmd-test/for-loop-name-shadow): ... these. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index d5237ee1f04..f0c6a146dfd 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -542,9 +542,10 @@ eshell-rewrite-for-command implemented via rewriting, rather than as a function." (if (and (equal (car terms) "for") (equal (nth 2 terms) "in")) - (let ((body (car (last terms)))) + (let ((for-items (make-symbol "for-items")) + (body (car (last terms)))) (setcdr (last terms 2) nil) - `(let ((for-items + `(let ((,for-items (append ,@(mapcar (lambda (elem) @@ -552,13 +553,13 @@ eshell-rewrite-for-command elem `(list ,elem))) (nthcdr 3 terms))))) - (while for-items - (let ((,(intern (cadr terms)) (car for-items)) + (while ,for-items + (let ((,(intern (cadr terms)) (car ,for-items)) (eshell--local-vars (cons ',(intern (cadr terms)) eshell--local-vars))) (eshell-protect ,(eshell-invokify-arg body t))) - (setq for-items (cdr for-items))) + (setq ,for-items (cdr ,for-items))) (eshell-close-handles))))) (defun eshell-structure-basic-command (func names keyword test body @@ -901,28 +902,33 @@ eshell-execute-pipeline (symbol-value tailproc)))))) (defmacro eshell-as-subcommand (command) - "Execute COMMAND using a temp buffer. -This is used so that certain Lisp commands, such as `cd', when -executed in a subshell, do not disturb the environment of the main -Eshell buffer." + "Execute COMMAND as a subcommand. +A subcommand creates a local environment so that any changes to +the environment don't propagate outside of the subcommand's +scope. This lets you use commands like `cd' within a subcommand +without changing the current directory of the main Eshell +buffer." `(let ,eshell-subcommand-bindings ,command)) (defmacro eshell-do-command-to-value (object) "Run a subcommand prepared by `eshell-command-to-value'. This avoids the need to use `let*'." + (declare (obsolete nil "30.1")) `(let ((eshell-current-handles (eshell-create-handles value 'overwrite))) (progn ,object (symbol-value value)))) -(defmacro eshell-command-to-value (object) - "Run OBJECT synchronously, returning its result as a string. -Returns a string comprising the output from the command." - `(let ((value (make-symbol "eshell-temp")) - (eshell-in-pipeline-p nil)) - (eshell-do-command-to-value ,object))) +(defmacro eshell-command-to-value (command) + "Run an Eshell COMMAND synchronously, returning its output." + (let ((value (make-symbol "eshell-temp"))) + `(let ((eshell-in-pipeline-p nil) + (eshell-current-handles + (eshell-create-handles ',value 'overwrite))) + ,command + ,value))) ;;;_* Iterative evaluation ;; diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index 94763954622..a7208eb3a0b 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -73,6 +73,13 @@ esh-cmd-test/subcommand-lisp e.g. \"{(+ 1 2)} 3\" => 3" (eshell-command-result-equal "{(+ 1 2)} 3" 3)) +(ert-deftest esh-cmd-test/subcommand-shadow-value () + "Test that the variable `value' isn't shadowed inside subcommands." + (with-temp-eshell + (with-no-warnings (setq-local value "hello")) + (eshell-match-command-output "echo ${echo $value}" + "hello\n"))) + (ert-deftest esh-cmd-test/let-rebinds-after-defer () "Test that let-bound values are properly updated after `eshell-defer'. When inside a `let' block in an Eshell command form, we need to @@ -151,13 +158,13 @@ esh-cmd-test/for-loop-multiple-args (eshell-match-command-output "for i in 1 2 (list 3 4) { echo $i }" "1\n2\n3\n4\n"))) -(ert-deftest esh-cmd-test/for-name-loop () ; bug#15231 +(ert-deftest esh-cmd-test/for-loop-name () ; bug#15231 "Test invocation of a for loop using `name'." (let ((process-environment (cons "name" process-environment))) (eshell-command-result-equal "for name in 3 { echo $name }" 3))) -(ert-deftest esh-cmd-test/for-name-shadow-loop () ; bug#15372 +(ert-deftest esh-cmd-test/for-loop-name-shadow () ; bug#15372 "Test invocation of a for loop using an env-var." (let ((process-environment (cons "name=env-value" process-environment))) (with-temp-eshell @@ -165,6 +172,13 @@ esh-cmd-test/for-name-shadow-loop "echo $name; for name in 3 { echo $name }; echo $name" "env-value\n3\nenv-value\n")))) +(ert-deftest esh-cmd-test/for-loop-for-items-shadow () + "Test that the variable `for-items' isn't shadowed inside for loops." + (with-temp-eshell + (with-no-warnings (setq-local for-items "hello")) + (eshell-match-command-output "for i in 1 { echo $for-items }" + "hello\n"))) + (ert-deftest esh-cmd-test/for-loop-pipe () "Test invocation of a for loop piped to another command." (skip-unless (executable-find "rev")) commit 626f2f744104bc14c28456134cf75ff2f16d9901 Author: Yuan Fu Date: Thu Mar 30 21:58:05 2023 -0700 Add some icons (bug#62562) * etc/images/symbols/README: New file. * etc/images/symbols/*.svg: New icons. diff --git a/etc/images/symbols/README b/etc/images/symbols/README new file mode 100644 index 00000000000..b2c7b8c3179 --- /dev/null +++ b/etc/images/symbols/README @@ -0,0 +1,37 @@ +This directory contains icons for some inline symbols. + +COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES + +Files: *.svg +Author: Yuan Fu +Copyright (C) 2023 Free Software Foundation, Inc. +License: GNU General Public License version 3 or later (see COPYING) + +How I made these icons: I made them with Figma, and exported them into +SVG. I made the shapes with vectors (SVG paths) rather than strokes, +merged all the shapes into a single shape with union operation, and +stripped filling attributes from the SVG files. This way the icons can +be colored like normal text! I'm not exactly sure how it works, but as +long as the icon uses SVG path, and there is only one path in the +file, and there is no filling attributes, the icons can be colored as +text. + +FWIW, this is the command I used to strip filling attributes: + +sed -i 's/fill="none"//g' +sed -i 's/fill="black"//g' + +Naming: Use underscore to separate styles, dash are considered normal +character so you can use it for names. End with the intended optical +size for the icon. + +There should also be an order for all the keywords. Right now we have +directions (left/right), circle, fill, and optical size. Among them, +the order should be + +1. direction +2. circle +3. fill +4. size + +E.g., arrow_right_circle_fill_16. \ No newline at end of file diff --git a/etc/images/symbols/check-mark_16.svg b/etc/images/symbols/check-mark_16.svg new file mode 100644 index 00000000000..10bf765f4d2 --- /dev/null +++ b/etc/images/symbols/check-mark_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/chevron_down_16.svg b/etc/images/symbols/chevron_down_16.svg new file mode 100644 index 00000000000..016e4a5720e --- /dev/null +++ b/etc/images/symbols/chevron_down_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/chevron_left_16.svg b/etc/images/symbols/chevron_left_16.svg new file mode 100644 index 00000000000..84ca3e28d8f --- /dev/null +++ b/etc/images/symbols/chevron_left_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/chevron_right_16.svg b/etc/images/symbols/chevron_right_16.svg new file mode 100644 index 00000000000..9ad6e1bf328 --- /dev/null +++ b/etc/images/symbols/chevron_right_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/chevron_up_16.svg b/etc/images/symbols/chevron_up_16.svg new file mode 100644 index 00000000000..1c4b9c47622 --- /dev/null +++ b/etc/images/symbols/chevron_up_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/cross_16.svg b/etc/images/symbols/cross_16.svg new file mode 100644 index 00000000000..f210cf230b6 --- /dev/null +++ b/etc/images/symbols/cross_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/cross_circle_16.svg b/etc/images/symbols/cross_circle_16.svg new file mode 100644 index 00000000000..1c05c7d8611 --- /dev/null +++ b/etc/images/symbols/cross_circle_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/menu_16.svg b/etc/images/symbols/menu_16.svg new file mode 100644 index 00000000000..bddc433b2eb --- /dev/null +++ b/etc/images/symbols/menu_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/minus_16.svg b/etc/images/symbols/minus_16.svg new file mode 100644 index 00000000000..9cb61d8d379 --- /dev/null +++ b/etc/images/symbols/minus_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/minus_circle_16.svg b/etc/images/symbols/minus_circle_16.svg new file mode 100644 index 00000000000..ced8594774f --- /dev/null +++ b/etc/images/symbols/minus_circle_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/plus_16.svg b/etc/images/symbols/plus_16.svg new file mode 100644 index 00000000000..a4d2f84f318 --- /dev/null +++ b/etc/images/symbols/plus_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/plus_circle_16.svg b/etc/images/symbols/plus_circle_16.svg new file mode 100644 index 00000000000..921857f5a84 --- /dev/null +++ b/etc/images/symbols/plus_circle_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/star_16.svg b/etc/images/symbols/star_16.svg new file mode 100644 index 00000000000..7ccbd6f01a5 --- /dev/null +++ b/etc/images/symbols/star_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/star_fill_16.svg b/etc/images/symbols/star_fill_16.svg new file mode 100644 index 00000000000..0e03675edd5 --- /dev/null +++ b/etc/images/symbols/star_fill_16.svg @@ -0,0 +1,3 @@ + + + diff --git a/etc/images/symbols/star_half_16.svg b/etc/images/symbols/star_half_16.svg new file mode 100644 index 00000000000..6c735ad64ae --- /dev/null +++ b/etc/images/symbols/star_half_16.svg @@ -0,0 +1,3 @@ + + + commit f5891da70aae4deb465e8f193a172fbad0b4485f Author: Mattias Engdegård Date: Sat Apr 1 10:53:50 2023 +0200 ; * src/fns.c: Use if instead of #ifdef * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS, load_unaligned_size_t): Always define these. (Fstring_lessp): Use if instead of #ifdef. diff --git a/src/fns.c b/src/fns.c index 47def5c43b4..e92ef7e4c81 100644 --- a/src/fns.c +++ b/src/fns.c @@ -452,6 +452,9 @@ DEFUN ("compare-strings", Fcompare_strings, Scompare_strings, 6, 7, 0, || defined __s390__ || defined __s390x__) \ && defined __OPTIMIZE__ #define HAVE_FAST_UNALIGNED_ACCESS 1 +#else +#define HAVE_FAST_UNALIGNED_ACCESS 0 +#endif /* Load a word from a possibly unaligned address. */ static inline size_t @@ -462,8 +465,6 @@ load_unaligned_size_t (const void *p) return x; } -#endif - DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, doc: /* Return non-nil if STRING1 is less than STRING2 in lexicographic order. Case is significant. @@ -504,18 +505,16 @@ DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, /* String data is normally allocated with word alignment, but there are exceptions (notably pure strings) so we restrict the wordwise skipping to safe architectures. */ -#ifdef HAVE_FAST_UNALIGNED_ACCESS + if (HAVE_FAST_UNALIGNED_ACCESS) { /* First compare entire machine words. */ int ws = sizeof (size_t); const char *w1 = SSDATA (string1); const char *w2 = SSDATA (string2); - while (b < nb - ws + 1 - && (load_unaligned_size_t (w1 + b) - == load_unaligned_size_t (w2 + b))) + while (b < nb - ws + 1 && load_unaligned_size_t (w1 + b) + == load_unaligned_size_t (w2 + b)) b += ws; } -#endif /* Scan forward to the differing byte. */ while (b < nb && SREF (string1, b) == SREF (string2, b)) commit 4bd1fc59664273c571aba8543940768c68eb336b Author: Po Lu Date: Sat Apr 1 14:25:47 2023 +0800 ; * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): Check in missing edit. diff --git a/src/fns.c b/src/fns.c index 354b3415ec5..47def5c43b4 100644 --- a/src/fns.c +++ b/src/fns.c @@ -462,8 +462,6 @@ load_unaligned_size_t (const void *p) return x; } -#else -#define HAVE_FAST_UNALIGNED_ACCESS 0 #endif DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, commit c10c545ef26ef0be00ec8526d30b8c57141a3683 Author: Po Lu Date: Sat Apr 1 14:24:22 2023 +0800 ; * src/fns.c (Fstring_lessp): Fix coding style. diff --git a/src/fns.c b/src/fns.c index 90bb3fac178..354b3415ec5 100644 --- a/src/fns.c +++ b/src/fns.c @@ -512,8 +512,9 @@ DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, int ws = sizeof (size_t); const char *w1 = SSDATA (string1); const char *w2 = SSDATA (string2); - while (b < nb - ws + 1 && load_unaligned_size_t (w1 + b) - == load_unaligned_size_t (w2 + b)) + while (b < nb - ws + 1 + && (load_unaligned_size_t (w1 + b) + == load_unaligned_size_t (w2 + b))) b += ws; } #endif commit 5276c0890586b10bdbb749803bc1985bf03d1015 Author: Po Lu Date: Sat Apr 1 14:23:32 2023 +0800 ; * src/fns.c (Fstring_lessp): Port to RISCs. diff --git a/src/fns.c b/src/fns.c index 94505eda444..90bb3fac178 100644 --- a/src/fns.c +++ b/src/fns.c @@ -506,7 +506,7 @@ DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, /* String data is normally allocated with word alignment, but there are exceptions (notably pure strings) so we restrict the wordwise skipping to safe architectures. */ - if (HAVE_FAST_UNALIGNED_ACCESS) +#ifdef HAVE_FAST_UNALIGNED_ACCESS { /* First compare entire machine words. */ int ws = sizeof (size_t); @@ -516,6 +516,7 @@ DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, == load_unaligned_size_t (w2 + b)) b += ws; } +#endif /* Scan forward to the differing byte. */ while (b < nb && SREF (string1, b) == SREF (string2, b)) commit 204b652493d88cfcef70095fb9adf930554b283f Author: Stefan Kangas Date: Sat Apr 1 06:00:47 2023 +0200 Update publicsuffix.txt from upstream * etc/publicsuffix.txt: Update from https://publicsuffix.org/list/public_suffix_list.dat dated 2023-03-18 16:17:52 UTC. diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt index 3b920e67ed0..9d0dfc04ea9 100644 --- a/etc/publicsuffix.txt +++ b/etc/publicsuffix.txt @@ -7189,7 +7189,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-02-22T15:15:03Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-03-18T15:13:13Z // This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -8898,9 +8898,6 @@ limo // lincoln : 2014-11-13 Ford Motor Company lincoln -// linde : 2014-12-04 Linde Aktiengesellschaft -linde - // link : 2013-11-14 Nova Registry Ltd link @@ -8967,9 +8964,6 @@ luxe // luxury : 2013-10-17 Luxury Partners, LLC luxury -// macys : 2015-07-31 Macys, Inc. -macys - // madrid : 2014-05-01 Comunidad de Madrid madrid commit 90be1f3adbba9e01baf61bb45bf4482131bbab32 Author: Stefan Kangas Date: Sat Apr 1 05:10:48 2023 +0200 ; Auto-commit of loaddefs files. diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index fe46b220da5..acf8a1d2556 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -3779,14 +3779,18 @@ "cc-styles" ;;; Generated autoloads from progmodes/cc-vars.el +(autoload 'c-string-list-p "cc-vars" "\ +Return non-nil if VAL is a list of strings. + +(fn VAL)") (put 'c-basic-offset 'safe-local-variable 'integerp) (put 'c-backslash-column 'safe-local-variable 'integerp) - (put 'c-font-lock-extra-types 'safe-local-variable #'c-list-of-strings) - (put 'c++-font-lock-extra-types 'safe-local-variable #'c-list-of-strings) - (put 'objc-font-lock-extra-types 'safe-local-variable #'c-list-of-strings) - (put 'java-font-lock-extra-types 'safe-local-variable #'c-list-of-strings) - (put 'idl-font-lock-extra-types 'safe-local-variable #'c-list-of-strings) - (put 'pike-font-lock-extra-types 'safe-local-variable #'c-list-of-strings) + (put 'c-font-lock-extra-types 'safe-local-variable #'c-string-list-p) + (put 'c++-font-lock-extra-types 'safe-local-variable #'c-string-list-p) + (put 'objc-font-lock-extra-types 'safe-local-variable #'c-string-list-p) + (put 'java-font-lock-extra-types 'safe-local-variable #'c-string-list-p) + (put 'idl-font-lock-extra-types 'safe-local-variable #'c-string-list-p) + (put 'pike-font-lock-extra-types 'safe-local-variable #'c-string-list-p) (put 'c-file-style 'safe-local-variable 'string-or-null-p) (register-definition-prefixes "cc-vars" '("awk-mode-hook" "c++-" "c-" "defcustom-c-stylevar" "idl-" "java-" "objc-" "pike-")) @@ -8234,15 +8238,23 @@ 'define-global-minor-mode TURN-ON is a function that will be called with no args in every buffer and that should try to turn MODE on if applicable for that buffer. -Each of KEY VALUE is a pair of CL-style keyword arguments. :predicate -specifies which major modes the globalized minor mode should be switched on -in. As the minor mode defined by this function is always global, any -:global keyword is ignored. Other keywords have the same meaning as in -`define-minor-mode', which see. In particular, :group specifies the custom -group. The most useful keywords are those that are passed on to the -`defcustom'. It normally makes no sense to pass the :lighter or :keymap -keywords to `define-globalized-minor-mode', since these are usually passed -to the buffer-local version of the minor mode. +Each of KEY VALUE is a pair of CL-style keyword arguments. +The :predicate argument specifies in which major modes should the +globalized minor mode be switched on. The value should be t (meaning +switch on the minor mode in all major modes), nil (meaning don't +switch on in any major mode), a list of modes (meaning switch on only +in those modes and their descendants), or a list (not MODES...), +meaning switch on in any major mode except MODES. The value can also +mix all of these forms, see the info node `Defining Minor Modes' for +details. +As the minor mode defined by this function is always global, any +:global keyword is ignored. +Other keywords have the same meaning as in `define-minor-mode', +which see. In particular, :group specifies the custom group. +The most useful keywords are those that are passed on to the `defcustom'. +It normally makes no sense to pass the :lighter or :keymap keywords +to `define-globalized-minor-mode', since these are usually passed to +the buffer-local version of the minor mode. BODY contains code to execute each time the mode is enabled or disabled. It is executed after toggling the mode, and before running @@ -9218,7 +9230,7 @@ "edt-vt100" ;;; Generated autoloads from progmodes/eglot.el -(push (purecopy '(eglot 1 12)) package--builtin-versions) +(push (purecopy '(eglot 1 13)) package--builtin-versions) (autoload 'eglot "eglot" "\ Start LSP server in support of PROJECT's buffers under MANAGED-MAJOR-MODE. @@ -22454,7 +22466,7 @@ "opascal" ;;; Generated autoloads from org/org.el -(push (purecopy '(org 9 6 1)) package--builtin-versions) +(push (purecopy '(org 9 6 2)) package--builtin-versions) (autoload 'org-babel-do-load-languages "org" "\ Load the languages defined in `org-babel-load-languages'. @@ -23553,48 +23565,6 @@ "package" (autoload 'package-vc-install-selected-packages "package-vc" "\ Ensure packages specified in `package-vc-selected-packages' are installed." t) -(defvar package-vc-selected-packages 'nil "\ -List of packages that must be installed. -Each member of the list is of the form (NAME . SPEC), where NAME -is a symbol designating the package and SPEC is one of: - -- nil, if any package version can be installed; -- a version string, if that specific revision is to be installed; -- a property list, describing a package specification. Valid - key/value pairs are - - `:url' (string) - The URL of the repository used to fetch the package source. - - `:branch' (string) - If given, the name of the branch to checkout after cloning the directory. - - `:lisp-dir' (string) - The repository-relative name of the directory to use for loading the Lisp - sources. If not given, the value defaults to the root directory - of the repository. - - `:main-file' (string) - The main file of the project, relevant to gather package metadata. - If not given, the assumed default is the package name with \".el\" - appended to it. - - `:vc-backend' (symbol) - A symbol of the VC backend to use for cloning the package. The - value ought to be a member of `vc-handled-backends'. If omitted, - `vc-clone' will fall back onto the archive default or on - `package-vc-default-backend'. - - All other keys are ignored. - -This user option differs from `package-selected-packages' in that -it is meant to be specified manually. If you want to install all -the packages in the list, you cal also use -`package-vc-install-selected-packages'. - -Note that this option will not override an existing source -package installation or revert the checked out revision.") -(custom-autoload 'package-vc-selected-packages "package-vc" nil) (autoload 'package-vc-update-all "package-vc" "\ Attempt to update all installed VC packages." t) (autoload 'package-vc-update "package-vc" "\ @@ -36975,7 +36945,7 @@ 'xref-pop-marker-stack Go back to the previous position in xref history. To undo, use \\[xref-go-forward]." t) (autoload 'xref-go-forward "xref" "\ -Got to the point where a previous \\[xref-go-back] was invoked." t) +Go to the point where a previous \\[xref-go-back] was invoked." t) (autoload 'xref-marker-stack-empty-p "xref" "\ Whether the xref back-history is empty.") (autoload 'xref-forward-history-empty-p "xref" "\ commit 4c0e40b75ba7c0ec1ee18eb577418f2ea5199a60 Author: Andrew G Cohen Date: Thu Mar 16 18:43:35 2023 +0800 Allow null date in gnus-icalendar-event--decode-datefield * lisp/gnus/gnus-icalendar.el: (gnus-icalendar-event--decode-datefield): Don't throw an error if the event date is missing. diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el index 0d776cd1bca..adbc39547ff 100644 --- a/lisp/gnus/gnus-icalendar.el +++ b/lisp/gnus/gnus-icalendar.el @@ -165,7 +165,7 @@ gnus-icalendar-event--decode-datefield (icalendar--get-event-property-attributes event field) zone-map)) (dtdate-dec (icalendar--decode-isodatetime dtdate nil dtdate-zone))) - (encode-time dtdate-dec))) + (when dtdate-dec (encode-time dtdate-dec)))) (defun gnus-icalendar-event--find-attendee (ical name-or-email) (let* ((event (car (icalendar--all-events ical))) commit 2c9ea31999d2f69f8bca4fe352dd0f74c6766c54 Author: Andrew G Cohen Date: Thu Mar 9 16:05:31 2023 +0800 Reset 'gnus-current-window-configuration' on edit-form exit. * lisp/gnus/gnus.el: New variable gnus-prev-cwc. * lisp/gnus/gnus-art.el (gnus-article-edit-mode): New local variable gnus-prev-cwc. (gnus-article-edit-article): Store original gnus-current-window-configuration as gnus-prev-cwc. (gnus-article-edit-done, gnus-article-edit-exit): Restore gnus-current-window-configuration from gnus-prev-cwc. * lisp/gnus/gnus-eform.el (gnus-edit-form-mode): New local variable gnus-prev-cwc. (gnus-edit-form): Store original gnus-current-window-configuration as gnus-prev-cwc. (gnus-edit-form-done, gnus-edit-form-exit): Restore gnus-current-window-configuration from gnus-prev-cwc. diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index ce7a4488a7f..6a7a3f41746 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -7390,6 +7390,7 @@ gnus-article-edit-mode \\{gnus-article-edit-mode-map}" (make-local-variable 'gnus-article-edit-done-function) (make-local-variable 'gnus-prev-winconf) + (make-local-variable 'gnus-prev-cwc) (setq-local font-lock-defaults '(message-font-lock-keywords t)) (setq-local mail-header-separator "") (setq-local gnus-article-edit-mode t) @@ -7420,7 +7421,8 @@ gnus-article-edit (defun gnus-article-edit-article (start-func exit-func &optional quiet) "Start editing the contents of the current article buffer." - (let ((winconf (current-window-configuration))) + (let ((winconf (current-window-configuration)) + (cwc gnus-current-window-configuration)) (set-buffer gnus-article-buffer) (let ((message-auto-save-directory ;; Don't associate the article buffer with a draft file. @@ -7431,6 +7433,7 @@ gnus-article-edit-article (gnus-configure-windows 'edit-article) (setq gnus-article-edit-done-function exit-func) (setq gnus-prev-winconf winconf) + (setq gnus-prev-cwc cwc) (unless quiet (gnus-message 6 "C-c C-c to end edits")))) @@ -7440,7 +7443,8 @@ gnus-article-edit-done (let ((func gnus-article-edit-done-function) (buf (current-buffer)) (start (window-start)) - (winconf gnus-prev-winconf)) + (winconf gnus-prev-winconf) + (cwc gnus-prev-cwc)) (widen) ;; Widen it in case that users narrowed the buffer. (funcall func arg) (set-buffer buf) @@ -7458,6 +7462,7 @@ gnus-article-edit-done (set-text-properties (point-min) (point-max) nil) (gnus-article-mode) (set-window-configuration winconf) + (setq gnus-current-window-configuration cwc) (set-buffer buf) (set-window-start (get-buffer-window buf) start) (set-window-point (get-buffer-window buf) (point))) @@ -7479,10 +7484,12 @@ gnus-article-edit-exit (erase-buffer) (if (gnus-buffer-live-p gnus-original-article-buffer) (insert-buffer-substring gnus-original-article-buffer)) - (let ((winconf gnus-prev-winconf)) + (let ((winconf gnus-prev-winconf) + (cwc gnus-prev-cwc)) (kill-all-local-variables) (gnus-article-mode) (set-window-configuration winconf) + (setq gnus-current-window-configuration cwc) ;; Tippy-toe some to make sure that point remains where it was. (with-current-buffer curbuf (set-window-start (get-buffer-window (current-buffer)) window-start) diff --git a/lisp/gnus/gnus-eform.el b/lisp/gnus/gnus-eform.el index 958d819048f..cc5beb16a34 100644 --- a/lisp/gnus/gnus-eform.el +++ b/lisp/gnus/gnus-eform.el @@ -70,17 +70,20 @@ gnus-edit-form-mode (when (gnus-visual-p 'group-menu 'menu) (gnus-edit-form-make-menu-bar)) (make-local-variable 'gnus-edit-form-done-function) - (make-local-variable 'gnus-prev-winconf)) + (make-local-variable 'gnus-prev-winconf) + (make-local-variable 'gnus-prev-cwc)) (defun gnus-edit-form (form documentation exit-func &optional layout) "Edit FORM in a new buffer. Call EXIT-FUNC on exit. Display DOCUMENTATION in the beginning of the buffer. The optional LAYOUT overrides the `edit-form' window layout." - (let ((winconf (current-window-configuration))) + (let ((winconf (current-window-configuration)) + (cwc gnus-current-window-configuration)) (set-buffer (gnus-get-buffer-create gnus-edit-form-buffer)) (gnus-configure-windows (or layout 'edit-form)) (gnus-edit-form-mode) + (setq gnus-prev-cwc cwc) (setq gnus-prev-winconf winconf) (setq gnus-edit-form-done-function exit-func) (erase-buffer) @@ -113,9 +116,11 @@ gnus-edit-form-done (defun gnus-edit-form-exit () "Kill the current buffer." (interactive nil gnus-edit-form-mode) - (let ((winconf gnus-prev-winconf)) + (let ((winconf gnus-prev-winconf) + (cwc gnus-prev-cwc)) (kill-buffer (current-buffer)) - (set-window-configuration winconf))) + (set-window-configuration winconf) + (setq gnus-current-window-configuration cwc))) (provide 'gnus-eform) diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index efab58437e9..fc8518512ee 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el @@ -2445,6 +2445,7 @@ gnus-moderated-hashtb ;; Save window configuration. (defvar gnus-prev-winconf nil) +(defvar gnus-prev-cwc nil) (defvar gnus-reffed-article-number nil) commit 9acfb7662c5c25fe9bfa7156da9916f58dfde9a5 Author: Andrew G Cohen Date: Mon Mar 14 07:59:25 2022 +0800 Use completion when mark limiting in gnus summary buffers * lisp/gnus/gnus-sum.el (gnus-summary-limit-to-marks) (gnus-summary-limit-exclude-marks): Use completing-read to complete on marks in the current summary buffer. diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index f13db8d9167..9a632922deb 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -8501,7 +8501,15 @@ gnus-summary-limit-exclude-marks If REVERSE, limit the summary buffer to articles that are marked with MARKS. MARKS can either be a string of marks or a list of marks. Returns how many articles were removed." - (interactive "sMarks: " gnus-summary-mode) + (interactive + (list + (completing-read "Marks:" + (let ((mark-list '())) + (mapc (lambda (datum) + (cl-pushnew (gnus-data-mark datum) mark-list)) + gnus-newsgroup-data) + (mapcar 'char-to-string mark-list))) + current-prefix-arg) gnus-summary-mode) (gnus-summary-limit-to-marks marks t)) (defun gnus-summary-limit-to-marks (marks &optional reverse) @@ -8510,7 +8518,15 @@ gnus-summary-limit-to-marks not marked with MARKS. MARKS can either be a string of marks or a list of marks. Returns how many articles were removed." - (interactive "sMarks: \nP" gnus-summary-mode) + (interactive + (list + (completing-read "Marks:" + (let ((mark-list '())) + (mapc (lambda (datum) + (cl-pushnew (gnus-data-mark datum) mark-list)) + gnus-newsgroup-data) + (mapcar 'char-to-string mark-list))) + current-prefix-arg) gnus-summary-mode) (prog1 (let ((data gnus-newsgroup-data) (marks (if (listp marks) marks commit 69f20365543f30263b9c6856071d5a8610490a24 Author: Andrew G Cohen Date: Mon Mar 14 07:47:39 2022 +0800 Track article while moving between gnus groups * lisp/gnus/gnus-sum.el (gnus-current-move-article): New variable to track article while moving. (gnus-summary-move-article): Set gnus-current-move-article when moving/copying/crossposting or respooling. diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 0e81f95cd15..f13db8d9167 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -1408,6 +1408,7 @@ gnus-inhibit-limiting (defvar gnus-newsgroup-adaptive-score-file nil) (defvar gnus-current-score-file nil) (defvar gnus-current-move-group nil) +(defvar gnus-current-move-article nil) (defvar gnus-current-copy-group nil) (defvar gnus-current-crosspost-group nil) (defvar gnus-newsgroup-display nil) @@ -10248,6 +10249,7 @@ gnus-summary-move-article article gnus-newsgroup-name (current-buffer) t))) ;; run the move/copy/crosspost/respool hook + (set (intern "gnus-current-move-article") (cdr art-group)) (run-hook-with-args 'gnus-summary-article-move-hook action (gnus-data-header (gnus-data-find article)) commit 6523359dfe212633f5bd274b29a1f5e613384c79 Author: Mattias Engdegård Date: Fri Mar 31 20:13:18 2023 +0200 Make string-lessp vectorisation safer Use memcpy for loading unaligned words on platforms where this can be done efficiently. This guards against problems arising from future compiler autovectorisation improvements that might cause instructions that require aligned addresses to be emitted, and should also work with an address sanitiser enabled. * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): Only define when optimising. (load_unaligned_size_t): New. (Fstring_lessp): Use load_unaligned_size_t. * src/lisp.h (UNALIGNED_LOAD_SIZE): Remove now unused macro. diff --git a/src/fns.c b/src/fns.c index 0af9b725c7a..94505eda444 100644 --- a/src/fns.c +++ b/src/fns.c @@ -439,17 +439,29 @@ DEFUN ("compare-strings", Fcompare_strings, Scompare_strings, 6, 7, 0, } /* Check whether the platform allows access to unaligned addresses for - size_t integers without trapping or undue penalty (a few cycles is OK). + size_t integers without trapping or undue penalty (a few cycles is OK), + and that a word-sized memcpy can be used to generate such an access. This whitelist is incomplete but since it is only used to improve performance, omitting cases is safe. */ -#if defined __x86_64__|| defined __amd64__ \ - || defined __i386__ || defined __i386 \ - || defined __arm64__ || defined __aarch64__ \ - || defined __powerpc__ || defined __powerpc \ - || defined __ppc__ || defined __ppc \ - || defined __s390__ || defined __s390x__ +#if (defined __x86_64__|| defined __amd64__ \ + || defined __i386__ || defined __i386 \ + || defined __arm64__ || defined __aarch64__ \ + || defined __powerpc__ || defined __powerpc \ + || defined __ppc__ || defined __ppc \ + || defined __s390__ || defined __s390x__) \ + && defined __OPTIMIZE__ #define HAVE_FAST_UNALIGNED_ACCESS 1 + +/* Load a word from a possibly unaligned address. */ +static inline size_t +load_unaligned_size_t (const void *p) +{ + size_t x; + memcpy (&x, p, sizeof x); + return x; +} + #else #define HAVE_FAST_UNALIGNED_ACCESS 0 #endif @@ -497,17 +509,12 @@ DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, if (HAVE_FAST_UNALIGNED_ACCESS) { /* First compare entire machine words. */ - typedef size_t word_t; - int ws = sizeof (word_t); - const word_t *w1 = (const word_t *) SDATA (string1); - const word_t *w2 = (const word_t *) SDATA (string2); - while (b < nb - ws + 1) - { - if (UNALIGNED_LOAD_SIZE (w1, b / ws) - != UNALIGNED_LOAD_SIZE (w2, b / ws)) - break; - b += ws; - } + int ws = sizeof (size_t); + const char *w1 = SSDATA (string1); + const char *w2 = SSDATA (string2); + while (b < nb - ws + 1 && load_unaligned_size_t (w1 + b) + == load_unaligned_size_t (w2 + b)) + b += ws; } /* Scan forward to the differing byte. */ diff --git a/src/lisp.h b/src/lisp.h index cacd318c26f..165fa47b0b3 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -5305,26 +5305,6 @@ __lsan_ignore_object (void const *p) } #endif -/* If built with USE_SANITIZER_UNALIGNED_LOAD defined, use compiler - provided ASan functions to perform unaligned loads, allowing ASan - to catch bugs which it might otherwise miss. */ -#if defined HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H \ - && defined ADDRESS_SANITIZER \ - && defined USE_SANITIZER_UNALIGNED_LOAD -# include -# if (SIZE_MAX == UINT64_MAX) -# define UNALIGNED_LOAD_SIZE(a, i) \ - (size_t) __sanitizer_unaligned_load64 ((void *) ((a) + (i))) -# elif (SIZE_MAX == UINT32_MAX) -# define UNALIGNED_LOAD_SIZE(a, i) \ - (size_t) __sanitizer_unaligned_load32 ((void *) ((a) + (i))) -# else -# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i)) -# endif -#else -# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i)) -#endif - extern void xputenv (const char *); extern char *egetenv_internal (const char *, ptrdiff_t); commit 3bdbb66efb9895b8ed55270075fa7d8329f8d36b Author: Eli Zaretskii Date: Fri Mar 31 16:18:09 2023 +0300 ; CONTRIBUTE: Minor stylistic changes. diff --git a/CONTRIBUTE b/CONTRIBUTE index 674b4e5b18c..82e5b0a1018 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -110,7 +110,7 @@ admin/notes/bug-triage. Any change that matters to end-users should have an entry in etc/NEWS. Try to start each NEWS entry with a sentence that summarizes the entry -and takes just one line -- this will allow to read NEWS in Outline +and takes just one line -- this will allow reading NEWS in Outline mode after hiding the body of each entry. Doc-strings should be updated together with the code. @@ -123,7 +123,7 @@ Think about whether your change requires updating the manuals. If you know it does not, mark the NEWS entry with "---". If you know that *all* the necessary documentation updates have been made as part of your changes or those by others, mark the entry with "+++". -Otherwise do not mark it. +Otherwise, do not mark it. If your change requires updating the manuals to document new functions/commands/variables/faces, then use the proper Texinfo @@ -400,7 +400,7 @@ the commit to master, by starting the commit message with "Backport:". The gitmerge function excludes these commits from the merge to the master. Some changes should not be merged to master at all, for whatever -reasons. These should be marked by including something like "Do not +reason. These should be marked by including something like "Do not merge to master" or anything that matches gitmerge-skip-regexp (see admin/gitmerge.el) in the commit message. @@ -449,8 +449,8 @@ files intended for use only with Emacs version 24.5 and later. *** Useful files in the admin/ directory -See all the files in admin/notes/* . In particular, see -admin/notes/newfile, see admin/notes/repo. +See all the files in 'admin/notes/*'. In particular, see +'admin/notes/newfile' and 'admin/notes/repo'. The file admin/MAINTAINERS records the areas of interest of frequent Emacs contributors. If you are making changes in one of the files commit 6f496105e392af45c2248b4523ef19804837a8a6 Author: Bob Rogers Date: Fri Mar 31 09:57:32 2023 +0200 Allow old input to include continuation lines in shell-mode * lisp/shell.el (shell-get-old-input-include-continuation-lines): New defcustom (default nil). (shell-get-old-input): New function. Like 'comint-get-old-input-default' but include all continuation lines if 'shell-get-old-input-include-continuation-lines' is non-nil. (shell-mode): Install shell-get-old-input. (Bug#61069) * etc/NEWS: Advertise the new defcustom. diff --git a/etc/NEWS b/etc/NEWS index f27cafb3d41..67e1a02d587 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -174,6 +174,14 @@ correctly unloads Eshell and all of its modules. After manually editing 'eshell-aliases-file', you can use this command to load the edited aliases. +** Shell Mode + ++++ +*** New user option 'shell-get-old-input-include-continuation-lines'. +When this user option is non-nil, 'shell-get-old-input' (C-RET) +includes multiple shell "\" continuation lines from command output. +Default is nil. + ** Prog Mode +++ diff --git a/lisp/shell.el b/lisp/shell.el index 5cf108bfa3b..b74442f1961 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -366,6 +366,12 @@ shell-has-auto-cd :group 'shell-directories :version "28.1") +(defcustom shell-get-old-input-include-continuation-lines nil + "Whether `shell-get-old-input' includes \"\\\" lines." + :type 'boolean + :group 'shell + :version "30.1") + (defcustom shell-kill-buffer-on-exit nil "Kill a shell buffer after the shell process terminates." :type 'boolean @@ -506,6 +512,39 @@ shell--parse-pcomplete-arguments (push (mapconcat #'identity (nreverse arg) "") args))) (cons (nreverse args) (nreverse begins))))) +(defun shell-get-old-input () + "Default for `comint-get-old-input' in `shell-mode'. +If `comint-use-prompt-regexp' is nil, then either +return the current input field (if point is on an input field), or the +current line (if point is on an output field). +If `comint-use-prompt-regexp' is non-nil, then return +the current line, with any initial string matching the regexp +`comint-prompt-regexp' removed. +In either case, if `shell-get-old-input-include-continuation-lines' +is non-nil and the current line ends with a backslash, the next +line is also included and examined for a backslash, ending with a +final line without a backslash." + (let (field-prop bof) + (if (and (not comint-use-prompt-regexp) + ;; Make sure we're in an input rather than output field. + (not (setq field-prop (get-char-property + (setq bof (field-beginning)) 'field)))) + (field-string-no-properties bof) + (comint-bol) + (let ((start (point))) + (cond ((or comint-use-prompt-regexp + (eq field-prop 'output)) + (goto-char (line-end-position)) + (when shell-get-old-input-include-continuation-lines + ;; Include continuation lines as long as the current + ;; line ends with a backslash. + (while (and (not (eobp)) + (= (char-before) ?\\)) + (goto-char (line-end-position 2))))) + (t + (goto-char (field-end)))) + (buffer-substring-no-properties start (point)))))) + ;;;###autoload (defun split-string-shell-command (string) "Split STRING (a shell command) into a list of strings. @@ -642,6 +681,7 @@ shell-mode (setq-local font-lock-defaults '(shell-font-lock-keywords t)) (setq-local shell-dirstack nil) (setq-local shell-last-dir nil) + (setq-local comint-get-old-input #'shell-get-old-input) ;; People expect Shell mode to keep the last line of output at ;; window bottom. (setq-local scroll-conservatively 101) commit d0eb12e8d3c9d6f95b8493e05857d583c29dd0fe Author: Shynur Date: Fri Mar 31 19:49:39 2023 +0800 Fix typo in section 14.1 of Emacs Manual * doc/emacs/display.texi (Scrolling): Fix typo. (Bug#62569) Copyright-paperwork-exempt: yes diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 7ec843180b8..6b2eb014c82 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -154,7 +154,7 @@ Scrolling @vindex redisplay-skip-fontification-on-input Finally, a third alternative to these variables is @code{redisplay-skip-fontification-on-input}. If this variable is -non-@code{nil}, skip some fontifications is there's input pending. +non-@code{nil}, skip some fontifications if there's input pending. This usually does not affect the display because redisplay is completely skipped anyway if input was pending, but it can make scrolling smoother by avoiding unnecessary fontification. commit c96bd1bf8843519bafc8d0dcb8ab096c49eef6cd Author: Michael Albinus Date: Fri Mar 31 14:17:54 2023 +0200 * test/infra/Dockerfile.emba (emacs-eglot): Adapt software selection. diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba index f8a10f913ef..d7b0b0d3ded 100644 --- a/test/infra/Dockerfile.emba +++ b/test/infra/Dockerfile.emba @@ -72,15 +72,6 @@ RUN apt-get update && \ RUN bash -c "$(wget --no-check-certificate -O - https://apt.llvm.org/llvm.sh)" RUN ln -s /usr/bin/clangd-15 /usr/bin/clangd -# A recent pylsp. In Debian bookworm there is the package -# python3-pylsp. -RUN apt-get update && \ - apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \ - python3-pyls \ - && rm -rf /var/lib/apt/lists/* -# eglot.el knows pyls. However, eglot-tests.el checks only for pylsp. -RUN ln -s /usr/bin/pyls /usr/bin/pylsp - COPY . /checkout WORKDIR /checkout RUN ./autogen.sh autoconf commit 06743df33a87a08ab2e69e797659e7ba9beb2dbb Author: Michael Albinus Date: Fri Mar 31 09:45:23 2023 +0200 * lisp/net/tramp.el (tramp-accept-process-output): Use `with-local-quit'. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index defdb2bd546..b1bd93410bc 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -5815,7 +5815,7 @@ tramp-accept-process-output (v (process-get proc 'tramp-vector))) (dolist (p (delq proc (process-list))) (when (tramp-file-name-equal-p v (process-get p 'tramp-vector)) - (accept-process-output p 0 nil t)))) + (with-local-quit (accept-process-output p 0 nil t))))) (with-current-buffer (process-buffer proc) (let ((inhibit-read-only t) commit b2fbec37f3909cb3274689b1f10bee6b187a759f Author: João Távora Date: Thu Mar 30 23:55:57 2023 +0100 ; * etc/EGLOT-NEWS: Clarify scope of topmost section diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index dc77e4fe624..d10412afd33 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -18,7 +18,7 @@ That is, to look up issue github#1234, go to https://github.com/joaotavora/eglot/issues/1234. -* Changes in Eglot 1.12 (13/03/2023) +* Changes in Eglot bundled with Emacs 29 ** LSP inlay hints are now supported. Inlay hints are small text annotations not unlike diagnostics, but commit 131ec049db03a3a90c887edf67a8de86ab47008a Author: João Távora Date: Thu Mar 30 23:52:27 2023 +0100 Eglot: unbreak eglot-extend-to-xref on w32 Because of a drive-letter casing mismatch between 'buffer-file-name' and the return value of 'url-generic-parse-url', the hash-table test 'equal' in 'eglot-current-server' failed. This failed to recognize that the file xref landed us on really is managed by the language server that facilitated that jump. The function w32-long-file-name seems to convert "C:/Users/" to "c:/Users" consistently and so is a good addition to eglot--uri-to-path. * lisp/progmodes/eglot.el (eglot--uri-to-path): Use w32-long-file-name. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3f5245397a0..8f64f849d72 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1620,10 +1620,9 @@ eglot--uri-to-path (normalized (if (and (not remote-prefix) (eq system-type 'windows-nt) (cl-plusp (length retval))) - (substring retval 1) + (w32-long-file-name (substring retval 1)) retval))) (concat remote-prefix normalized)) - uri))) (defun eglot--snippet-expansion-fn () commit 0622e1f29f6e4c7a361f5e78ac09bed6466c4b57 Author: João Távora Date: Thu Mar 30 19:47:00 2023 +0100 Eglot: ensure server shutdown turns off eglot-inlay-hints-mode * lisp/progmodes/eglot.el (eglot--managed-mode-off): Turn off eglot-inlay-hints-mode. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index b4116dc4aaf..3f5245397a0 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1886,6 +1886,7 @@ eglot--managed-mode (defun eglot--managed-mode-off () "Turn off `eglot--managed-mode' unconditionally." (remove-overlays nil nil 'eglot--overlay t) + (eglot-inlay-hints-mode -1) (eglot--managed-mode -1)) (defun eglot-current-server () commit 59f66ea3027fc7b6c1eb977b47de0bd8d610d3c3 Author: Philip Kaludercic Date: Thu Mar 30 23:25:20 2023 +0200 ; * lisp/emacs-lisp/package-vc.el: Remove completed item from TODO diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el index d57095a83d1..2b73e187b14 100644 --- a/lisp/emacs-lisp/package-vc.el +++ b/lisp/emacs-lisp/package-vc.el @@ -41,9 +41,6 @@ ;; - Allow maintaining patches that are ported back onto regular ;; packages and maintained between versions. -;; -;; - Add a heuristic for guessing a `:lisp-dir' when cloning directly -;; from a URL. ;;; Code: commit d23dc3dd7e31526e5748332614ab4501984ad625 Author: Philip Kaludercic Date: Thu Mar 30 23:24:08 2023 +0200 ; * lisp/emacs-lisp/package-vc.el (package-vc): Fix manual reference diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el index 253b35f1f1a..d57095a83d1 100644 --- a/lisp/emacs-lisp/package-vc.el +++ b/lisp/emacs-lisp/package-vc.el @@ -58,7 +58,7 @@ (defgroup package-vc nil "Manage packages from VC checkouts." :group 'package - :link '(custom-manual "(emacs) Package from Source") + :link '(custom-manual "(emacs) Fetching Package Sources") :prefix "package-vc-" :version "29.1") commit 4508a024e81834cfb01c6f7984182e1a6cbb91ea Author: Eli Zaretskii Date: Thu Mar 30 16:34:41 2023 +0300 ; Clarify documentation of 'cursor' text property * doc/lispref/text.texi (Special Properties): Clarify that 'cursor' property is only considered when the overlay hides buffer text on display. (Bug#62540) diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 0a48beab8b8..4c13185b0dd 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -3765,18 +3765,19 @@ Special Properties @item cursor @kindex cursor @r{(text property)} Normally, the cursor is displayed at the beginning or the end of any -overlay and text property strings present at the current buffer -position. You can instead tell Emacs to place the cursor on any -desired character of these strings by giving that character a -non-@code{nil} @code{cursor} text property. In addition, if the value -of the @code{cursor} property is an integer, it specifies the number -of buffer's character positions, starting with the position where the -overlay or the @code{display} property begins, for which the cursor -should be displayed on that character. Specifically, if the value of -the @code{cursor} property of a character is the number @var{n}, the -cursor will be displayed on this character for any buffer position in -the range @code{[@var{ovpos}..@var{ovpos}+@var{n})}, where @var{ovpos} -is the overlay's starting position given by @code{overlay-start} +overlay and text property strings that ``hide'' (i.e., are displayed +instead of) the current buffer position. You can instead tell Emacs +to place the cursor on any desired character of these strings by +giving that character a non-@code{nil} @code{cursor} text property. +In addition, if the value of the @code{cursor} property is an integer, +it specifies the number of buffer's character positions, starting with +the position where the overlay or the @code{display} property begins, +for which the cursor should be displayed on that character. +Specifically, if the value of the @code{cursor} property of a +character is the number @var{n}, the cursor will be displayed on this +character for any buffer position in the range +@code{[@var{ovpos}..@var{ovpos}+@var{n})}, where @var{ovpos} is the +overlay's starting position given by @code{overlay-start} (@pxref{Managing Overlays}), or the position where the @code{display} text property begins in the buffer. commit d2e82817a3f341e426c220e98048e1784d1e3076 Author: Yuan Fu Date: Fri Mar 24 16:45:15 2023 -0700 Add two typescript-ts-mode faces (bug#62429) * lisp/progmodes/typescript-ts-mode.el: (typescript-ts-mode-jsx-tag-face) (typescript-ts-mode-jsx-attribute-face): New faces. (typescript-ts-mode--font-lock-settings): Use new faces. (tsx-ts-mode): Mention the new faces in the docstring. diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index a9ca85d5d35..23815c79906 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -41,6 +41,16 @@ typescript-ts-mode-indent-offset :safe 'integerp :group 'typescript) +(defface typescript-ts-jsx-tag-face + '((t . (:inherit font-lock-function-call-face))) + "Face for HTML tags like
and

in JSX." + :group 'typescript) + +(defface typescript-ts-jsx-attribute-face + '((t . (:inherit font-lock-constant-face))) + "Face for HTML attributes like name and id in JSX." + :group 'typescript) + (defvar typescript-ts-mode--syntax-table (let ((table (make-syntax-table))) ;; Taken from the cc-langs version @@ -284,17 +294,17 @@ typescript-ts-mode--font-lock-settings :feature 'jsx `((jsx_opening_element [(nested_identifier (identifier)) (identifier)] - @font-lock-function-call-face) + @typescript-ts-jsx-tag-face) (jsx_closing_element [(nested_identifier (identifier)) (identifier)] - @font-lock-function-call-face) + @typescript-ts-jsx-tag-face) (jsx_self_closing_element [(nested_identifier (identifier)) (identifier)] - @font-lock-function-call-face) + @typescript-ts-jsx-tag-face) - (jsx_attribute (property_identifier) @font-lock-constant-face)) + (jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face)) :language language :feature 'number @@ -381,7 +391,12 @@ typescript-ts-mode ;;;###autoload (define-derived-mode tsx-ts-mode typescript-ts-base-mode "TypeScript[TSX]" - "Major mode for editing TypeScript." + "Major mode for editing TSX and JSX documents. + +This major mode defines two additional JSX-specific faces: +`typescript-ts-jsx-attribute-face' and +`typescript-ts-jsx-attribute-face' that are used for HTML tags +and attributes, respectively." :group 'typescript :syntax-table typescript-ts-mode--syntax-table commit 10918fc9d249fb829a363a4b73847289b8f2bce9 Author: Shynur Date: Thu Mar 30 01:29:17 2023 +0800 Fix scrolling window when point moves up This fixes the case when both 'scroll-conservatively' and 'scroll-step' are customized to non-default values. * src/xdisp.c (try_scrolling): Fix precedence between 'scroll-step' and 'scroll-conservatively' when scrolling with 'previous-line'. (Bug#62530) Copyright-paperwork-exempt: yes diff --git a/src/xdisp.c b/src/xdisp.c index 0b190529404..8e265fb5a49 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -18546,8 +18546,9 @@ try_scrolling (Lisp_Object window, bool just_this_one_p, start_display (&it, w, startp); if (arg_scroll_conservatively) - amount_to_scroll = max (dy, frame_line_height - * max (scroll_step, temp_scroll_step)); + amount_to_scroll + = min (max (dy, frame_line_height), + frame_line_height * arg_scroll_conservatively); else if (scroll_step || temp_scroll_step) amount_to_scroll = scroll_max; else commit 9b32bc134c4b4d8928df1bdc39907d9b1d6c73b5 Author: Eli Zaretskii Date: Thu Mar 30 09:09:43 2023 +0300 Improve documentation of 'defcustom's :set keyword * lisp/custom.el (defcustom): * doc/lispref/customize.texi (Variable Definitions): Improve the documentation of the :set keyword in 'defcustom'. diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi index 308145def55..6015c134d21 100644 --- a/doc/lispref/customize.texi +++ b/doc/lispref/customize.texi @@ -378,8 +378,15 @@ Variable Definitions modify its value argument destructively. The default for @var{setfunction} is @code{set-default-toplevel-value}. +If defined, @var{setfunction} will also be called when evaluating a +@code{defcustom} form with @kbd{C-M-x} in Emacs Lisp mode and when the +@var{option}'s value is changed via the @code{setopt} macro +(@pxref{Setting Variables, setopt}). + If you specify this keyword, the variable's documentation string -should describe how to do the same job in hand-written Lisp code. +should describe how to do the same job in hand-written Lisp code, +either by invoking @var{setfunction} directly or by using +@code{setopt}. @item :get @var{getfunction} @kindex get@r{, @code{defcustom} keyword} diff --git a/lisp/custom.el b/lisp/custom.el index 0522bdd447b..df6db181615 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -280,7 +280,9 @@ defcustom when using the Customize user interface. It takes two arguments, the symbol to set and the value to give it. The function should not modify its value argument destructively. The default choice - of function is `set-default-toplevel-value'. + of function is `set-default-toplevel-value'. If this keyword is + defined, modifying the value of SYMBOL via `setopt' will call the + function specified by VALUE to install the new value. :get VALUE should be a function to extract the value of symbol. The function takes one argument, a symbol, and should return the current value for that symbol. The default choice of function commit ab4273056e0ab68a27fe807b16e2995bf84b72ec Author: Andrea Corallo Date: Wed Mar 29 18:02:30 2023 +0200 Comp fix calls to redefined primtives with op-bytecode (bug#61917) * test/src/comp-tests.el (61917-1): New test. * src/comp.c (syms_of_comp): New variable. * lisp/loadup.el: Store primitive arities before dumping. * lisp/emacs-lisp/comp.el (comp--func-arity): New function. (comp-emit-set-call-subr): Make use of `comp--func-arity'. diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 283c00103b5..e97832455b9 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -1763,27 +1763,32 @@ comp-emit-switch (_ (signal 'native-ice "missing previous setimm while creating a switch")))) +(defun comp--func-arity (subr-name) + "Like `func-arity' but invariant against primitive redefinitions. +SUBR-NAME is the name of function." + (or (gethash subr-name comp-subr-arities-h) + (func-arity subr-name))) + (defun comp-emit-set-call-subr (subr-name sp-delta) "Emit a call for SUBR-NAME. SP-DELTA is the stack adjustment." - (let ((subr (symbol-function subr-name)) - (nargs (1+ (- sp-delta)))) - (let* ((arity (func-arity subr)) - (minarg (car arity)) - (maxarg (cdr arity))) - (when (eq maxarg 'unevalled) - (signal 'native-ice (list "subr contains unevalled args" subr-name))) - (if (eq maxarg 'many) - ;; callref case. - (comp-emit-set-call (comp-callref subr-name nargs (comp-sp))) - ;; Normal call. - (unless (and (>= maxarg nargs) (<= minarg nargs)) - (signal 'native-ice - (list "incoherent stack adjustment" nargs maxarg minarg))) - (let* ((subr-name subr-name) - (slots (cl-loop for i from 0 below maxarg - collect (comp-slot-n (+ i (comp-sp)))))) - (comp-emit-set-call (apply #'comp-call (cons subr-name slots)))))))) + (let* ((nargs (1+ (- sp-delta))) + (arity (comp--func-arity subr-name)) + (minarg (car arity)) + (maxarg (cdr arity))) + (when (eq maxarg 'unevalled) + (signal 'native-ice (list "subr contains unevalled args" subr-name))) + (if (eq maxarg 'many) + ;; callref case. + (comp-emit-set-call (comp-callref subr-name nargs (comp-sp))) + ;; Normal call. + (unless (and (>= maxarg nargs) (<= minarg nargs)) + (signal 'native-ice + (list "incoherent stack adjustment" nargs maxarg minarg))) + (let* ((subr-name subr-name) + (slots (cl-loop for i from 0 below maxarg + collect (comp-slot-n (+ i (comp-sp)))))) + (comp-emit-set-call (apply #'comp-call (cons subr-name slots))))))) (eval-when-compile (defun comp-op-to-fun (x) diff --git a/lisp/loadup.el b/lisp/loadup.el index 46b26750cd5..1cc70348267 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -476,7 +476,13 @@ ;; At this point, we're ready to resume undo recording for scratch. (buffer-enable-undo "*scratch*") +(defvar comp-subr-arities-h) (when (featurep 'native-compile) + ;; Save the arity for all primitives so the compiler can always + ;; retrive it even in case of redefinition. + (mapatoms (lambda (f) + (when (subr-primitive-p (symbol-function f)) + (puthash f (func-arity f) comp-subr-arities-h)))) ;; Fix the compilation unit filename to have it working when ;; installed or if the source directory got moved. This is set to be ;; a pair in the form of: diff --git a/src/comp.c b/src/comp.c index 1fce108fea4..3f72d088a66 100644 --- a/src/comp.c +++ b/src/comp.c @@ -5910,6 +5910,14 @@ syms_of_comp (void) Vcomp_loaded_comp_units_h = CALLN (Fmake_hash_table, QCweakness, Qvalue, QCtest, Qequal); + DEFVAR_LISP ("comp-subr-arities-h", Vcomp_subr_arities_h, + doc: /* Hash table recording the arity of Lisp primitives. +This is in case they are redefined so the compiler still knows how to +compile calls to them. +subr-name -> arity +For internal use. */); + Vcomp_subr_arities_h = CALLN (Fmake_hash_table, QCtest, Qequal); + Fprovide (intern_c_string ("native-compile"), Qnil); #endif /* #ifdef HAVE_NATIVE_COMP */ diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el index 926ba27e563..c5e5b346adb 100644 --- a/test/src/comp-tests.el +++ b/test/src/comp-tests.el @@ -446,7 +446,7 @@ primitive-advice (should (equal comp-test-primitive-advice '(3 4)))) (advice-remove #'+ f)))) -(defvar comp-test-primitive-redefine-args) +(defvar comp-test-primitive-redefine-args nil) (comp-deftest primitive-redefine () "Test effectiveness of primitive redefinition." (cl-letf ((comp-test-primitive-redefine-args nil) @@ -532,6 +532,22 @@ 48029-1 (should (subr-native-elisp-p (symbol-function 'comp-test-48029-nonascii-žžž-f)))) +(comp-deftest 61917-1 () + "Verify we can compile calls to redefined primitives with +dedicated byte-op code." + (let (x + (f (lambda (fn &rest args) + (setq comp-test-primitive-redefine-args args)))) + (advice-add #'delete-region :around f) + (unwind-protect + (setf x (native-compile + '(lambda () + (delete-region 1 2)))) + (should (subr-native-elisp-p x)) + (funcall x) + (advice-remove #'delete-region f) + (should (equal comp-test-primitive-redefine-args '(1 2)))))) + ;;;;;;;;;;;;;;;;;;;;; ;; Tromey's tests. ;; commit c98929c7e184740a7d68e63a2a619a436e00d813 Author: Eli Zaretskii Date: Wed Mar 29 21:28:53 2023 +0300 ; Fix last change diff --git a/lisp/net/eww.el b/lisp/net/eww.el index d42429e53aa..22b078217bd 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -73,7 +73,7 @@ eww-default-download-directory (defun eww--download-directory () "Return the name of the EWW download directory. -The default is specified by `eww-download-directory'; however, +The default is specified by `eww-default-download-directory'; however, if that directory doesn't exist and the DOWNLOAD XDG user directory is defined, use the latter instead." (or (and (file-exists-p eww-default-download-directory) commit a14c3f62a67d1a5fa423cd3818ede870f2596a09 Author: Eli Zaretskii Date: Wed Mar 29 21:28:02 2023 +0300 ; Fix last change diff --git a/lisp/net/eww.el b/lisp/net/eww.el index bc5f3e38ed5..d42429e53aa 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -76,7 +76,7 @@ eww--download-directory The default is specified by `eww-download-directory'; however, if that directory doesn't exist and the DOWNLOAD XDG user directory is defined, use the latter instead." - (or (and (file-exists-p eww-download-directory) + (or (and (file-exists-p eww-default-download-directory) eww-default-download-directory) (when-let ((dir (xdg-user-dir "DOWNLOAD"))) (file-name-as-directory dir)) commit 09fece5722f6a6235936526991092fa444e0bd8c Author: Eli Zaretskii Date: Wed Mar 29 21:27:09 2023 +0300 Fix duplicate defcustom in eww.el * lisp/net/eww.el (eww-default-download-directory): Renamed back from 'eww-download-directory'; all users changed. Doc fix. (Bug#62531) diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 9451083f396..bc5f3e38ed5 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -64,8 +64,9 @@ eww-use-browse-url :version "28.1" :type 'regexp) -(defcustom eww-download-directory "~/Downloads/" - "Default directory where `eww' saves downloaded files." +(defcustom eww-default-download-directory "~/Downloads/" + "Default directory where `eww' saves downloaded files. +Used by `eww--download-directory', which see." :version "29.1" :group 'eww :type 'directory) @@ -76,10 +77,10 @@ eww--download-directory if that directory doesn't exist and the DOWNLOAD XDG user directory is defined, use the latter instead." (or (and (file-exists-p eww-download-directory) - eww-download-directory) + eww-default-download-directory) (when-let ((dir (xdg-user-dir "DOWNLOAD"))) (file-name-as-directory dir)) - eww-download-directory)) + eww-default-download-directory)) (defcustom eww-download-directory 'eww--download-directory "Directory where files will downloaded. commit e45bd10a3d9cc4be676e43714ea6fb2068b8e614 Author: Eli Zaretskii Date: Wed Mar 29 14:56:20 2023 +0300 Fix indentation regression in 'C-h l' * lisp/help.el (view-lossage): Fix indentation of commands when the key sequence includes a semicolon. (Bug#62453) diff --git a/lisp/help.el b/lisp/help.el index 3e94b5046e5..6eac037df2c 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -689,6 +689,10 @@ view-lossage (with-current-buffer standard-output (goto-char (point-min)) (let ((comment-start ";; ") + ;; Prevent 'comment-indent' from handling a single + ;; semicolon as the beginning of a comment. + (comment-start-skip ";; ") + (comment-use-syntax nil) (comment-column 24)) (while (not (eobp)) (comment-indent) commit 46fd10a760012ced5be15ceab42637e0a2221567 Author: Michael Albinus Date: Wed Mar 29 10:55:18 2023 +0200 * doc/misc/tramp.texi (Remote shell setup): Clarify use of ssh RemoteCommand. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 468bdfdbcba..f9617f7a5cd 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -1,5 +1,5 @@ \input texinfo @c -*- mode: texinfo; coding: utf-8 -*- -@setfilename ../info/tramp +@setfilename ../../info/tramp.info @c %**start of header @include docstyle.texi @c In the Tramp GIT, the version number and the bug report address @@ -2372,10 +2372,11 @@ Remote shell setup @vindex RemoteCommand@r{, ssh option} @strong{Note}: If you use an @option{ssh}-based method for connection, do @emph{not} set the @option{RemoteCommand} option in your -@command{ssh} configuration, for example to @command{screen}. On the -other hand, some @option{ssh}-based methods, like @option{sshx} or -@option{scpx}, silently overwrite a @option{RemoteCommand} option of -the configuration file. +@command{ssh} configuration to something like @command{screen}. If +used, @option{RemoteCommand} must open an interactive shell on the +remote host. On the other hand, some @option{ssh}-based methods, like +@option{sshx} or @option{scpx}, silently overwrite a +@option{RemoteCommand} option of the configuration file. @subsection Other remote shell setup hints