From 669e93ec5dfe235da95ed0b7beb6c06df2384dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sat, 13 Jun 2026 16:15:44 +0100 Subject: [PATCH 01/20] Eglot: restore compatibility to Emacs 26.3 Github-reference: https://github.com/joaotavora/eglot/discussions/1591 Can't use setf plist-get. * lisp/progmodes/eglot.el (eglot--async-request): Use cl-getf. --- lisp/progmodes/eglot.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 8d5d7cafc3c..da6738412ac 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2117,7 +2117,7 @@ and also used as a hint of the request cancellation mechanism (see :timeout-fn (wrapfn timeout-fn) moreargs))) (when (and hint eglot-advertise-cancellation) - (push id (plist-get inflight hint))) + (push id (cl-getf inflight hint))) id)) (cl-defun eglot--delete-overlays (&optional (prop 'eglot--overlays)) From d48977dea8521aacaead07503047c63f3a17e542 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 13 Jun 2026 18:27:26 -0400 Subject: [PATCH 02/20] src/keyboard.c (Finsert_special_event): Don't ignore unknown events --- src/keyboard.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/keyboard.c b/src/keyboard.c index 6f0b5fbb2ec..0c6c36319b3 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -12100,7 +12100,11 @@ Only 'input_event' slots KIND and ARG are set. */) CHECK_CONS (event); if (NILP (access_keymap (get_keymap (Vspecial_event_map, 0, 1), event, 0, 0, 1))) - signal_error ("Invalid event kind", XCAR (event)); + /* FIXME: Remove this check. Since `special-event-map` may change + between now and the moment we process the event, this check is + unreliable, and it's redundant anyway since we check below + if EVENT is one of the supported ones. */ + signal_error ("Invalid special event kind", XCAR (event)); /* Construct an input event. */ struct input_event ie; @@ -12137,7 +12141,7 @@ Only 'input_event' slots KIND and ARG are set. */) : EQ (XCAR (event), Qfocus_out) ? FOCUS_OUT_EVENT : EQ (XCAR (event), Qmove_frame) ? MOVE_FRAME_EVENT : EQ (XCAR (event), Qsleep_event) ? SLEEP_EVENT - : NO_EVENT); + : (signal_error ("Invalid special event kind", XCAR (event)), NO_EVENT)); ie.frame_or_window = Qnil; ie.arg = CDR (event); From df60bad16529e3709ef200adbf599da456509332 Mon Sep 17 00:00:00 2001 From: Kyle Meyer Date: Sat, 13 Jun 2026 23:59:15 -0400 Subject: [PATCH 03/20] Update to Org 9.8.6 --- etc/refcards/orgcard.tex | 2 +- lisp/org/ob-core.el | 5 ++++- lisp/org/org-version.el | 4 ++-- lisp/org/org.el | 9 ++++++--- lisp/org/ox-latex.el | 2 +- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex index 8b38b98897e..300af8d9d8c 100644 --- a/etc/refcards/orgcard.tex +++ b/etc/refcards/orgcard.tex @@ -1,5 +1,5 @@ % Reference Card for Org Mode -\def\orgversionnumber{9.8.5} +\def\orgversionnumber{9.8.6} \def\versionyear{2026} % latest update \input emacsver.tex diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el index a8ca1ccd080..13fa3a2c236 100644 --- a/lisp/org/ob-core.el +++ b/lisp/org/ob-core.el @@ -2976,6 +2976,7 @@ used as a string to be appended to #+begin_example line." (forward-line 0) (insert ": ") (forward-line 1))) (t (goto-char beg) + (unless (bolp) (insert "\n")) (insert (if results-switches (format "%s%s\n" (funcall maybe-cap "#+begin_example") @@ -2984,7 +2985,9 @@ used as a string to be appended to #+begin_example line." (let ((p (point))) (if (markerp end) (goto-char end) (forward-char (- end beg))) (org-escape-code-in-region p (point))) - (insert (funcall maybe-cap "#+end_example\n"))))))))) + (unless (bolp) (insert "\n")) + (insert (funcall maybe-cap "#+end_example")) + (unless (eolp) (insert "\n"))))))))) (defun org-babel-update-block-body (new-body) "Update the body of the current code block to NEW-BODY." diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index f0a212f2ef0..25cbd97621b 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -5,13 +5,13 @@ (defun org-release () "The release version of Org. Inserted by installing Org mode or when a release is made." - (let ((org-release "9.8.5")) + (let ((org-release "9.8.6")) org-release)) ;;;###autoload (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.8.5")) + (let ((org-git-version "release_9.8.6")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index ba31ad67bd1..be9f31ecc9e 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -9,7 +9,7 @@ ;; URL: https://orgmode.org ;; Package-Requires: ((emacs "28.2")) -;; Version: 9.8.5 +;; Version: 9.8.6 ;; This file is part of GNU Emacs. ;; @@ -9551,6 +9551,7 @@ When foo is written as FOO, upcase the #+BEGIN/END as well." (goto-char region-end) ;; Ignore empty lines at the end of the region. (skip-chars-backward " \r\t\n") + (unless (eolp) (insert "\n") (forward-line -1)) (end-of-line)) (unless (bolp) (insert "\n")) (indent-to column) @@ -9877,7 +9878,8 @@ When called through Elisp, arg is also interpreted in the following way: (org-update-parent-todo-statistics)) (when (bound-and-true-p org-clock-out-when-done) (org-clock-out-if-current)) - (run-hooks 'org-after-todo-state-change-hook) + (save-excursion + (run-hooks 'org-after-todo-state-change-hook)) (when (and arg (not (member org-state org-done-keywords))) (setq head (org-get-todo-sequence-head org-state))) (put-text-property (line-beginning-position) @@ -10583,7 +10585,8 @@ enough to shift date past today. Continue? " (org-timestamp-change n (cdr (assoc what whata)) nil t)) (setq msg (concat msg type " " org-last-changed-timestamp " "))))))) - (run-hooks 'org-todo-repeat-hook) + (save-excursion + (run-hooks 'org-todo-repeat-hook)) (setq org-log-post-message msg) (message msg)))) diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el index 1feddac37cd..d07af9e63ad 100644 --- a/lisp/org/ox-latex.el +++ b/lisp/org/ox-latex.el @@ -1712,7 +1712,7 @@ Return the new header." ;; exclusively through ini files, return HEADER as-is. (header (if (or language-ini-only (not (stringp language-code)) - (not (string-match "\\\\usepackage\\[\\(.*\\)\\]{babel}" header))) + (not (string-match "\\\\usepackage\\[\\([^]]*\\)\\]{babel}" header))) header (let ((options (save-match-data (org-split-string (match-string 1 header) ",[ \t]*")))) From a8da2d20d0767a7aff5df4f16a163572f57cd254 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 14 Jun 2026 07:21:39 +0300 Subject: [PATCH 04/20] ; * src/keyboard.c (Finsert_special_event): Fix quotes. --- src/keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard.c b/src/keyboard.c index 0c6c36319b3..b1d14ef1a25 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -12100,7 +12100,7 @@ Only 'input_event' slots KIND and ARG are set. */) CHECK_CONS (event); if (NILP (access_keymap (get_keymap (Vspecial_event_map, 0, 1), event, 0, 0, 1))) - /* FIXME: Remove this check. Since `special-event-map` may change + /* FIXME: Remove this check. Since 'special-event-map' may change between now and the moment we process the event, this check is unreliable, and it's redundant anyway since we check below if EVENT is one of the supported ones. */ From 7b4e12b51c273a62b01f014897958a84abb9459c Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Mon, 15 Jun 2026 10:41:00 +0200 Subject: [PATCH 05/20] ; * lisp/help.el (temp-buffer-resize-mode): Fix doc-string typo. --- lisp/help.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/help.el b/lisp/help.el index 5e628083def..be6e56ab646 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -2007,7 +2007,7 @@ When this mode is enabled, a window is resized only if it has been specially created for a temporary buffer. Windows that have shown another buffer before being reused for displaying a temporary buffer are not resized (but note that if `even-window-sizes' is non-nil, they -might beresized in some situations anyway). A frame is resized only +might be resized in some situations anyway). A frame is resized only if `fit-frame-to-buffer' is non-nil. This mode is used by `help', `apropos' and `completion' buffers, From ea09986daedbe50e1115cd6de36fb45f98f0ba40 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Mon, 15 Jun 2026 10:46:11 +0200 Subject: [PATCH 06/20] ; * lisp/window.el (display-buffer): Fix doc-string typo. --- lisp/window.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/window.el b/lisp/window.el index bd0653fe0d4..601a2b18fe3 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8273,7 +8273,7 @@ Action alist entries are: and `shrink-window-if-larger-than-buffer'. \\+`window-width' -- The value specifies the desired width of the window chosen and is either an integer (the total width of - the window specified in frame lines), a floating point + the window specified in frame columns), a floating point number (the fraction of its total width with respect to the width of the frame's root window), a cons cell whose car is `body-columns' and whose cdr is an integer that specifies the From a6f543711071bfab8a7dbf6eb5c9974a1fba802e Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 16 Jun 2026 09:57:48 -0400 Subject: [PATCH 07/20] (comint--intersect-regions): Fix bug#81243 * lisp/comint.el (comint--intersect-regions): Fix syntax-propertization. --- lisp/comint.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/comint.el b/lisp/comint.el index 95e117d999a..e5418f4ee67 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -4234,7 +4234,9 @@ function called, or nil, if no function was called (if BEG = END)." (eq is-output (eq (get-text-property (1+ end2) 'field) 'output))) (setq end2 (field-end end2))) - ;; Narrow to the whole field surrounding the region + ;; Narrow to the whole field surrounding the region. + ;; `syntax-propertize' can't widen so avoid the need to (bug#81243). + (syntax-propertize beg2) (narrow-to-region beg2 end2)) (setq return-end (list (funcall fun beg1 (marker-position end1))))) From a25cf2b986560cfe82f4bd26eaa1526a70c1a072 Mon Sep 17 00:00:00 2001 From: JD Smith Date: Tue, 16 Jun 2026 17:11:44 -0400 Subject: [PATCH 08/20] Revert "Fix the Android build" This reverts commit 916572f6e0ab3e36f7098b6d9b5ff19f87240da4, in favor of another fix. --- configure.ac | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index cfa238e254c..d2967210bc3 100644 --- a/configure.ac +++ b/configure.ac @@ -5271,14 +5271,12 @@ if test "${with_native_compilation}" != "no"; then else libgccjit_not_found_err fi]) - # `libgcc_not_found' may set `with_native_compilation' to `no'. - AS_IF([test "$with_native_compilation" != "no"], - [AC_CHECK_HEADERS([libgccjit.h], [], - [if test "${with_native_compilation}" = "default"; then + AC_CHECK_HEADERS([libgccjit.h], [], + [if test "${with_native_compilation}" = "default"; then libgccjit_dev_not_found else libgccjit_dev_not_found_err - fi])]) + fi]) if test "${with_native_compilation}" != "no"; then # Check if libgccjit really works. AC_RUN_IFELSE([libgccjit_smoke_test], [], From 2ac289d0968581ea93a37c15abbcc93d794bb7e3 Mon Sep 17 00:00:00 2001 From: JD Smith Date: Fri, 5 Jun 2026 18:34:24 -0400 Subject: [PATCH 09/20] Correct default native-comp tests Supersedes 5bd9d1f7df3. * configure.ac: Store `with_native_compilation' to correctly test whether to use the soft or hard (error) checks, as these set the variable by side-effect. --- configure.ac | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index d2967210bc3..e5f496cfa11 100644 --- a/configure.ac +++ b/configure.ac @@ -5176,19 +5176,6 @@ You can find the instructions on how to compile and install libgccjit from source on this site: .])]) -HAVE_NATIVE_COMP=no -LIBGCCJIT_LIBS= -LIBGCCJIT_CFLAGS= -if test "$canonical" = i686-pc-cygwin; then - if test "${with_cygwin32_native_compilation}" = yes; then - with_native_compilation=yes - elif test "${with_native_compilation}" != no; then - AC_MSG_ERROR([Native compilation is not supported on 32-bit Cygwin. -If you really want to try it anyway, use the configure option -'--with-cygwin32-native-compilation'.]) - fi -fi - AC_DEFUN([libgccjit_not_found], [ AC_MSG_WARN([Elisp native compiler can't be enabled as libgccjit was not found. @@ -5222,6 +5209,19 @@ source on this site: with_native_compilation=no]) +HAVE_NATIVE_COMP=no +LIBGCCJIT_LIBS= +LIBGCCJIT_CFLAGS= +if test "$canonical" = i686-pc-cygwin; then + if test "${with_cygwin32_native_compilation}" = yes; then + with_native_compilation=yes + elif test "${with_native_compilation}" != no; then + AC_MSG_ERROR([Native compilation is not supported on 32-bit Cygwin. +If you really want to try it anyway, use the configure option +'--with-cygwin32-native-compilation'.]) + fi +fi + if test "$with_features" = "no" \ && test "${with_native_compilation}" = "default"; then with_native_compilation=no @@ -5265,14 +5265,15 @@ if test "${with_native_compilation}" != "no"; then fi # Check if libgccjit is available. + native_compilation_requested=${with_native_compilation} AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire], [], - [if test "${with_native_compilation}" = "default"; then + [if test "${native_compilation_requested}" = "default"; then libgccjit_not_found else libgccjit_not_found_err fi]) AC_CHECK_HEADERS([libgccjit.h], [], - [if test "${with_native_compilation}" = "default"; then + [if test "${native_compilation_requested}" = "default"; then libgccjit_dev_not_found else libgccjit_dev_not_found_err @@ -5280,7 +5281,7 @@ if test "${with_native_compilation}" != "no"; then if test "${with_native_compilation}" != "no"; then # Check if libgccjit really works. AC_RUN_IFELSE([libgccjit_smoke_test], [], - [if test "${with_native_compilation}" = "default"; then + [if test "${native_compilation_requested}" = "default"; then libgccjit_broken else libgccjit_broken_err From 050ca1a40fcf6a6dc1d1b1815c7dbc3dac53696b Mon Sep 17 00:00:00 2001 From: Alan Third Date: Sun, 14 Jun 2026 15:09:28 +0100 Subject: [PATCH 10/20] ; Remove NS port toolbar styling code (bug#80307) Reverts cbf9c5873056657865c5a149ece5122a8d03011a. * src/nsterm.m: Remove the code that calls setToolbarStyle. --- src/nsterm.m | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index f4de0a76c0a..120442cda25 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9827,14 +9827,6 @@ - (instancetype) initWithEmacsFrame: (struct frame *) f #ifdef NS_IMPL_COCOA if ([self respondsToSelector:@selector(setTabbingMode:)]) [self setTabbingMode:NSWindowTabbingModeDisallowed]; -#endif - /* Always show the toolbar below the window title. This is needed - on Mac OS 11+ where the toolbar style is decided by the system - (which is unpredictable) and the newfangled "compact" toolbar - may be chosen (which is undesirable). */ -#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 110000 - if ([self respondsToSelector:@selector(setToolbarStyle:)]) - [self setToolbarStyle: NSWindowToolbarStyleExpanded]; #endif } From 14bf2a707c68f7b8eb35dd98446e00741d52370e Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Thu, 18 Jun 2026 16:41:23 +0200 Subject: [PATCH 11/20] Fix thinko in 'set-frame-size-and-position' (Bug#81193) * lisp/frame.el (set-frame-size-and-position): Do not subtract scoll bar, fringes and internal border sizes twice (Bug#81193). --- lisp/frame.el | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lisp/frame.el b/lisp/frame.el index 85b58cee070..36c14304ec7 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1782,11 +1782,7 @@ resize and move FRAME." (when negative (setq gravity 3) (setq left (- parent-or-display-width (- left) - (+ text-width - (frame-scroll-bar-width frame) - (frame-fringe-width frame) - (* 2 (frame-internal-border-width frame)) - outer-minus-text-width)))) + text-width outer-minus-text-width))) (setq negative nil) (cond @@ -1813,9 +1809,7 @@ resize and move FRAME." ;; This should get us 7 or 9. (setq gravity (+ gravity 6)) (setq top (- parent-or-display-height (- top) - (+ text-height - (* 2 (frame-internal-border-width frame))) - outer-minus-text-height))) + text-height outer-minus-text-height))) (set-frame-size-and-position-pixelwise frame text-width text-height left top gravity))) From b6e7962700dd1a7ae774b9f2ae2a2c0d9e33151d Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Fri, 19 Jun 2026 06:35:44 +0300 Subject: [PATCH 12/20] Fix "diff-apply-buffer applies to the wrong file" * lisp/vc/diff-mode.el (diff-find-file-name): Inhibit the "drop dir" behavior in diffs produced by Git and Hg (bug#81210). Except for the virtual subdirectories like a/b/etc, which is moved and happens for all such diffs. Tighten the check for such virtual directory names, though (characters are the chars used by the configuration option 'diff.mnemonicPrefix'). (diff-setup-buffer-type): Recognize Hg diffs where only one revision is specified, too. * test/lisp/vc/diff-mode-tests.el (diff-mode-test-setup-buffer-type) (diff-mode-test-find-file-name-create): New tests. --- lisp/vc/diff-mode.el | 15 ++++++----- test/lisp/vc/diff-mode-tests.el | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 32f34ebaa10..c1227573351 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -1176,6 +1176,10 @@ PREFIX is only used internally: don't use it." (or (ignore-errors (diff-beginning-of-file)) (re-search-forward diff-file-header-re nil t))) (let ((fs (diff-hunk-file-names old))) + (when (memq diff-buffer-type '(git hg)) + (setq fs + (mapcar (lambda (f) (replace-regexp-in-string "\\`[icoawib]/" "" f)) + fs))) (if prefix (setq fs (mapcar (lambda (f) (concat prefix f)) fs))) (or ;; use any previously used preference @@ -1186,7 +1190,10 @@ PREFIX is only used internally: don't use it." (if (and newfile (file-exists-p newfile)) (cl-return newfile)))) ;; look for each file in turn. If none found, try again but ;; ignoring the first level of directory, ... - (cl-do* ((files fs (delq nil (mapcar #'diff-filename-drop-dir files))) + (cl-do* ((files fs (and (not (and (memq diff-buffer-type '(git hg)) + (not old) + (equal null-device (cadr files)))) + (delq nil (mapcar #'diff-filename-drop-dir files)))) (file nil nil)) ((or (null files) (setq file (cl-do* ((files files (cdr files)) @@ -1212,10 +1219,6 @@ PREFIX is only used internally: don't use it." (let ((file (or (car fs) "")) (creation (equal null-device (car (diff-hunk-file-names (not old)))))) - (when (and (memq diff-buffer-type '(git hg)) - (string-match "/" file)) - ;; Strip the dst prefix (like b/) if diff is from Git/Hg. - (setq file (substring file (match-end 0)))) (setq file (expand-file-name file)) (setq file (read-file-name (format "Use file %s: " file) @@ -1822,7 +1825,7 @@ modified lines of the diff." (setq-local diff-buffer-type (if (re-search-forward "^diff --git" nil t) 'git - (if (re-search-forward "^diff -r.*-r" nil t) + (if (re-search-forward "^diff -r " nil t) 'hg nil)))) (when (eq diff-buffer-type 'git) diff --git a/test/lisp/vc/diff-mode-tests.el b/test/lisp/vc/diff-mode-tests.el index c75e7ef066b..36291fee0a5 100644 --- a/test/lisp/vc/diff-mode-tests.el +++ b/test/lisp/vc/diff-mode-tests.el @@ -744,5 +744,53 @@ plum (set-buffer-modified-p nil) (kill-buffer buf-after)))))) +(ert-deftest diff-mode-test-setup-buffer-type () + "Check that `diff-setup-buffer-type' recognizes the diff's origin." + (with-temp-buffer + (insert "diff --git a/foo b/foo\n--- a/foo\n+++ b/foo\n") + (diff-mode) + (should (eq diff-buffer-type 'git))) + (with-temp-buffer + (insert "diff -r 0123456789ab foo\n--- a/foo\n+++ b/foo\n") + (diff-mode) + (should (eq diff-buffer-type 'hg))) + (with-temp-buffer + (insert "--- foo\n+++ foo\n@@ -1 +1 @@\n-a\n+b\n") + (diff-mode) + (should (eq diff-buffer-type nil)))) + +(ert-deftest diff-mode-test-find-file-name-create () + "Check `diff-find-file-name' for a Git/Hg file creation. +It should not use existing file without subdirectory." + (ert-with-temp-directory temp-dir + (let ((default-directory temp-dir) + call-dir call-initial call-mustmatch) + ;; A decoy with the same basename as the created file, but in a + ;; different directory. + (with-temp-file (expand-file-name "created.txt" temp-dir) + (insert "decoy\n")) + (with-temp-buffer + (insert "diff --git a/sub/created.txt b/sub/created.txt +new file mode 100644 +index 0000000..3456789 +--- /dev/null ++++ b/sub/created.txt +@@ -0,0 +1 @@ ++new +") + (diff-mode) + (goto-char (point-min)) + (let ((read-file-name-function + (lambda (_p &optional dir _def mustmatch initial _pred) + (setq call-dir dir + call-initial initial + call-mustmatch mustmatch) + "magic"))) + (should (equal (diff-find-file-name) + "magic")) + (should (equal call-dir (expand-file-name "sub/" temp-dir))) + (should (equal call-initial "created.txt")) + (should (equal call-mustmatch nil))))))) + (provide 'diff-mode-tests) ;;; diff-mode-tests.el ends here From a94a33827b4048accf43b93d3cd7958b1832559f Mon Sep 17 00:00:00 2001 From: Stephen Berman Date: Fri, 19 Jun 2026 10:13:22 +0200 Subject: [PATCH 13/20] Avoid an unusual error when visiting a directory in Dired * lisp/dired.el (dired-internal-noselect): Unset 'dired--ls-error-buffer' before calling 'dired-readin'. This is a safeguard to prevent an error when visiting a directory in Dired, which apparently happens when the variable somehow gets set even though 'ls' has not emitted an error message (bug#80499, Message #218). * test/lisp/dired-tests.el (dired-test-set-dired--ls-error-buffer): New test. --- lisp/dired.el | 18 ++++++++++++++---- test/lisp/dired-tests.el | 10 ++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lisp/dired.el b/lisp/dired.el index 9ce3f042f6b..26e698341d8 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -1459,10 +1459,20 @@ The return value is the target column for the file names." ;; (buffer-local), so we can call dired-readin: (let ((failed t)) (unwind-protect - (progn (dired-readin) - (unless (and dired--ls-error-buffer - (get-buffer "*ls error*")) - (setq failed nil))) + (progn + ;; `dired--ls-error-buffer' should only be set in + ;; `insert-directory', and if `ls' errors and the buffer + ;; displaying the error message pops ups, + ;; `dired--ls-error-buffer' is then unset. But if for + ;; some reason it gets set before the next Dired + ;; buffer-display command is invoked, this can raise an + ;; error, so ensure the variable is unset before reading + ;; the directory contents into a Dired buffer. + (setq dired--ls-error-buffer nil) + (dired-readin) + (unless (and dired--ls-error-buffer + (get-buffer "*ls error*")) + (setq failed nil))) ;; If either `dired-readin' failed (e.g. if parent directories ;; are inaccessible) or `ls' errored, don't leave the Dired ;; buffer around. diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el index f77d56637fd..65ca58cc705 100644 --- a/test/lisp/dired-tests.el +++ b/test/lisp/dired-tests.el @@ -820,5 +820,15 @@ of the value of `dired-auto-toggle-b-switch'." (let ((dired-auto-toggle-b-switch nil)) (dired-test--filename-with-backslash-n))) +(ert-deftest dired-test-set-dired--ls-error-buffer () ; bug#80499, Message #218 + "Test visiting a directory after setting `dired--ls-error-buffer'." + (let ((dir (ert-resource-file (file-name-as-directory "test-dir")))) + (make-directory dir t) + (setq dired--ls-error-buffer (get-buffer-create "*ls error*")) + (find-file dir) + (should (equal list-buffers-directory dir)) + (kill-buffer (current-buffer)) + (delete-directory dir))) + (provide 'dired-tests) ;;; dired-tests.el ends here From 9d1b0c2d7f64d8367a7d700041d2c4a3605663e7 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Thu, 28 May 2026 22:43:09 -0700 Subject: [PATCH 14/20] Fix markdown-inline incremental parsing issue (bug#81019) * lisp/treesit.el: (treesit--embed-languages-need-full-parse): New variable. (treesit--set-embed-ranges): Reparse full range if the langauge needs it. --- lisp/treesit.el | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lisp/treesit.el b/lisp/treesit.el index e2e62bb71a2..dbb39b19226 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -680,6 +680,11 @@ If none are valid, return nil." ;;; Range API supplement +;; See bug#81019. +(defvar treesit--embed-languages-need-full-parse '(markdown-inline) + "Languages that requires a full parse when used as embedded languages. +This variable is not intended for general use.") + (defvar treesit--range-verbose nil "If non-nil, print verbose debugging info for setting ranges. Useful when your multi-parser setup doesn't seem to work.") @@ -1094,6 +1099,14 @@ RANGES is a list of (START . END) or just (START . END)." (when (and (null new-ranges) treesit--range-verbose) (message "Setting empty ranges to %s\nRanges for embedded parser :%s\nRanges for host parser: %s\nIntersection is empty" new-ranges-1 embed-parser host-parser)) + ;; Due to some tree-sitter bug[1], we need to force a full reparse for + ;; some languages to get a correct parse tree. + ;; [1] https://github.com/tree-sitter/tree-sitter/issues/5636 + (when (memq (treesit-parser-language embed-parser) + treesit--embed-languages-need-full-parse) + (treesit-parser-set-included-ranges + embed-parser `((,(point-min) . ,(point-min)))) + (treesit-parser-root-node embed-parser)) ;; When there's no range for the embedded language, set it's range ;; to a dummy (1 . 1), otherwise it would be set to the whole ;; buffer, which is not what we want. From c0a33a474d3f536357b125996b16a9ace484199d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Wed, 17 Jun 2026 16:56:12 +0530 Subject: [PATCH 15/20] Fix c-ts-mode bsd-style indentation of union bodies (bug#81255) * lisp/progmodes/c-ts-mode.el (c-ts-mode--simple-indent-rules): Add "union_specifier" to the parent-is regexp. * test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts: New test. --- lisp/progmodes/c-ts-mode.el | 1 + test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index d08615446a1..5f064716a89 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -501,6 +501,7 @@ MODE can be `c' or `cpp'. STYLE can be `gnu', `k&r', `linux', `bsd'." ((parent-is ,(rx (or "function_definition" "struct_specifier" "enum_specifier" + "union_specifier" "function_declarator" "template_declaration"))) standalone-parent 0) diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts index 2325b3b008d..66a8153c63f 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts @@ -125,3 +125,12 @@ if (true) else break; =-=-= + +Name: Union (bug#81255) + +=-= +union u +{ + int i; +}; +=-=-= From c3bc04954913be4fdb704620044d1178ad44f2c6 Mon Sep 17 00:00:00 2001 From: Oleksandr Makhmudov Date: Tue, 9 Jun 2026 11:43:14 +0200 Subject: [PATCH 16/20] Eglot: add 'nu-ts-mode' as a nushell major mode 'nu-ts-mode' is an alternative tree-sitter-based major mode for nushell. This commit adds it to the list of major modes that run the nushell language server. * lisp/progmodes/eglot.el (eglot-server-programs): Add 'nu-ts-mode'. (Bug#81206) Copyright-paperwork-exempt: yes --- lisp/progmodes/eglot.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index da6738412ac..457391572a0 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -317,7 +317,7 @@ automatically)." ((toml-ts-mode conf-toml-mode) . ("tombi" "lsp")) (nix-mode . ,(eglot-alternatives '("nil" "rnix-lsp" "nixd"))) (nickel-mode . ("nls")) - ((nushell-mode nushell-ts-mode) . ("nu" "--lsp")) + ((nushell-mode nushell-ts-mode nu-ts-mode) . ("nu" "--lsp")) (gdscript-mode . ("localhost" 6008)) (fennel-mode . ("fennel-ls")) (move-mode . ("move-analyzer")) From ca7c8208b7979df9951c8d63e8f4a638d0b22b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Marks?= Date: Wed, 10 Jun 2026 13:34:22 -0400 Subject: [PATCH 17/20] markdown-ts-mode: Fix computing code block current region (bug#81219) This ensures that commands such as 'comment-or-uncomment-region' operate on the correct region in the work buffer. * lisp/textmodes/markdown-ts-mode.el (markdown-ts--run-command-in-code-block): Fix adj-region-beg and adj-region-end. --- lisp/textmodes/markdown-ts-mode.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/textmodes/markdown-ts-mode.el b/lisp/textmodes/markdown-ts-mode.el index 6b70f2aced9..7486ca2b2c8 100644 --- a/lisp/textmodes/markdown-ts-mode.el +++ b/lisp/textmodes/markdown-ts-mode.el @@ -3214,8 +3214,8 @@ ARGS are captured by `markdown-ts--maybe-run-command-in-code-block'." (region-end (use-region-end)) (adj-point (1+ (- orig-point beg))) (adj-mark (when orig-mark (1+ (- orig-mark beg)))) - (adj-region-beg (when region-beg (1+ (- orig-point region-beg)))) - (adj-region-end (when region-end (1+ (- orig-point region-end)))) + (adj-region-beg (when region-beg (1+ (- region-beg beg)))) + (adj-region-end (when region-end (1+ (- region-end beg)))) (point-delta 0) (ignore-output (memq command markdown-ts-code-block-ignore-output-commands)) From ae69929472d4cf20e642a63fccd4e3611567478e Mon Sep 17 00:00:00 2001 From: Ivar Rummelhoff Date: Sun, 14 Jun 2026 13:30:12 +0200 Subject: [PATCH 18/20] ; Improve code comment and 'winner-redo' docstring (bug#81235). --- lisp/winner.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lisp/winner.el b/lisp/winner.el index e888de2ae35..7b63103fafa 100644 --- a/lisp/winner.el +++ b/lisp/winner.el @@ -272,8 +272,8 @@ You may want to include buffer names such as *Help*, *Apropos*, ;; Make sure point does not end up in the minibuffer and delete -;; windows displaying dead or boring buffers -;; (cf. `winner-boring-buffers') and `winner-boring-buffers-regexp'. +;; windows displaying dead or boring buffers, +;; cf. `winner-boring-buffers' and `winner-boring-buffers-regexp'. ;; Return nil if all the windows should be deleted. Preserve correct ;; points and marks. (defun winner-set (conf) @@ -425,7 +425,10 @@ In other words, \"undo\" changes in window configuration." (defun winner-redo () ; If you change your mind. - "Restore a more recent window configuration saved by Winner mode." + "Cancel the current sequence of `winner-undo' commands. +This restores the window configuration before that sequence. If any +other command has intervened, `winner-redo' is no longer applicable; +but the configuration can then be restored with `winner-undo'." (interactive) (cond ((eq last-command 'winner-undo) From 75cd27719849169716283d77e42b4f8c439808a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Marks?= Date: Thu, 11 Jun 2026 14:26:21 -0400 Subject: [PATCH 19/20] markdown-ts-mode: fix code block and table overlays (bug#81195) Fix to eliminate erroneous multiple code block overlays. Fixes to deal with 'treesit' fontification catching up to user-initiated code block range expansions; e.g., inserting, yanking. Set overlay properties only once. * lisp/textmodes/markdown-ts-mode.el (markdown-ts--fontify-code-block): Use 'overlays-in' not 'overlays-at'. Use only overlays, eliminate markers. (markdown-ts--enable-code-block-in-context-mode): Add 'sit-for' to allow 'treesit' to catch up (pending input should not be an issue). (markdown-ts--run-command-in-code-block): Use overlays instead of 'get-char-property'. (markdown-ts--code-block-in-context-mode-update-ov): Use overlays instead of 'get-char-property'. Set overlay properties only once. (markdown-ts--in-table-mode-update-ov): Set overlay properties only once. --- lisp/textmodes/markdown-ts-mode.el | 85 +++++++++++++++++------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/lisp/textmodes/markdown-ts-mode.el b/lisp/textmodes/markdown-ts-mode.el index 7486ca2b2c8..a27255ca645 100644 --- a/lisp/textmodes/markdown-ts-mode.el +++ b/lisp/textmodes/markdown-ts-mode.el @@ -1602,19 +1602,14 @@ properties `markdown-ts-code-block-language' and (markdown-ts--code-block-language-mode lang))) (existing (seq-find (lambda (ov) (overlay-get ov 'markdown-ts-code-block)) - (overlays-at node-start)))) + (overlays-in node-start node-end)))) (if existing (progn (move-overlay existing node-start node-end) (overlay-put existing 'face face) (overlay-put existing 'markdown-ts-code-block-language lang) (overlay-put existing 'markdown-ts-code-block-mode mode)) - (let ((ov (make-overlay node-start node-end nil t nil))) - ;; Markers need to be set only once. - (overlay-put ov 'markdown-ts-code-beg-marker (set-marker (make-marker) - node-start)) - (overlay-put ov 'markdown-ts-code-end-marker (set-marker (make-marker) - node-end)) + (let ((ov (make-overlay node-start node-end nil nil t))) (overlay-put ov 'markdown-ts-code-block t) (overlay-put ov 'face face) (overlay-put ov 'priority '(nil . 10)) @@ -1625,7 +1620,8 @@ properties `markdown-ts-code-block-language' and (defun markdown-ts-at-code-block-p (&optional pos) "Return non nil if point is in a code block. If POS is nil, use point." - (get-char-property (or pos (point)) 'markdown-ts-code-block)) + (cl-some (lambda (ov) (overlay-get ov 'markdown-ts-code-block)) + (overlays-at (or pos (point))))) (defun markdown-ts-code-block-language-at (&optional pos) "Return the language symbol of the code block at POS. @@ -1633,14 +1629,18 @@ If POS is nil, use point. Returns nil if POS is not inside a fenced code block. This works regardless of whether a guest tree-sitter parser is active, since the language is stored on the code block overlay by the host parser's fontification." - (get-char-property (or pos (point)) 'markdown-ts-code-block-language)) + (cl-some (lambda (ov) (overlay-get ov 'markdown-ts-code-block-language)) + (overlays-at (or pos (point))))) (defun markdown-ts-code-block-mode-at (&optional pos) "Return the major mode for the code block at POS. If POS is nil, use point. Returns nil if POS is not inside a fenced -code block or if the language has no recognized mode." +code block, or `markdown-ts-default-code-block-mode' if the language has +no recognized mode." + (setq pos (or pos (point))) (when (markdown-ts-at-code-block-p pos) - (or (get-char-property (or pos (point)) 'markdown-ts-code-block-mode) + (or (cl-some (lambda (ov) (overlay-get ov 'markdown-ts-code-block-mode)) + (overlays-at pos)) markdown-ts-default-code-block-mode))) (defun markdown-ts--host-ranges-notifier (ranges _parser) @@ -2903,8 +2903,8 @@ node as a non-ts mode." (mode (alist-get lang markdown-ts--code-block-non-ts-modes)) (tick (buffer-chars-modified-tick)) (block-start (treesit-node-start node)) - ;; Cannot use markers 'markdown-ts-code-beg-marker - ;; 'markdown-ts-code-end-marker they are set after this + ;; Cannot rely on anything set in + ;; `markdown-ts--fontify-code-block' that runs after this ;; function runs. (node-start (save-excursion (goto-char (treesit-node-start node)) @@ -3100,6 +3100,8 @@ See `markdown-ts--run-command-in-code-block'.") (defun markdown-ts--enable-code-block-in-context-mode () "Enable `markdown-ts-code-block-in-context-mode' if in a fenced code block." + ;; Let treesit catch up with buffer edits. + (sit-for 0) (markdown-ts-code-block-in-context-mode (if (markdown-ts-at-code-block-p) 1 -1))) @@ -3200,8 +3202,12 @@ command will run in the context of the `markdown-ts-mode' buffer." (defun markdown-ts--run-command-in-code-block (block-mode command &rest args) "Run COMMAND in BLOCK-MODE. ARGS are captured by `markdown-ts--maybe-run-command-in-code-block'." - (when-let* ((beg (get-char-property (point) 'markdown-ts-code-beg-marker)) - (end (get-char-property (point) 'markdown-ts-code-end-marker)) + (when-let* ((ov (cl-some + (lambda (ov) + (when (overlay-get ov 'markdown-ts-code-block) ov)) + (overlays-at (point)))) + (beg (overlay-start ov)) + (end (overlay-end ov)) (str (buffer-substring-no-properties beg end))) ;; Use a temp (or work) buffer because treesit currently confuses ;; nodes in an indirect buffer even if the indirect buffer is not @@ -5496,20 +5502,24 @@ This enables the keymap `markdown-ts-code-block-in-context-mode-map'." (defun markdown-ts--code-block-in-context-mode-update-ov () "Manage `markdown-ts--code-block-in-context-mode-ov'." (cond (markdown-ts-code-block-in-context-mode - (let ((beg (get-char-property (point) 'markdown-ts-code-beg-marker)) - (end (get-char-property (point) 'markdown-ts-code-end-marker))) + (when-let* ((ov (cl-some + (lambda (ov) + (when (overlay-get ov 'markdown-ts-code-block) ov)) + (overlays-at (point)))) + (beg (overlay-start ov)) + (end (overlay-end ov))) (if markdown-ts--code-block-in-context-mode-ov (move-overlay markdown-ts--code-block-in-context-mode-ov beg end) (setq markdown-ts--code-block-in-context-mode-ov - (make-overlay beg end nil t nil))) - (overlay-put markdown-ts--code-block-in-context-mode-ov - 'markdown-ts-in-code-block t) - (overlay-put markdown-ts--code-block-in-context-mode-ov - 'evaporate t) - (overlay-put markdown-ts--code-block-in-context-mode-ov - 'priority '(nil . 20)) - (overlay-put markdown-ts--code-block-in-context-mode-ov - 'face 'markdown-ts-in-code-block))) + (make-overlay beg end nil nil t)) + (overlay-put markdown-ts--code-block-in-context-mode-ov + 'markdown-ts-in-code-block t) + (overlay-put markdown-ts--code-block-in-context-mode-ov + 'evaporate t) + (overlay-put markdown-ts--code-block-in-context-mode-ov + 'priority '(nil . 20)) + (overlay-put markdown-ts--code-block-in-context-mode-ov + 'face 'markdown-ts-in-code-block)))) (t (when markdown-ts--code-block-in-context-mode-ov (delete-overlay markdown-ts--code-block-in-context-mode-ov))))) @@ -5591,22 +5601,21 @@ It is up to this function's callers to call (end (treesit-node-end table))) (if markdown-ts--in-table-mode-ov ;; Move the overlay, if needed, and reset the tick if so. - (when (not (eq (overlay-start markdown-ts--in-table-mode-ov) - beg)) + (unless (and (eq (overlay-start markdown-ts--in-table-mode-ov) beg) + (eq (overlay-end markdown-ts--in-table-mode-ov) end)) (move-overlay markdown-ts--in-table-mode-ov beg end) (overlay-put markdown-ts--in-table-mode-ov 'markdown-ts-in-table-tick nil)) (setq markdown-ts--in-table-mode-ov - (make-overlay beg end nil t nil))) - (overlay-put markdown-ts--in-table-mode-ov - 'markdown-ts-in-table t) - (overlay-put markdown-ts--in-table-mode-ov - 'evaporate t) - (overlay-put markdown-ts--in-table-mode-ov - 'priority '(nil . 20)) - (overlay-put markdown-ts--in-table-mode-ov - 'face 'markdown-ts-in-table) - )) + (make-overlay beg end nil t t)) + (overlay-put markdown-ts--in-table-mode-ov + 'markdown-ts-in-table t) + (overlay-put markdown-ts--in-table-mode-ov + 'evaporate t) + (overlay-put markdown-ts--in-table-mode-ov + 'priority '(nil . 20)) + (overlay-put markdown-ts--in-table-mode-ov + 'face 'markdown-ts-in-table)))) (t (when markdown-ts--in-table-mode-ov (delete-overlay markdown-ts--in-table-mode-ov))))) From 4f1af6fa6ec4452532e84b641512255f65c7d507 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 20 Jun 2026 12:06:39 +0300 Subject: [PATCH 20/20] ; * doc/lispref/commands.texi (Interactive Codes): Clarify '*' (bug#81236). --- doc/lispref/commands.texi | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 76a3db1947b..8614ee53f87 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -388,7 +388,16 @@ It is a single, isolated character. @table @samp @item * -Signal an error if the current buffer is read-only. Special. +Signal an error if the current buffer is read-only. Special. Note that +many Emacs primitives will signal an error if a command attempts to +modify text of a read-only buffer, even if the command's interactive +spec does not include @samp{*}. So this character is for when you want +to forcibly signal an error even if the command's implementation doesn't +invoke any primitives which modify the buffer. For example, a command +that binds @code{inhibit-read-only} non-@code{nil} (because it affects +more than just read-only buffers), or a command which, depending on the +conditions, might end up not modifying the buffer, but you want it to +signal this error anyway. @item @@ Select the window mentioned in the first mouse event in the key