commit e13fb667a2179548a1b57bf1e345b5a1dc00bb24 Author: Zhengyi Fu Date: Tue Jun 16 12:49:15 2026 +0800 Support OSC 8 hyperlinks in man pages * lisp/man.el: Require `ansi-osc'. (Man-ansi-osc-handlers): New variable. (Man-fontify-manpage): Call ansi-osc-apply-on-region to buttonize OSC 8 hyperlinks. (Bug#81240) * etc/NEWS: Announce the new feature. diff --git a/etc/NEWS b/etc/NEWS index 60f4327d4eb..a13e556fa47 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -101,6 +101,13 @@ check out the repository to prepare a patch for the package maintainer. --- *** Messages from Ansible are now recognized. +** Man + +--- +*** OSC 8 hyperlinks in man pages are now buttonized. +When a man page contains OSC 8 hyperlink escape sequences, they +are now buttonized, allowing using mouse or 'RET' to follow them. + ** VC +++ diff --git a/lisp/man.el b/lisp/man.el index 3b59efa0a44..c49c4da8f04 100644 --- a/lisp/man.el +++ b/lisp/man.el @@ -88,6 +88,7 @@ ;;; Code: (require 'ansi-color) +(require 'ansi-osc) (require 'cl-lib) (defgroup man nil @@ -155,6 +156,9 @@ set `Man-ansi-color-basic-faces-vector'.") (make-obsolete-variable 'Man-ansi-color-map 'Man-ansi-color-basic-faces-vector "28.1") +(defvar Man-ansi-osc-handlers '(("8" . ansi-osc-hyperlink-handler)) + "The value used here for `ansi-osc-handlers'.") + (defcustom Man-notify-method 'friendly "Selects the behavior when manpage is ready. This variable may have one of the following values, where (sf) means @@ -1377,6 +1381,8 @@ Same for the ANSI bold and normal escape sequences." (let ((ansi-color-apply-face-function #'ansi-color-apply-text-property-face) (ansi-color-basic-faces-vector Man-ansi-color-basic-faces-vector)) (ansi-color-apply-on-region (point-min) (point-max))) + (let ((ansi-osc-handlers Man-ansi-osc-handlers)) + (ansi-osc-apply-on-region (point-min) (point-max))) ;; Other highlighting. (let ((buffer-undo-list t)) (if (< (buffer-size) (position-bytes (point-max))) commit cc78db98f1774e2f3bc9f5df60c1fccb6f9f36da Author: Stéphane Marks Date: Sun Jun 14 12:45:12 2026 -0400 ; Backward compatibility for variables set via 'setopt--set-local' (bug#81120) Ensure that buffer locals are set despite setters not supporting 'buffer-local (signaling an error is too heavy handed). * lisp/cus-edit.el (setopt--set-local): If the defcustom setter does not support 'setopt-local', warn and set the buffer local. diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index f592a913546..18e649987f2 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1181,7 +1181,8 @@ Consult `setopt-local-type-mismatch'." (lambda (x v &optional _) (set-local x v))) variable value 'buffer-local) (wrong-number-of-arguments - (error "The setter of %S does not support setopt-local" variable)))))) + (warn "The setter of %S lacks support for setopt-local" variable) + (set-local variable value)))))) ;;;###autoload (defun customize-save-variable (variable value &optional comment) commit 0ff6ee371f03aba3e52469811c7c783e945a03c8 Author: Andrea Alberti Date: Sat Jun 20 14:34:17 2026 +0200 Fix :align-to 'center' when line numbers are displayed When line numbers are shown, 'center' was computed as the center of the whole text area, which includes the line-number display, so it landed half the line-number width too far to the right. Center it on the editable text area instead. (Bug#81275) * src/xdisp.c (calc_pixel_width_or_height): Correct the adjustment of 'center' for line-number display, so 'center' is the center of the editable part of the text area. * doc/lispref/display.texi (Pixel Specification): Say that 'center' denotes the center of the editable text area. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index ae7d314c795..88654af4b09 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5701,7 +5701,9 @@ edge, center, or right edge of the text area. When the window displays line numbers, and @code{:align-to} is used in display properties of buffer text (as opposed to header line, see below), the @code{left} and the @code{center} positions are offset to account for -the screen space taken by the line-number display. +the screen space taken by the line-number display. In particular, +@code{center} then denotes the center of the editable text area, i.e.@: +the text area excluding the line-number display. Any of the above window elements (except @code{text}) can also be used with @code{:align-to} to specify that the position is relative to diff --git a/src/xdisp.c b/src/xdisp.c index 295a13b99ed..f991adb7d98 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -30506,11 +30506,12 @@ calc_pixel_width_or_height (double *res, struct it *it, /* 'right': right edge of the text area. */ if (EQ (prop, Qright)) return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA)); - /* 'center': the center of the text area. */ + /* 'center': the center of the editable text area, i.e. the text + area excluding the line-number display. */ if (EQ (prop, Qcenter)) return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) - + LNUM_ONCE - + window_box_width (it->w, TEXT_AREA) / 2); + + (LNUM_ONCE + + window_box_width (it->w, TEXT_AREA)) / 2); /* 'left-fringe': left edge of the left fringe. */ if (EQ (prop, Qleft_fringe)) return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w) commit 5e48f106852d36359ad1bee9f54e9fa94d568132 Author: Andrea Alberti Date: Wed Jun 17 18:31:20 2026 +0200 Fix :align-to when a number precedes a window element * src/xdisp.c (calc_pixel_width_or_height): Track the line-number width in a new LNUM_ADDED argument instead of overloading *ALIGN_TO, so it is counted once and a window element following a numeric term is still recognized. (Bug#81253) (produce_stretch_glyph, display_min_width): Pass the new argument. diff --git a/src/xdisp.c b/src/xdisp.c index 4af9bcca428..295a13b99ed 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -857,7 +857,7 @@ bool help_echo_showing_p; enum { REDISPLAY_SOME = 2}; /* Arbitrary choice. */ static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object, - struct font *, bool, int *); + struct font *, bool, int *, bool *); void redisplay_other_windows (void) @@ -5807,7 +5807,7 @@ display_min_width (struct it *it, ptrdiff_t charpos, font = face->font ? face->font : FRAME_FONT (it->f); calc_pixel_width_or_height (&width, it, XCAR (it->min_width_property), - font, true, NULL); + font, true, NULL, NULL); width -= it->current_x - it->min_width_start; /* It makes no sense to try to obey min-width which yields a stretch that ends beyond the visible portion of the @@ -5823,7 +5823,7 @@ display_min_width (struct it *it, ptrdiff_t charpos, { calc_pixel_width_or_height (&width, it, XCAR (it->min_width_property), - NULL, true, NULL); + NULL, true, NULL, NULL); width -= (it->current_x - it->min_width_start) / FRAME_COLUMN_WIDTH (it->f); if (width > 0 @@ -30391,15 +30391,26 @@ display may depend on `buffer-invisibility-spec', which see. */) If ALIGN_TO is NULL, returns the result in *RES. If ALIGN_TO is non-NULL, the value of *ALIGN_TO is a window-relative pixel coordinate, and *RES is the additional pixel width from that point - till the end of the stretch glyph. If *ALIGN_TO is negative, it - means no element contributed to alignment (yet). The value starts at - -1, and is set to either -2 or a positive number once we've processed - the first element that contributes to the alignment. + till the end of the stretch glyph. *ALIGN_TO starts at -1 and stays + negative until a window element (e.g. 'left' or 'center') contributes + an anchor position, at which point it holds that non-negative + coordinate. + + LNUM_ADDED, if non-NULL, must point to a flag initialized to false. + The default text-area base, which includes the line-number width, + must contribute to the alignment exactly once; whichever term first + establishes that base adds the line-number width and sets + *LNUM_ADDED, so it is never counted more than once per alignment. + Because of the recursive nature of the function, the state needs to + be managed with a pointer: if the code flow branches into subcalls of + the same function and one of the subcalls applies the line-number + width offset, the change of state needs to propagate to the sibling + subcalls to avoid applying the offset once again. WIDTH_P non-zero means take the width dimension or X coordinate of the object specified by PROP, WIDTH_P zero means take the height - dimension or the Y coordinate. (Therefore, if ALIGN_TO is - non-NULL, WIDTH_P should be non-zero.) + dimension or the Y coordinate. (Therefore, if ALIGN_TO is non-NULL, + WIDTH_P should be non-zero.) FONT is the font of the face of the surrounding text. @@ -30407,8 +30418,9 @@ display may depend on `buffer-invisibility-spec', which see. */) calculated, i.e. if PROP is a valid spec. */ static bool -calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, - struct font *font, bool width_p, int *align_to) +calc_pixel_width_or_height (double *res, struct it *it, + Lisp_Object prop, struct font *font, + bool width_p, int *align_to, bool *lnum_added) { /* Don't adjust for line number if we didn't yet produce it for this screen line. This is for when this function is called from @@ -30419,6 +30431,11 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, # define OK_PIXELS(val) (*res = (val), true) # define OK_ALIGN_TO(val) (*align_to = (val), true) + /* Add the line-number width to an alignment base only once; + LNUM_ONCE yields it the first time and 0 after. */ +# define LNUM_ONCE (lnum_added && !*lnum_added \ + ? (*lnum_added = true, lnum_pixel_width) \ + : 0) if (NILP (prop)) return OK_PIXELS (0); @@ -30479,20 +30496,20 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, /* ':align_to'. First time we compute the value, window elements are interpreted as the position of the element's left edge. */ - if (align_to && *align_to == -1) + if (align_to && *align_to < 0) { *res = 0; /* 'left': left edge of the text area. */ if (EQ (prop, Qleft)) return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) - + lnum_pixel_width); + + LNUM_ONCE); /* 'right': right edge of the text area. */ if (EQ (prop, Qright)) return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA)); /* 'center': the center of the text area. */ if (EQ (prop, Qcenter)) return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) - + lnum_pixel_width + + LNUM_ONCE + window_box_width (it->w, TEXT_AREA) / 2); /* 'left-fringe': left edge of the left fringe. */ if (EQ (prop, Qleft_fringe)) @@ -30544,15 +30561,12 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, int base_unit = (width_p ? FRAME_COLUMN_WIDTH (it->f) : FRAME_LINE_HEIGHT (it->f)); - /* `align_to' starts at -1. A numeric value without an explicit - base is relative to the text area's left edge, so account for - line numbers once and mark the default base as consumed, so we - don't account for the line-number width more than once. */ - if (width_p && align_to && *align_to == -1) - { - *align_to = -2; - return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width); - } + /* A numeric value is measured from the text area's left edge + until a window element sets an anchor. While *align_to < 0, + include the line-number width, but only once per alignment via + the macro LNUM_ONCE. */ + if (width_p && align_to && *align_to < 0) + return OK_PIXELS (XFLOATINT (prop) * base_unit + LNUM_ONCE); return OK_PIXELS (XFLOATINT (prop) * base_unit); } @@ -30591,7 +30605,8 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, while (CONSP (cdr)) { if (!calc_pixel_width_or_height (&px, it, XCAR (cdr), - font, width_p, align_to)) + font, width_p, align_to, + lnum_added)) return false; if (first) pixels = (EQ (car, Qplus) ? px : -px), first = false; @@ -30613,20 +30628,16 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, if (NUMBERP (car)) { double fact; - int offset = 0; - /* See the NUMBERP case above: the default text-area base - should apply only once to the whole pixel expression, not - once for each numeric subexpression. */ - if (width_p && align_to && *align_to == -1) - { - offset = lnum_pixel_width; - *align_to = -2; - } + /* As in the NUMBERP case above: while *align_to < 0, add the + line-number width, but only once per alignment via the macro + LNUM_ONCE. */ + int offset = (width_p && align_to && *align_to < 0) ? LNUM_ONCE : 0; pixels = XFLOATINT (car); if (NILP (cdr)) return OK_PIXELS (pixels + offset); if (calc_pixel_width_or_height (&fact, it, cdr, - font, width_p, align_to)) + font, width_p, align_to, + lnum_added)) return OK_PIXELS (pixels * fact + offset); return false; } @@ -32858,9 +32869,13 @@ produce_stretch_glyph (struct it *it) eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace)); plist = XCDR (it->object); + /* Seeds calc_pixel_width_or_height's recursion; must start false. + Its value on return is ignored here, hence the name. */ + bool lnum_added_ignored = false; + /* Compute the width of the stretch. */ if ((prop = plist_get (plist, QCwidth), !NILP (prop)) - && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL)) + && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL, NULL)) { /* Absolute width `:width WIDTH' specified and valid. */ zero_width_ok_p = true; @@ -32905,7 +32920,7 @@ produce_stretch_glyph (struct it *it) } else if ((prop = plist_get (plist, QCalign_to), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, true, - &align_to)) + &align_to, &lnum_added_ignored)) { int x = it->current_x + (it->align_visually_p ? 0 @@ -32959,7 +32974,7 @@ produce_stretch_glyph (struct it *it) font ? normal_char_height (font, ' ') : FRAME_LINE_HEIGHT (it->f); if ((prop = plist_get (plist, QCheight), !NILP (prop)) - && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL)) + && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL, NULL)) { height = (int)tem; zero_height_ok_p = true; @@ -32980,7 +32995,7 @@ produce_stretch_glyph (struct it *it) NUMVAL (prop) > 0 && NUMVAL (prop) <= 100) ascent = height * NUMVAL (prop) / 100.0; else if (!NILP (prop) - && calc_pixel_width_or_height (&tem, it, prop, font, false, 0)) + && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL, NULL)) ascent = min (max (0, (int)tem), height); else ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font); commit 9195e692ea03336ff30e77536f3ff9369f05dfa8 Author: Manuel Giraud Date: Wed Jun 17 14:46:36 2026 +0200 Fix display of overlay arrow in margin Follow-up on bug#81109. * src/xdisp.c (get_overlay_arrow_glyph_row): Add a parameter to select the base face. (display_line): Use it to default to margin face for drawing overlay arrow in margin. Also fix placement calculation. diff --git a/src/xdisp.c b/src/xdisp.c index 444878a7d6d..4af9bcca428 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -23780,7 +23780,8 @@ usage: (trace-to-stderr STRING &rest OBJECTS) */) fringe. */ static struct glyph_row * -get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) +get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string, + enum face_id face_id) { struct frame *f = XFRAME (WINDOW_FRAME (w)); struct buffer *buffer = XBUFFER (w->contents); @@ -23819,7 +23820,13 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) /* Get its face. */ ilisp = make_fixnum (char_num++); face = Fget_text_property (ilisp, Qface, overlay_arrow_string); - it.face_id = compute_char_face (f, it.char_to_display, face); + + /* If no face was found in the overlay arrow string, use the one + provided by the caller. */ + if (NILP (face)) + it.face_id = lookup_basic_face (it.w, f, face_id); + else + it.face_id = compute_char_face (f, it.char_to_display, face); /* Compute its width, get its glyphs. */ n_glyphs_before = it.glyph_row->used[TEXT_AREA]; @@ -26749,32 +26756,44 @@ display_line (struct it *it, int cursor_vpos) /* Overlay arrow in window redisplay is a fringe bitmap. */ if (STRINGP (overlay_arrow_string)) { + short left_margin_glyphs + = row->glyphs[TEXT_AREA] - row->glyphs[LEFT_MARGIN_AREA]; struct glyph_row *arrow_row - = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string); - struct glyph *glyph = arrow_row->glyphs[TEXT_AREA]; - struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA]; + = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string, + MARGIN_FACE_ID); + short arrow_used_glyphs = arrow_row->used[TEXT_AREA]; + struct glyph *glyph; + struct glyph *arrow_end; struct glyph *p, *p2, *end, *where; short *p_used; + enum glyph_row_area area; /* When possible, put the arrow glyphs at the start of the left margin. Otherwise put them at the start of the text - area. */ - if (WINDOW_LEFT_MARGIN_WIDTH (it->w) >= arrow_row->used[TEXT_AREA]) - { - p = where = row->glyphs[LEFT_MARGIN_AREA]; - p_used = &(row->used[LEFT_MARGIN_AREA]); - row->used[LEFT_MARGIN_AREA] += arrow_row->used[TEXT_AREA]; - } + area. Also privilege the margin face in the margin. */ + if (left_margin_glyphs >= arrow_used_glyphs) + area = LEFT_MARGIN_AREA; else { - p = where = row->glyphs[TEXT_AREA]; - p_used = &(row->used[TEXT_AREA]); + arrow_row = get_overlay_arrow_glyph_row (it->w, + overlay_arrow_string, + DEFAULT_FACE_ID); + arrow_used_glyphs = arrow_row->used[TEXT_AREA]; + area = TEXT_AREA; } + glyph = arrow_row->glyphs[TEXT_AREA]; + arrow_end = glyph + arrow_used_glyphs; + p = where = row->glyphs[area]; + p_used = &(row->used[area]); /* Copy the arrow glyphs. */ while (glyph < arrow_end) *p++ = *glyph++; + /* Update the 'used' count of the area where we copied the + arrow. */ + row->used[area] = max (row->used[area], arrow_used_glyphs); + /* Throw away padding glyphs. */ p2 = p; end = where + *p_used; commit 4cfcf6ac67b079cb1b12758595c40c5f1c1ffc8b Merge: 6505ac5c940 e78a0fc9f4d Author: Eli Zaretskii Date: Sat Jun 20 07:20:28 2026 -0400 Merge from origin/emacs-31 e78a0fc9f4d Resurrect effect of 2nd arg t in 'format-mode-line' commit e78a0fc9f4d38c524601dacfa5b01b060f46c764 Author: Eli Zaretskii Date: Sat Jun 20 14:18:16 2026 +0300 Resurrect effect of 2nd arg t in 'format-mode-line' * src/xdisp.c (Fformat_mode_line): Resurrect support for FACE = t. Doc fix. (Bug#81271) * doc/lispref/modes.texi (Emulating Mode Line): Fix documentation of 'format-mode-line' when 2nd argument is t. * test/src/xdisp-tests.el (xdisp-test-format-mode-line): New test. diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 5f0e9a0fade..a2cc2198108 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -2869,7 +2869,7 @@ The value string normally has text properties that correspond to the faces, keymaps, etc., that the mode line would have. Any character for which no @code{face} property is specified by @var{format} gets a default value determined by @var{face}. If @var{face} is @code{t}, that -stands for either @code{mode-line} if @var{window} is selected, +stands for either @code{mode-line-active} if @var{window} is selected, otherwise @code{mode-line-inactive}. If @var{face} is @code{nil} or omitted, that stands for the default face. If @var{face} is an integer, the value returned by this function will have no text properties. diff --git a/src/xdisp.c b/src/xdisp.c index f0c787bcb5c..5080c5253a4 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -28985,7 +28985,7 @@ By default, the format is evaluated for the currently selected window. Optional second arg FACE specifies the face property to put on all characters for which no face is specified. The value nil means the default face. The value t means whatever face the window's mode line -currently uses (either `mode-line' or `mode-line-inactive', +currently uses (either `mode-line-active' or `mode-line-inactive', depending on whether the window is the selected window or not). An integer value means the value string has no text properties. @@ -29036,6 +29036,11 @@ are the selected window and the WINDOW's buffer). */) : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID : DEFAULT_FACE_ID; + if (EQ (face, Qt)) + face = EQ (window, selected_window) + ? Qmode_line_active + : Qmode_line_inactive; + old_buffer = current_buffer; /* Save things including mode_line_proptrans_alist, diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el index 3b5ab902cc2..4369c00ca34 100644 --- a/test/src/xdisp-tests.el +++ b/test/src/xdisp-tests.el @@ -179,4 +179,17 @@ int main () { (buffer-string))) "foo\n"))) +(ert-deftest xdisp-test-format-mode-line () + ;; 'format-mode-line' returns an empty string with no properties in + ;; noninteractive sessions. + (skip-when noninteractive) + (with-temp-buffer + (insert (format-mode-line " " t)) + (should (equal (buffer-string) #(" " 0 1 (face mode-line-active))))) + (with-temp-buffer + (insert (format-mode-line + (propertize "x" 'face 'bold-italic) + 1200000000000000000000000000)) + (should (null (get-text-property 1 'face))))) + ;;; xdisp-tests.el ends here commit 6505ac5c940ae15022b225beab3773d13de7edbb Merge: 2ba20245581 3eb124692d2 Author: Eli Zaretskii Date: Sat Jun 20 06:33:53 2026 -0400 Merge from origin/emacs-31 3eb124692d2 Fix 'format-mode-line' for integer second argument commit 3eb124692d2ed0545aaeb02d9db8c4bbecfa591f Author: Eli Zaretskii Date: Sat Jun 20 13:32:22 2026 +0300 Fix 'format-mode-line' for integer second argument * src/xdisp.c (Fformat_mode_line): Test for integers with INTEGERP. (Bug#81272) diff --git a/src/xdisp.c b/src/xdisp.c index b440b8f1825..f0c787bcb5c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -29001,7 +29001,7 @@ are the selected window and the WINDOW's buffer). */) struct window *w; struct buffer *old_buffer = NULL; int face_id; - bool no_props = FIXNUMP (face); + bool no_props = INTEGERP (face); specpdl_ref count = SPECPDL_INDEX (); Lisp_Object str; int string_start = 0; commit 2ba2024558106cbecccdb2575e6717bb97c66ea1 Merge: 3e0915c6882 4f1af6fa6ec Author: Eli Zaretskii Date: Sat Jun 20 06:26:29 2026 -0400 Merge from origin/emacs-31 4f1af6fa6ec ; * doc/lispref/commands.texi (Interactive Codes): Clarif... 75cd2771984 markdown-ts-mode: fix code block and table overlays (bug#... ae69929472d ; Improve code comment and 'winner-redo' docstring (bug#8... ca7c8208b79 markdown-ts-mode: Fix computing code block current region... c3bc0495491 Eglot: add 'nu-ts-mode' as a nushell major mode c0a33a474d3 Fix c-ts-mode bsd-style indentation of union bodies (bug#... 9d1b0c2d7f6 Fix markdown-inline incremental parsing issue (bug#81019) a94a33827b4 Avoid an unusual error when visiting a directory in Dired b6e7962700d Fix "diff-apply-buffer applies to the wrong file" 14bf2a707c6 Fix thinko in 'set-frame-size-and-position' (Bug#81193) 050ca1a40fc ; Remove NS port toolbar styling code (bug#80307) 2ac289d0968 Correct default native-comp tests a25cf2b9865 Revert "Fix the Android build" a6f54371107 (comint--intersect-regions): Fix bug#81243 ea09986daed ; * lisp/window.el (display-buffer): Fix doc-string typo. 7b4e12b51c2 ; * lisp/help.el (temp-buffer-resize-mode): Fix doc-strin... a8da2d20d07 ; * src/keyboard.c (Finsert_special_event): Fix quotes. df60bad1652 Update to Org 9.8.6 d48977dea85 src/keyboard.c (Finsert_special_event): Don't ignore unkn... 669e93ec5df Eglot: restore compatibility to Emacs 26.3 commit 3e0915c68825ca88244ddf1f670f6dd62dcd131c Author: Joshua Murphy Date: Sat Jun 20 13:11:07 2026 +0300 ; * etc/NEWS: Document 'newsticker-treeview-copy-url' (bug#81013). Copyright-paperwork-exempt: yes diff --git a/etc/NEWS b/etc/NEWS index 672e8b62971..60f4327d4eb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -136,6 +136,14 @@ with named choices for the predefined search functions ('outline-search-from-regexp' and 'outline-search-level') as well as the default nil and arbitrary user functions. +** Newsticker + +--- +*** New command to copy the URL of the selected newsticker item. +The new command 'newsticker-copy-url', bound to 'w', adds the URL of +the currently selected item in the list view to the kill-ring. + + * New Modes and Packages in Emacs 32.1 commit dc6287d1130c45b088860371a88a01e35a29b95b Author: Joshua Murphy Date: Sat May 16 14:02:57 2026 -0400 Add function to copy url of newsticker item * lisp/net/newst-treeview.el (newsticker-treeview-copy-url): Allow copying selected url. (newsticker-treeview-mode-map): Add binding. (Bug#81013) Copyright-paperwork-exempt: yes diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el index 8b5f8a8528f..dd7659d5bc7 100644 --- a/lisp/net/newst-treeview.el +++ b/lisp/net/newst-treeview.el @@ -1191,6 +1191,15 @@ Arguments are ignored." (if newsticker-automatically-mark-visited-items-as-old (newsticker-treeview-mark-item-old)))))) +(defun newsticker-treeview-copy-url () + "Copy the url for the current item." + (interactive) + (let ((url (url-encode-url + (newsticker--link + (newsticker--treeview-get-selected-item))))) + (kill-new url) + (message "Copied %s" url))) + (defun newsticker--treeview-buffer-init () "Initialize all treeview buffers." (setq newsticker--treeview-buffers nil) @@ -2040,6 +2049,7 @@ Return t if groups have changed, nil otherwise." "s" #'newsticker-treeview-save "u" #'newsticker-treeview-update "v" #'newsticker-treeview-browse-url + "w" #'newsticker-treeview-copy-url ;;"C-j" #'newsticker-treeview-scroll-item ;;"RET" #'newsticker-treeview-scroll-item "M-m" #'newsticker-group-move-feed commit 4f1af6fa6ec4452532e84b641512255f65c7d507 Author: Eli Zaretskii Date: Sat Jun 20 12:06:39 2026 +0300 ; * doc/lispref/commands.texi (Interactive Codes): Clarify '*' (bug#81236). 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 commit 9f61797da5f7e5c7b1a50dbf8f2cae4c6355ec60 Author: Morgan Willcock Date: Tue Jun 16 19:29:20 2026 +0100 Accept file:// scheme in 'mml-expand-html-into-multipart-related' * lisp/gnus/mml.el (mml-expand-html-into-multipart-related): Accept URLs which both use a file:// scheme and have an empty host component. These URLs describe absolute local file names and are the only format accepted by 'url-generic-parse-url' which can contain a Windows driver letter. (Bug#81250) diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 88217b15398..75430ba2e6e 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -556,12 +556,19 @@ type detected." (libxml-parse-html-region (point) (progn (forward-sexp) (point)))))) (end (point)) - (parsed (url-generic-parse-url (cdr (assq 'src (cadr img)))))) - (when (and (null (url-type parsed)) + (url (cdr (assq 'src (cadr img)))) + (parsed (url-generic-parse-url url))) + (when (and (let ((type (url-type parsed))) + (or + ;; No scheme. + (null type) + ;; A file scheme with an empty host part. + (and (string-equal type "file") + (string-empty-p (url-host parsed))))) (not (zerop (length (url-filename parsed)))) (file-exists-p (url-filename parsed))) (goto-char start) - (when (search-forward (url-filename parsed) end t) + (when (search-forward url end t) (let ((cid (format "fsf.%d" cid))) (replace-match (concat "cid:" cid) t t) (push (list cid (url-filename parsed) commit 75cd27719849169716283d77e42b4f8c439808a5 Author: Stéphane Marks Date: Thu Jun 11 14:26:21 2026 -0400 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. 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))))) commit ae69929472d4cf20e642a63fccd4e3611567478e Author: Ivar Rummelhoff Date: Sun Jun 14 13:30:12 2026 +0200 ; Improve code comment and 'winner-redo' docstring (bug#81235). 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) commit d0087b33461de703b6f69eefefa5f42821f57a76 Author: kobarity Date: Sun Jun 14 17:10:00 2026 +0900 Sanitize sys.path when executing Python import management * lisp/progmodes/python.el (python--list-imports): Add sanitizing sys.path. (python--run-module): New constant. (python--do-isort, python-fix-imports): Use it. (Bug#70440) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 86336979067..962f9c5a031 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -7056,6 +7056,10 @@ REPORT-FN is Flymake's callback function." ;;; Import management (defconst python--list-imports "\ +import sys + +sys.path = [p for p in sys.path if p] + from sys import argv, exit, stdin try: @@ -7164,6 +7168,17 @@ PROMPT string, is made unless there is a single candidate." (unless (string-empty-p statement) statement))) +(defconst python--run-module "\ +import runpy, sys + +sys.path = [p for p in sys.path if p] + +runpy.run_module(sys.argv.pop(1), run_name='__main__', alter_sys=True) +" + "Script to run a Python module. +It removes the leading empty string from `sys.path' before executing the +module.") + (defun python--do-isort (&rest args) "Edit the current buffer using isort called with ARGS. Return non-nil if the buffer was actually modified." @@ -7178,7 +7193,7 @@ Return non-nil if the buffer was actually modified." (append (split-string-shell-command python-interpreter-args) - '("-m" "isort" "-") + `("-c" ,python--run-module "isort" "-") args))) (tick (buffer-chars-modified-tick))) (unless (eq 0 status) @@ -7272,7 +7287,7 @@ and may appear to hang." (append (split-string-shell-command python-interpreter-args) - '("-m" "pyflakes")))) + `("-c" ,python--run-module "pyflakes")))) (goto-char (point-min)) (when (looking-at-p ".* No module named pyflakes$") (error "%s couldn't find pyflakes" python-interpreter)) commit ca7c8208b7979df9951c8d63e8f4a638d0b22b66 Author: Stéphane Marks Date: Wed Jun 10 13:34:22 2026 -0400 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. 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)) commit c3bc04954913be4fdb704620044d1178ad44f2c6 Author: Oleksandr Makhmudov Date: Tue Jun 9 11:43:14 2026 +0200 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 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")) commit c0a33a474d3f536357b125996b16a9ace484199d Author: समीर सिंह Sameer Singh Date: Wed Jun 17 16:56:12 2026 +0530 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. 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; +}; +=-=-= commit 9d1b0c2d7f64d8367a7d700041d2c4a3605663e7 Author: Yuan Fu Date: Thu May 28 22:43:09 2026 -0700 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. 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. commit a94a33827b4048accf43b93d3cd7958b1832559f Author: Stephen Berman Date: Fri Jun 19 10:13:22 2026 +0200 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. 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 commit b6e7962700dd1a7ae774b9f2ae2a2c0d9e33151d Author: Dmitry Gutov Date: Fri Jun 19 06:35:44 2026 +0300 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. 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 commit 14bf2a707c68f7b8eb35dd98446e00741d52370e Author: Martin Rudalics Date: Thu Jun 18 16:41:23 2026 +0200 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). 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))) commit 050ca1a40fcf6a6dc1d1b1815c7dbc3dac53696b Author: Alan Third Date: Sun Jun 14 15:09:28 2026 +0100 ; Remove NS port toolbar styling code (bug#80307) Reverts cbf9c5873056657865c5a149ece5122a8d03011a. * src/nsterm.m: Remove the code that calls setToolbarStyle. 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 } commit 2ac289d0968581ea93a37c15abbcc93d794bb7e3 Author: JD Smith Date: Fri Jun 5 18:34:24 2026 -0400 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. 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 commit a25cf2b986560cfe82f4bd26eaa1526a70c1a072 Author: JD Smith Date: Tue Jun 16 17:11:44 2026 -0400 Revert "Fix the Android build" This reverts commit 916572f6e0ab3e36f7098b6d9b5ff19f87240da4, in favor of another fix. 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], [], commit a6f543711071bfab8a7dbf6eb5c9974a1fba802e Author: Stefan Monnier Date: Tue Jun 16 09:57:48 2026 -0400 (comint--intersect-regions): Fix bug#81243 * lisp/comint.el (comint--intersect-regions): Fix syntax-propertization. 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))))) commit ea09986daedbe50e1115cd6de36fb45f98f0ba40 Author: Martin Rudalics Date: Mon Jun 15 10:46:11 2026 +0200 ; * lisp/window.el (display-buffer): Fix doc-string typo. 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 commit 7b4e12b51c273a62b01f014897958a84abb9459c Author: Martin Rudalics Date: Mon Jun 15 10:41:00 2026 +0200 ; * lisp/help.el (temp-buffer-resize-mode): Fix doc-string typo. 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, commit a8da2d20d0767a7aff5df4f16a163572f57cd254 Author: Eli Zaretskii Date: Sun Jun 14 07:21:39 2026 +0300 ; * src/keyboard.c (Finsert_special_event): Fix quotes. 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. */ commit df60bad16529e3709ef200adbf599da456509332 Author: Kyle Meyer Date: Sat Jun 13 23:59:15 2026 -0400 Update to Org 9.8.6 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]*")))) commit d48977dea8521aacaead07503047c63f3a17e542 Author: Stefan Monnier Date: Sat Jun 13 18:27:26 2026 -0400 src/keyboard.c (Finsert_special_event): Don't ignore unknown events 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); commit 669e93ec5dfe235da95ed0b7beb6c06df2384dd8 Author: João Távora Date: Sat Jun 13 16:15:44 2026 +0100 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. 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))