From fd6d8faa62c56064c41a9709ab1010eecb8797f2 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 2 Feb 2026 16:04:04 -0800 Subject: [PATCH 01/13] Fix aligning buffer regions containing multiple alignment sections * lisp/align.el (align-region): Use markers to ensure the regions stay accurate after overlapping aligning modifications. (Bug#80316) * test/lisp/align-tests.el (align-c-multi-section): New test. --- lisp/align.el | 38 +++++++++++++++++++++++++------- test/lisp/align-tests.el | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 8 deletions(-) diff --git a/lisp/align.el b/lisp/align.el index 1f1c8f58009..c2132da17ea 100644 --- a/lisp/align.el +++ b/lisp/align.el @@ -1407,11 +1407,18 @@ aligner would have dealt with are." (align-region beg end 'entire exclude-rules nil + ;; Use markers for exclusion area bounds so + ;; they remain accurate after subsequent + ;; alignment sections modify the buffer. (lambda (b e mode) (or (and mode (listp mode)) + (let ((bm (copy-marker b)) + (em (copy-marker e t))) + (push bm markers) + (push em markers) (setq exclude-areas - (cons (cons b e) - exclude-areas))))) + (cons (cons bm em) + exclude-areas)))))) (setq exclude-areas (nreverse (sort exclude-areas #'car-less-than-car)))) @@ -1458,12 +1465,15 @@ aligner would have dealt with are." (setq same nil) (align--set-marker eol (line-end-position))) - ;; remember the beginning position of this rule - ;; match, and save the match-data, since either - ;; the `valid' form, or the code that searches for - ;; section separation, might alter it - (setq rule-beg (match-beginning first) - save-match-data (match-data)) + ;; Remember the beginning position of this rule + ;; match as a marker so it remains accurate after + ;; `align-regions' modifies the buffer for a + ;; previous alignment section. Also save the + ;; match-data, since either the `valid' form, or + ;; the code that searches for section separation, + ;; might alter it. + (align--set-marker rule-beg (match-beginning first) t) + (setq save-match-data (match-data)) (or rule-beg (error "No match for subexpression %s" first)) @@ -1480,6 +1490,18 @@ aligner would have dealt with are." (when (and last-point (align-new-section-p last-point rule-beg thissep)) + ;; Convert saved match-data positions to + ;; markers before `align-regions' modifies + ;; the buffer, so the restored match-data + ;; reflects the updated buffer state. + (setq save-match-data + (mapcar (lambda (pos) + (if (integerp pos) + (let ((m (copy-marker pos))) + (push m markers) + m) + pos)) + save-match-data)) (align-regions regions align-props rule func) (setq regions nil) (setq align-props nil)) diff --git a/test/lisp/align-tests.el b/test/lisp/align-tests.el index 92605a7f4aa..43660f8de87 100644 --- a/test/lisp/align-tests.el +++ b/test/lisp/align-tests.el @@ -36,6 +36,53 @@ (ert-test-erts-file (ert-resource-file "c-mode.erts") (test-align-transform-fun #'c-mode))) +(ert-deftest align-c-multi-section () + "Test alignment of multiple sections in C code. +Regression test for bug where positions become stale after earlier +sections are aligned, causing incorrect alignment in later sections." + (let ((input "int main(void) +{ + long signed int foo = 5; + int bar = 7; + { + int a1 = 4; + int b1 = 2; + long signed int junk1 = 2; + } + { + int a2 = 4; /* comment */ + int b2 = 2; + long signed int junk2 = 2; /* another comment */ + } + + return 0; +} +") + (expected "int main(void) +{ + long signed int foo = 5; + int bar = 7; + { + int a1 = 4; + int b1 = 2; + long signed int junk1 = 2; + } + { + int a2 = 4; /* comment */ + int b2 = 2; + long signed int junk2 = 2; /* another comment */ + } + + return 0; +} +")) + (with-temp-buffer + (c-mode) + (setq indent-tabs-mode nil) + (insert input) + (align (point-min) (point-max)) + (should (equal (buffer-string) expected))))) + (ert-deftest align-css () (let ((indent-tabs-mode nil)) (ert-test-erts-file (ert-resource-file "css-mode.erts") From f660a5469c9f7f85ca0925f2a5727df88f529f46 Mon Sep 17 00:00:00 2001 From: Troy Brown Date: Wed, 4 Feb 2026 23:07:01 -0500 Subject: [PATCH 02/13] Fix last change in align.el * lisp/align.el (align-region): Additional fix of last change. (Bug#80316) Copyright-paperwork-exempt: yes --- lisp/align.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/align.el b/lisp/align.el index c2132da17ea..362d59f2231 100644 --- a/lisp/align.el +++ b/lisp/align.el @@ -1475,7 +1475,7 @@ aligner would have dealt with are." (align--set-marker rule-beg (match-beginning first) t) (setq save-match-data (match-data)) - (or rule-beg + (or (marker-position rule-beg) (error "No match for subexpression %s" first)) ;; unless the `valid' attribute is set, and tells From 8beb69b77ca68a4fca1848d268f29041418df021 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 5 Feb 2026 11:28:13 +0200 Subject: [PATCH 03/13] ; Fix cross references in "User Lisp Directory" * doc/emacs/custom.texi (User Lisp Directory): Fix wording, punctuation, and cross-references. (Bug#80321) --- doc/emacs/custom.texi | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index d79bcf3fe0f..b2fcb3c489f 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -3138,30 +3138,33 @@ elisp, The Emacs Lisp Reference Manual}. If the directory specified by @code{user-lisp-directory}, defaulting to @file{~/.config/emacs/user-lisp/} or @file{~/.emacs.d/user-lisp/}, exists, then at startup Emacs will prepare Lisp files within that -directory for use in the session. Emacs does the following things: +directory for use in the session. Specifically, Emacs does the +following: @itemize @item Gather and activate autoload cookies. This means that you can use autoloaded commands and other entry points for the files in your @code{user-lisp-directory} without explicitly loading any of the -files in your initialization file. (@pxref{Autoload,,, elisp, The -Emacs Lisp Reference Manual}.) +files in your initialization file. @xref{Autoload,,, elisp, The +Emacs Lisp Reference Manual}. @item -Byte-compile all files, and if supported on your system, natively -compile them too. This speeds up the execution of the code in the -files when they are loaded. (@pxref{Byte Compilation,,, elisp, The -Emacs Lisp Reference Manual}.) +Byte-compile all the files (@pxref{Byte Compilation,,, elisp, The Emacs +Lisp Reference Manual}), and if supported by your build of Emacs, +compile them to native code as well (@pxref{Native Compilation,,, elisp, +The Emacs Lisp Reference Manual}). This speeds up the execution of the +code in those files when they are loaded and when they are executed +later. @item Adjust @code{load-path} such that all the files can be loaded and -autoloaded in the usual ways. (@pxref{Library Search,,, elisp, The -Emacs Lisp Reference Manual}.) +autoloaded in the usual ways. @xref{Library Search,,, elisp, The +Emacs Lisp Reference Manual}. @end itemize - The User Lisp directory is processed before loading the @ref{Init -File} file. Therefore any customizations to the user options discussed -below must be made in your early init file (@pxref{Early Init File}) in -order to have any effect. + The User Lisp directory is processed before loading your init file +(@pxref{Init File}). Therefore any customizations to the user +options discussed below must be made in your early init file +(@pxref{Early Init File}) in order to have any effect. @vindex user-lisp-ignored-directories @vindex user-lisp-auto-scrape From 0dfaa756120f4feecf5f6011ec243741b071e440 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 5 Feb 2026 11:31:05 +0000 Subject: [PATCH 04/13] Bind "s" in diff-mode-read-only-map, not diff-mode-shared-map * lisp/vc/diff-mode.el (diff-mode-shared-map): Move binding for "s" from here ... (diff-mode-read-only-map): ... to here (bug#80330). --- lisp/vc/diff-mode.el | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 2f0d949f108..b4389de8a7b 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -201,8 +201,9 @@ The default \"-b\" means to ignore whitespace-only changes, (defvar-keymap diff-mode-shared-map :doc "Bindings for read-only `diff-mode' buffers. These bindings are also available with an ESC prefix -(i.e. a \\=`M-' prefix) in read-write `diff-mode' buffers, -and with a `diff-minor-mode-prefix' prefix in `diff-minor-mode'. +(i.e. a \\=`M-' prefix) in all `diff-mode' buffers, including in +particular read-write `diff-mode' buffers, and with a +`diff-minor-mode-prefix' prefix in `diff-minor-mode'. See also `diff-mode-read-only-map'." "n" #'diff-hunk-next "N" #'diff-file-next @@ -218,7 +219,6 @@ See also `diff-mode-read-only-map'." "" #'diff-goto-source "o" #'diff-goto-source ; other-window " " #'undo-ignore-read-only - "s" #'diff-split-hunk ;; The foregoing commands don't affect buffers beyond this one. ;; The following command is the only one that has a single-character @@ -235,15 +235,17 @@ See also `diff-mode-read-only-map'." :doc "Additional bindings for read-only `diff-mode' buffers. Most of the bindings for read-only `diff-mode' buffers are in `diff-mode-shared-map'. This map contains additional bindings for -read-only `diff-mode' buffers that are *not* available with an ESC -prefix (i.e. a \\=`M-' prefix) in read-write `diff-mode' buffers." +read-only `diff-mode' buffers that are *not* also available with an ESC +prefix (i.e. a \\=`M-' prefix) in read-write (nor read-only) `diff-mode' +buffers." ;; We don't want the following in read-write `diff-mode' buffers ;; because they hide useful `M-' global bindings when editing. "W" #'widen "w" #'diff-kill-ring-save "A" #'diff-ediff-patch "r" #'diff-restrict-view - "R" #'diff-reverse-direction) + "R" #'diff-reverse-direction + "s" #'diff-split-hunk) (defvar-keymap diff-mode-map :doc "Keymap for `diff-mode'. See also `diff-mode-shared-map'." From ccee1c0de6eb283482ab6fbcdff6043863edfa82 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 5 Feb 2026 11:46:01 +0000 Subject: [PATCH 05/13] ; Improve outgoing base command docstrings. --- lisp/vc/vc.el | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 14da03cda1d..3d85453a3b3 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3347,7 +3347,9 @@ Uncommitted changes are included in the diff. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. @@ -3375,7 +3377,9 @@ Uncommitted changes are included in the diff. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. @@ -3409,7 +3413,9 @@ working revision and UPSTREAM-LOCATION. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. @@ -3441,7 +3447,9 @@ working revision and UPSTREAM-LOCATION. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. From 10aa35bab7d624fed2b267fc48ebb05e839da57c Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 5 Feb 2026 11:49:28 +0000 Subject: [PATCH 06/13] Bind "u", "@" in diff-mode-read-only-map, not diff-mode-shared-map * lisp/vc/diff-mode.el (diff-mode-shared-map): Move bindings for "u" and "@" from here ... (diff-mode-read-only-map): ... to here. --- lisp/vc/diff-mode.el | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index b4389de8a7b..0b6d2af517a 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -218,15 +218,7 @@ See also `diff-mode-read-only-map'." "RET" #'diff-goto-source "" #'diff-goto-source "o" #'diff-goto-source ; other-window - " " #'undo-ignore-read-only - - ;; The foregoing commands don't affect buffers beyond this one. - ;; The following command is the only one that has a single-character - ;; binding and which affects buffers beyond this one. - ;; However, the following command asks for confirmation by default, - ;; so that seems okay. --spwhitton - "u" #'diff-revert-and-kill-hunk - "@" #'diff-revert-and-kill-hunk) + " " #'undo-ignore-read-only) ;; Not `diff-read-only-mode-map' because there is no such mode ;; `diff-read-only-mode'; see comment above. @@ -245,7 +237,18 @@ buffers." "A" #'diff-ediff-patch "r" #'diff-restrict-view "R" #'diff-reverse-direction - "s" #'diff-split-hunk) + "s" #'diff-split-hunk + + ;; The foregoing commands in `diff-mode-shared-map' and + ;; `diff-mode-read-only-map' don't affect buffers beyond this one. + ;; The following command is the only one that has a single-character + ;; binding and which affects buffers beyond this one. However, the + ;; following command asks for confirmation by default, so that seems + ;; okay. --spwhitton + "u" #'diff-revert-and-kill-hunk + ;; `diff-revert-and-kill-hunk' is the `diff-mode' analogue of what '@' + ;; does in VC-Dir, so give it the same short binding. + "@" #'diff-revert-and-kill-hunk) (defvar-keymap diff-mode-map :doc "Keymap for `diff-mode'. See also `diff-mode-shared-map'." From dda572a2fad925d72fa19ee5724472d490d6cdb5 Mon Sep 17 00:00:00 2001 From: Protesilaos Stavrou Date: Sat, 10 Jan 2026 08:13:12 +0200 Subject: [PATCH 07/13] New minibuffer history for vc-user-edit-command (bug#80169) * lisp/vc/vc-dispatcher.el (vc-user-edit-command-history): New variable. (vc-user-edit-command): Use it (bug#80169). * etc/NEWS: Announce it. --- etc/NEWS | 5 +++++ lisp/vc/vc-dispatcher.el | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index 3a9d5ef6f8f..9e5ac796697 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2885,6 +2885,11 @@ This command is Diff mode's specialized 'narrow-to-region'. consistency, 'diff-restrict-view' is now too. To enable it again, use 'M-x enable-command'. +--- +*** 'C-x v !' has its own input history. +This is shared with the input history of 'C-x v P' for certain backends +which use the same mechanism as 'C-x v !'. + ** Package +++ diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index dc17b582ed7..374ae778d55 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -384,6 +384,9 @@ the man pages for \"torsocks\" for more details about Tor." :version "27.1" :group 'vc) +(defvar vc-user-edit-command-history nil + "Minibuffer history for `vc-user-edit-command'.") + (defun vc-user-edit-command (command file-or-list flags) "Prompt the user to edit VC command COMMAND and FLAGS. Intended to be used as the value of `vc-filter-command-function'." @@ -398,7 +401,8 @@ Intended to be used as the value of `vc-filter-command-function'." (cons command (remq nil (if files-separator-p (butlast flags) flags)))) - " "))))) + " ") + 'vc-user-edit-command-history)))) (list (car edited) file-or-list (nconc (cdr edited) (and files-separator-p '("--")))))) From e2f9e6ba7dc9094d54ace1dc125f73c05b6abc5e Mon Sep 17 00:00:00 2001 From: Visuwesh Date: Thu, 5 Feb 2026 12:11:53 +0000 Subject: [PATCH 08/13] vc-git--mailinfo: Use file-local-name (bug#80295, bug#80320) * lisp/vc/vc-git.el (vc-git--mailinfo): Use file-local-name (bug#80295, bug#80320). --- lisp/vc/vc-git.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index d6a7145b34e..9c97fcad97d 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -1472,7 +1472,9 @@ line of the commit message in an entry with key \"Subject\"." (if (eq system-type 'windows-nt) locale-coding-system coding-system-for-write))) - (vc-git--call input-file t "mailinfo" msg-file patch-file)) + (vc-git--call input-file t "mailinfo" + (file-local-name msg-file) + (file-local-name patch-file))) (goto-char (point-min)) ;; git-mailinfo joins up any header continuation lines for us. (while (re-search-forward "^\\([^\t\n\s:]+\\):\\(.*\\)$" nil t) From 3863449a0a62fd3d3e234c16f44c147637772af5 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 5 Feb 2026 12:18:54 +0000 Subject: [PATCH 09/13] ; * lisp/window.el (window--frame-landscape-p): Tweak wording. --- lisp/window.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/window.el b/lisp/window.el index 3a1ebd16fa6..2327ffcd5f2 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7586,7 +7586,7 @@ strategy." (defun window--frame-landscape-p (&optional frame) "Non-nil if FRAME is wider than it is tall. -This means actually wider on the screen, not character-wise. +This means actually wider on the screen, not wider character-wise. On text frames, use the heuristic that characters are roughtly twice as tall as they are wide." (if (display-graphic-p frame) From a06cddec20d79b92a11172c201fa8cec54a28ffb Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Thu, 5 Feb 2026 12:24:05 +0000 Subject: [PATCH 10/13] ; diff--revert-kill-hunks: Hoist binding inhibit-read-only. --- lisp/vc/diff-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 0b6d2af517a..559310ff770 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2332,10 +2332,10 @@ If REVERTP is non-nil, reverse-apply hunks before killing them." (setq beg (copy-marker beg) end (point-marker)) (unwind-protect (cl-loop initially (goto-char beg) + with inhibit-read-only = t for (hunk-beg hunk-end) = (diff-bounds-of-hunk) for file-bounds = (ignore-errors (diff-bounds-of-file)) for (file-beg file-end) = file-bounds - for inhibit-read-only = t if (and file-bounds (progn (goto-char file-beg) From 893e0783c98528906001e4091230395006476489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Thu, 5 Feb 2026 15:03:51 +0100 Subject: [PATCH 11/13] ; * lisp/subr.el (take-while): bytecode micro-optimisation --- lisp/subr.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index fcf03dd4f67..6f2dcb8c16d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1148,8 +1148,8 @@ side-effects, and the argument LIST is not modified." (make-symbol "f"))) (r (make-symbol "r"))) `(let (,@(and f `((,f ,pred))) - (,tail ,list) - (,r nil)) + (,r nil) + (,tail ,list)) (while (and ,tail (funcall ,(or f pred) (car ,tail))) (push (car ,tail) ,r) (setq ,tail (cdr ,tail))) From 4169720313cc9786f5b68c2ffdc94ae94e6293ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Thu, 5 Feb 2026 16:26:42 +0100 Subject: [PATCH 12/13] ; * test/lisp/vc/ediff-mult-tests.el: use ert-with-temp-directory Suggested by Pip Cet. --- test/lisp/vc/ediff-mult-tests.el | 44 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/test/lisp/vc/ediff-mult-tests.el b/test/lisp/vc/ediff-mult-tests.el index 4d7f3f35859..7887ae086fe 100644 --- a/test/lisp/vc/ediff-mult-tests.el +++ b/test/lisp/vc/ediff-mult-tests.el @@ -20,38 +20,34 @@ ;;; Code: (require 'ert) +(require 'ert-x) (require 'ediff-mult) (ert-deftest ediff-test-bug3348 () "After saving `ediff-meta-diff-buffer' to a file, we should not reuse it." - (let ((test-dir - (expand-file-name "bug-3348-testdir" temporary-file-directory))) - (make-directory test-dir t) - (unwind-protect - (progn - (cd test-dir) + (ert-with-temp-directory test-dir + (cd test-dir) - (make-directory "dir-a" t) - (make-directory "dir-b" t) + (make-directory "dir-a" t) + (make-directory "dir-b" t) - (with-temp-file "dir-a/file" - (insert "aaa\n")) - (with-temp-file "dir-b/file" - (insert "bbb\n")) + (with-temp-file "dir-a/file" + (insert "aaa\n")) + (with-temp-file "dir-b/file" + (insert "bbb\n")) - (ediff-directories "dir-a" "dir-b" nil) - (switch-to-buffer "*Ediff Session Group Panel*") + (ediff-directories "dir-a" "dir-b" nil) + (switch-to-buffer "*Ediff Session Group Panel*") - (ediff-next-meta-item 1) - (ediff-mark-for-operation-at-pos nil) - (ediff-collect-custom-diffs) + (ediff-next-meta-item 1) + (ediff-mark-for-operation-at-pos nil) + (ediff-collect-custom-diffs) - (with-current-buffer "*Ediff Multifile Diffs*" - (write-file "foo.patch")) + (with-current-buffer "*Ediff Multifile Diffs*" + (write-file "foo.patch")) - (with-temp-file "dir-b/file" - (insert "BBB\n")) - (ediff-collect-custom-diffs) + (with-temp-file "dir-b/file" + (insert "BBB\n")) + (ediff-collect-custom-diffs) - (should-not (equal ediff-meta-diff-buffer (get-buffer "foo.patch")))) - (delete-directory test-dir t)))) + (should-not (equal ediff-meta-diff-buffer (get-buffer "foo.patch"))))) From ec5479f0b5a9622be9a0f7eb923c7ea738fe8b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Thu, 5 Feb 2026 22:39:19 +0000 Subject: [PATCH 13/13] Eglot: fix thinko in eglot--async-request Just because a specific request of a specific "hint" is cancelled doesn't mean we can cancel the other's too. Also eglot-advertise-cancellation = nil was subtly broken. This manifested itself mostly in Eglot semantic tokens. * lisp/progmodes/eglot.el (eglot--async-request): Fix thinkos. --- lisp/progmodes/eglot.el | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 28ee14c67cb..89fbdec131f 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2030,21 +2030,25 @@ according to `eglot-advertise-cancellation'.") (timeout-fn nil timeout-fn-supplied-p) (timeout nil timeout-supplied-p) hint - &aux moreargs - id (buf (current-buffer))) + &aux moreargs id + (buf (current-buffer)) + (inflight eglot--inflight-async-requests)) "Like `jsonrpc-async-request', but for Eglot LSP requests. SUCCESS-FN, ERROR-FN and TIMEOUT-FN run in buffer of call site. HINT argument is a symbol passed as DEFERRED to `jsonrpc-async-request' and also used as a hint of the request cancellation mechanism (see `eglot-advertise-cancellation')." (cl-labels - ((clearing-fn (fn) + ((wrapfn (fn) (lambda (&rest args) (eglot--when-live-buffer buf - (when (and - fn (memq id (cl-getf eglot--inflight-async-requests hint))) - (apply fn args)) - (cl-remf eglot--inflight-async-requests hint))))) + (cond (eglot-advertise-cancellation + (when-let* ((tail (and fn (plist-member inflight hint)))) + (when (memq id (cadr tail)) + (apply fn args)) + (setf (cadr tail) (delete id (cadr tail))))) + (t + (apply fn args))))))) (eglot--cancel-inflight-async-requests (list hint)) (when timeout-supplied-p (setq moreargs (nconc `(:timeout ,timeout) moreargs))) @@ -2053,13 +2057,12 @@ and also used as a hint of the request cancellation mechanism (see (setq id (car (apply #'jsonrpc-async-request server method params - :success-fn (clearing-fn success-fn) - :error-fn (clearing-fn error-fn) - :timeout-fn (clearing-fn timeout-fn) + :success-fn (wrapfn success-fn) + :error-fn (wrapfn error-fn) + :timeout-fn (wrapfn timeout-fn) moreargs))) (when (and hint eglot-advertise-cancellation) - (push id - (plist-get eglot--inflight-async-requests hint))) + (push id (plist-get inflight hint))) id)) (cl-defun eglot--delete-overlays (&optional (prop 'eglot--overlays))