commit 48ef7d91b13155f127aa4862ee0d4f7024494142 (HEAD, refs/remotes/origin/master) Author: Elรญas Gabriel Pรฉrez Date: Mon Nov 10 15:46:19 2025 -0600 hideshow: Fix indicators for multiple block in the same line bug#79810 * lisp/progmodes/hideshow.el (hs-hideable-region-p): Simplify. (hs-block-positions): Change return value. (hs--add-indicators): Go to the next line only if we have successfully created the overlays. (hs-hide-block-at-point, hs-hide-block): Update code. diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el index affcdd475e3..9e93916661a 100644 --- a/lisp/progmodes/hideshow.el +++ b/lisp/progmodes/hideshow.el @@ -682,11 +682,16 @@ Skip \"internal\" overlays if `hs-allow-nesting' is non-nil." (delete-overlay ov)))) (hs--refresh-indicators from to)) -(defun hs-hideable-region-p (beg end) - "Return t if region in BEG and END can be hidden." +(defun hs-hideable-region-p (&optional beg end) + "Return t if region in BEG and END can be hidden. +If BEG and END are not specified, it will try to check at the current +block at point." ;; Check if BEG and END are not in the same line number, ;; since using `count-lines' is slow. - (< beg (save-excursion (goto-char end) (line-beginning-position)))) + (if (and beg end) + (< beg (save-excursion (goto-char end) (line-beginning-position))) + (when-let* ((block (hs-block-positions))) + (apply #'hs-hideable-region-p block)))) (defun hs-make-overlay (b e kind &optional b-offset e-offset) "Return a new overlay in region defined by B and E with type KIND. @@ -729,7 +734,7 @@ to call with the newly initialized overlay." (defun hs-block-positions () "Return the current code block positions. -This returns a cons-cell with the current code block beginning and end +This returns a list with the current code block beginning and end positions. This does nothing if there is not a code block at current point." (save-match-data @@ -759,7 +764,7 @@ point." (setq block-end (or (funcall hs-adjust-block-end-function block-beg) block-end))) - (cons block-beg block-end)))))) + (list block-beg block-end)))))) (defun hs--make-indicators-overlays (beg) "Helper function to make the indicators overlays." @@ -830,9 +835,9 @@ point." (point)))) ;; Check if block is longer than 1 line. (_ (hs-hideable-region-p b-beg b-end))) - (hs--make-indicators-overlays b-beg)) - ;; Only 1 indicator per line - (forward-line 1)) + ;; Only 1 indicator per line + (when (hs--make-indicators-overlays b-beg) + (forward-line)))) `(jit-lock-bounds ,beg . ,end)) (defun hs--refresh-indicators (from to) @@ -953,8 +958,8 @@ Otherwise, return nil." (if comment-reg (hs-hide-comment-region (car comment-reg) (cadr comment-reg) end) (when-let* ((block (hs-block-positions))) - (let ((p (car-safe block)) - (q (cdr-safe block)) + (let ((p (car block)) + (q (cadr block)) ov) (if (hs-hideable-region-p p q) (progn @@ -1235,7 +1240,8 @@ Upon completion, point is repositioned and the normal hook `hs-hide-hook' is run. See documentation for `run-hooks'." (interactive "P") (hs-life-goes-on - (let ((c-reg (funcall hs-inside-comment-predicate))) + (let ((c-reg (funcall hs-inside-comment-predicate)) + (pos (point))) (cond ((and c-reg (or (null (nth 0 c-reg)) (not (hs-hideable-region-p (car c-reg) (nth 1 c-reg))))) @@ -1244,20 +1250,24 @@ Upon completion, point is repositioned and the normal hook (c-reg (hs-hide-block-at-point end c-reg)) ((or (and (eq hs-hide-block-behavior 'after-bol) - (save-excursion - (goto-char (line-beginning-position)) - (funcall hs-find-next-block-function hs-block-start-regexp - (line-end-position) nil)) + (setq pos (point)) + (goto-char (line-beginning-position)) + (catch 'hs--exit-hide + (while (and (funcall hs-find-next-block-function + hs-block-start-regexp + (line-end-position) nil) + (save-excursion + (goto-char (match-beginning 0)) + (if (hs-hideable-region-p) + (throw 'hs--exit-hide t) + t))))) (goto-char (match-beginning 0))) - (funcall hs-looking-at-block-start-predicate)) - ;; If hiding the block fails (due the block is not hideable) - ;; then just hide the parent block (if possible) - (unless (save-excursion (hs-hide-block-at-point end)) - (goto-char (1- (point))) - (funcall hs-find-block-beginning-function) - (hs-hide-block-at-point end))) - - ((funcall hs-find-block-beginning-function) + (and (goto-char pos) + (funcall hs-looking-at-block-start-predicate))) + (hs-hide-block-at-point end)) + + ((and (goto-char (line-beginning-position)) + (funcall hs-find-block-beginning-function)) (hs-hide-block-at-point end))) (run-hooks 'hs-hide-hook)))) commit 9709cb8d162c5696c9960abd4449078a4400b369 Author: Juri Linkov Date: Mon Nov 10 21:46:29 2025 +0200 Improve hideshow support for heex-ts-mode and yaml-ts-mode * lisp/progmodes/heex-ts-mode.el (heex-ts--thing-settings): Add 'defun' thing. (heex-ts-mode): Use it in 'hs-treesit-things'. * lisp/textmodes/yaml-ts-mode.el (yaml-ts-mode): Set 'hs-treesit-things' and 'hs-adjust-block-end-function'. diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el index e5cdd8d734d..dc2b9c8f528 100644 --- a/lisp/progmodes/heex-ts-mode.el +++ b/lisp/progmodes/heex-ts-mode.el @@ -152,7 +152,8 @@ Return nil if NODE is not a defun node or doesn't have a name." (_ nil))) (defvar heex-ts--thing-settings - `((sexp + `((defun ,(rx bos (or "component" "tag" "slot") eos)) + (sexp (not (or (and named ,(rx bos (or "fragment" "comment") eos)) (and anonymous @@ -262,7 +263,7 @@ Return nil if NODE is not a defun node or doesn't have a name." ;; Enable the 'sexp' navigation by default (setq-local forward-sexp-function #'treesit-forward-sexp treesit-sexp-thing 'sexp - hs-treesit-things 'list))) + hs-treesit-things '(or defun list)))) (derived-mode-add-parents 'heex-ts-mode '(heex-mode)) diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el index c50daf8cead..0f38887a758 100644 --- a/lisp/textmodes/yaml-ts-mode.el +++ b/lisp/textmodes/yaml-ts-mode.el @@ -217,6 +217,9 @@ Return nil if there is no name or if NODE is not a defun node." (treesit-major-mode-setup) + (setq-local hs-treesit-things "block_mapping_pair") + (setq-local hs-adjust-block-end-function (lambda (_) (line-end-position))) + ;; Use the `list' thing defined above to navigate only lists ;; with `C-M-n', `C-M-p', `C-M-u', `C-M-d', but not sexps ;; with `C-M-f', `C-M-b' neither adapt to 'show-paren-mode' commit d059e7516e5a70b049fe99284260af47ba0c1c10 Author: Juri Linkov Date: Mon Nov 10 20:46:40 2025 +0200 Improve hideshow support for elixir-ts-mode and heex-ts-mode * lisp/progmodes/elixir-ts-mode.el (elixir-ts--thing-settings): Add 'defun' thing. (elixir-ts-mode): Set 'hs-treesit-things'. * lisp/progmodes/heex-ts-mode.el (heex-ts-mode): Set 'hs-treesit-things'. Use bos/eos instead of bol/eol. diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index 1b57f4bb34d..fda76967335 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -591,7 +591,8 @@ "Tree-sitter font-lock feature list.") (defvar elixir-ts--thing-settings - `((sexp (not (or (and named + `((defun ,(rx bos "call" eos)) + (sexp (not (or (and named ,(rx bos (or "source" "keywords" "comment") eos)) (and anonymous @@ -798,7 +799,8 @@ Return nil if NODE is not a defun node or doesn't have a name." treesit-sexp-thing 'sexp ;; But still use 'list' for `down-list' and `up-list' treesit-sexp-thing-down-list 'list - treesit-sexp-thing-up-list 'list))) + treesit-sexp-thing-up-list 'list + hs-treesit-things '(or defun sexp)))) (derived-mode-add-parents 'elixir-ts-mode '(elixir-mode)) diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el index 2cdec337821..e5cdd8d734d 100644 --- a/lisp/progmodes/heex-ts-mode.el +++ b/lisp/progmodes/heex-ts-mode.el @@ -209,7 +209,7 @@ Return nil if NODE is not a defun node or doesn't have a name." ;; Navigation. (setq-local treesit-defun-type-regexp - (rx bol (or "component" "tag" "slot") eol)) + (rx bos (or "component" "tag" "slot") eos)) (setq-local treesit-defun-name-function #'heex-ts--defun-name) ;; Imenu @@ -261,7 +261,8 @@ Return nil if NODE is not a defun node or doesn't have a name." ;; Enable the 'sexp' navigation by default (setq-local forward-sexp-function #'treesit-forward-sexp - treesit-sexp-thing 'sexp))) + treesit-sexp-thing 'sexp + hs-treesit-things 'list))) (derived-mode-add-parents 'heex-ts-mode '(heex-mode)) commit 4358838a3b02e292e23a4c127fb5a6a4fb36ee8d Author: Sean Whitton Date: Mon Nov 10 18:08:39 2025 +0000 vc-do-command: Support discarding standard error * lisp/vc/vc-dispatcher.el (vc-do-command): Support discarding standard error. * lisp/vc/vc-hg.el (vc-hg-dir-status-files): Discard standard error of 'hg status' to avoid parsing mistakes. (vc-hg-command): Update docstring given new meaning of first argument to vc-do-command. * test/lisp/vc/vc-tests/vc-test-misc.el (vc-test-do-command-1) (vc-test-do-command-2, vc-test-do-command-3) (vc-test-do-command-4, vc-test-do-command-5) (vc-test-do-command-6, vc-test-do-command-7): New tests. diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index 39db738894a..75f3e75e0cb 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -378,22 +378,44 @@ Intended to be used as the value of `vc-filter-command-function'." (nconc (cdr edited) (and files-separator-p '("--")))))) ;;;###autoload -(defun vc-do-command (buffer okstatus command file-or-list &rest flags) - "Execute a slave command, notifying user and checking for errors. -Output from COMMAND goes to BUFFER, or the current buffer if -BUFFER is t. If the destination buffer is not already current, -set it up properly and erase it. The command is considered -successful if its exit status does not exceed OKSTATUS (if -OKSTATUS is nil, that means to ignore error status, if it is -`async', that means not to wait for termination of the -subprocess; if it is t it means to ignore all execution errors). +(defun vc-do-command (destination okstatus command file-or-list &rest flags) + "Execute an inferior command, notifying user and checking for errors. +DESTINATION specifies what to do with COMMAND's output. It can be a +buffer or the name of a buffer to insert output there, t to mean the +current buffer, or nil to discard output. +DESTINATION can also have the form (REAL-BUFFER STDERR-FILE); in that +case, REAL-BUFFER says what to do with standard output, as above, while +STDERR-FILE says what to do with standard error in the child. +STDERR-FILE may only be nil which means to discard standard error +output or t which means to mix it with standard output. +If the destination for standard output is a buffer that is not the +current buffer, set up the buffer properly and erase it. +The command is considered successful if its exit status does not exceed +OKSTATUS (if OKSTATUS is nil, that means to ignore error status, if it +is `async', that means not to wait for termination of the subprocess; if +it is t it means to ignore all execution errors). FILE-OR-LIST is the name of a working file; it may be a list of files or be nil (to execute commands that don't expect a file name or set of files). If an optional list of FLAGS is present, that is inserted into the command line before the filename. -Return the return value of the slave command in the synchronous -case, and the process object in the asynchronous case." +Return the return value of the inferior command in the synchronous case, +and the process object in the asynchronous case." + ;; STDERR-FILE is limited to nil or t, instead of also supporting + ;; putting stderr output into a buffer or file, because of how we + ;; support both synchronous and asynchronous execution. + ;; `call-process' supports STDERR-FILE being a file name but not a + ;; buffer, while `make-process' with `:file-handler' non-nil supports + ;; putting stderr output in a buffer but not in a file (see Info node + ;; `(elisp) Asynchronous Processes' for this detail). I.e. the only + ;; options supported by both `call-process' and `make-process' are + ;; discarding stderr output or mixing it with stdout. + (cl-assert (or (atom destination) + (and (length= destination 2) + (memq (cadr destination) '(t nil)))) + nil + "Invalid DESTINATION argument to `vc-do-command': %s" + destination) (pcase-let (;; Keep entire commands in *Messages* but avoid resizing the ;; echo area. Messages in this function are formatted in ;; a such way that the important parts are at the beginning, @@ -402,13 +424,17 @@ case, and the process object in the asynchronous case." (vc-inhibit-message (or (eq vc-command-messages 'log) (eq (selected-window) (active-minibuffer-window)))) + (`(,command ,file-or-list ,flags) (funcall vc-filter-command-function - command file-or-list flags))) + command file-or-list flags)) + ((or `(,stdout ,stderr) (and stdout (let stderr t))) + destination)) (save-current-buffer - (unless (or (eq buffer t) - (eq (current-buffer) (get-buffer buffer))) - (vc-setup-buffer buffer)) + (unless (or (memq stdout '(t nil)) + (eq (current-buffer) (get-buffer stdout))) + (vc-setup-buffer stdout) + (setq stdout t)) (when vc-tor (push command flags) (setq command "torsocks")) @@ -439,18 +465,24 @@ case, and the process object in the asynchronous case." (w32-quote-process-args t)) (if (eq okstatus 'async) ;; Run asynchronously. - (let ((proc - (let (process-connection-type) - (apply #'start-file-process command - (current-buffer) command squeezed)))) + (let* ((stderr-buf + (and (not stderr) + (generate-new-buffer " *temp*" t))) + (proc + (make-process :name command + :buffer (and stdout (current-buffer)) + :command (cons command squeezed) + :connection-type nil + :filter #'vc-process-filter + :sentinel #'ignore + :stderr stderr-buf + :file-handler t))) + (when stderr-buf + (vc-run-delayed (kill-buffer stderr-buf))) (when vc-command-messages (let ((inhibit-message vc-inhibit-message)) (message "Running in background: %s" full-command))) - ;; Get rid of the default message insertion, in case - ;; we don't set a sentinel explicitly. - (set-process-sentinel proc #'ignore) - (set-process-filter proc #'vc-process-filter) (setq status proc) (when vc-command-messages (vc-run-delayed @@ -463,8 +495,8 @@ case, and the process object in the asynchronous case." (let ((inhibit-message vc-inhibit-message)) (message "Running in foreground: %s" full-command))) (let ((buffer-undo-list t)) - (setq status (apply #'process-file - command nil t nil squeezed))) + (setq status (apply #'process-file command nil + (list stdout stderr) nil squeezed))) (when (and (not (eq t okstatus)) (or (not (integerp status)) (and okstatus (< okstatus status)))) diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index 84a00232c9d..7bbd5d778b6 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1518,7 +1518,7 @@ REV is the revision to check out into WORKFILE." ;; XXX: We can't pass DIR directly to 'hg status' because that ;; returns all ignored files if FILES is non-nil (bug#22481). (let ((default-directory dir)) - (apply #'vc-hg-command (current-buffer) 'async files + (apply #'vc-hg-command '(t nil) 'async files "status" (concat "-mardu" (if files "i")) "-C" (if (version<= "4.2" (vc-hg--program-version)) '("--config" "commands.status.relative=1") @@ -1700,7 +1700,7 @@ This runs the command \"hg merge\"." (defun vc-hg-command (buffer okstatus file-or-list &rest flags) "A wrapper around `vc-do-command' for use in vc-hg.el. This function differs from `vc-do-command' in that -- BUFFER may be nil +- BUFFER nil means use a buffer called \"*vc*\" - it invokes `vc-hg-program' and passes `vc-hg-global-switches' to it before FLAGS." ;; Commands which pass command line arguments which might diff --git a/test/lisp/vc/vc-tests/vc-test-misc.el b/test/lisp/vc/vc-tests/vc-test-misc.el index 0bbcefd16fd..0543d29f34a 100644 --- a/test/lisp/vc/vc-tests/vc-test-misc.el +++ b/test/lisp/vc/vc-tests/vc-test-misc.el @@ -163,5 +163,65 @@ (vc-test--exec-after-wait) (should (eq (point) (point-min)))))) +(ert-deftest vc-test-do-command-1 () + "Test `vc-run-command' synchronous, discarding stderr." + (with-temp-buffer + (vc-do-command '(t nil) 0 "sh" nil "-c" "echo foo; echo >&2 bar") + (should (equal (buffer-string) "foo\n")))) + +(ert-deftest vc-test-do-command-2 () + "Test `vc-run-command' synchronous, keeping stderr." + (with-temp-buffer + (vc-do-command t 0 "sh" nil "-c" "echo foo; echo >&2 bar") + (goto-char (point-min)) + (should (save-excursion (re-search-forward "foo" nil t))) + (should (save-excursion (re-search-forward "bar" nil t))))) + +(ert-deftest vc-test-do-command-3 () + "Test `vc-run-command' synchronous, discarding both." + (with-temp-buffer + (vc-do-command '(nil t) 0 "sh" nil "-c" "echo foo; echo >&2 bar") + (should (bobp)))) + +(ert-deftest vc-test-do-command-4 () + "Test `vc-run-command' asynchronous, discarding stderr." + (with-temp-buffer + (let ((proc (vc-do-command '(t nil) 'async "sh" nil + "-c" "echo foo; echo >&2 bar")) + success) + (vc-test--exec-after-wait) + (should (equal (buffer-string) "foo\n"))))) + +(ert-deftest vc-test-do-command-5 () + "Test `vc-run-command' asynchronous, keeping stderr." + (with-temp-buffer + (let ((proc (vc-do-command t 'async "sh" nil + "-c" "echo foo; echo >&2 bar")) + success) + (vc-test--exec-after-wait) + (goto-char (point-min)) + (should (save-excursion (re-search-forward "foo" nil t))) + (should (save-excursion (re-search-forward "bar" nil t)))))) + +(ert-deftest vc-test-do-command-6 () + "Test `vc-run-command' asynchronous, discarding both." + (with-temp-buffer + (let ((proc (vc-do-command '(nil t) 'async "sh" nil + "-c" "echo foo; echo >&2 bar")) + success) + (vc-test--exec-after-wait) + (should (bobp))))) + +(ert-deftest vc-test-do-command-7 () + "Test `vc-run-command' setting up the buffer." + (let ((buf (generate-new-buffer " *temp*" t))) + (unwind-protect + (progn + (vc-do-command (list buf nil) 0 "sh" nil + "-c" "echo foo; echo >&2 bar") + (with-current-buffer buf + (should (equal (buffer-string) "foo\n")))) + (kill-buffer buf)))) + (provide 'vc-test-misc) ;;; vc-test-misc.el ends here commit af9a137fe83f28decac03fcebec3ca3020e910de Author: Sean Whitton Date: Mon Nov 10 15:14:13 2025 +0000 ; vc-start-logentry: Require log-edit (bug#79803) * lisp/vc/vc-dispatcher.el (vc-start-logentry): Require log-edit (bug#79803). diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index 8d23ab13edd..39db738894a 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -870,7 +870,8 @@ DIFF-FUNCTION is `log-edit-diff-function' for the Log Edit buffer." ;; `log-edit-show-files' and `log-edit-maybe-show-diff' which ;; don't make sense if the user is not going to do any ;; editing, and can cause unexpected window layout changes. - (log-edit-hook (and (not immediate) log-edit-hook))) + (log-edit-hook (and (not immediate) + (require 'log-edit) log-edit-hook))) (vc-log-edit files mode backend diff-function)) (make-local-variable 'vc-log-after-operation-hook) (when after-hook commit 1772a4e468c4436e07ab4ea7098e9712c8dcae2d Author: Joรฃo Tรกvora Date: Mon Nov 10 12:28:14 2025 +0000 ; Eglot: unbreak "lsp-abiding-column" test for newer clangd Newer/newest clangd support more encodings and actually negotiate with us, so test shouldn't assume UTF-16.. * test/lisp/progmodes/eglot-tests.el (eglot-tests--lsp-abiding-column-1): Tweak. diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index b01b7d269ec..8455c8ff8db 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -1005,26 +1005,31 @@ int main() { (eglot--with-fixture '(("project" . (("foo.c" . "const char write_data[] = u8\"๐Ÿš‚๐Ÿšƒ๐Ÿš„๐Ÿš…๐Ÿš†๐Ÿšˆ๐Ÿš‡๐Ÿšˆ๐Ÿš‰๐ŸšŠ๐Ÿš‹๐ŸšŒ๐ŸšŽ๐Ÿš๐Ÿšž๐ŸšŸ๐Ÿš ๐Ÿšก๐Ÿ›ค๐Ÿ›ฒ\";")))) - (let ((eglot-server-programs + (let (expected-column + (eglot-server-programs '((c-mode . ("clangd"))))) (with-current-buffer (eglot--find-file-noselect "project/foo.c") - (setq-local eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos) - (setq-local eglot-current-linepos-function #'eglot-utf-16-linepos) (eglot--sniffing (:client-notifications c-notifs) (eglot--tests-connect) (end-of-line) + + ;; will be 71 if utf-16 was negotiated, 51 if utf-32, + ;; something else if utf-8 + (setq expected-column (funcall eglot-current-linepos-function)) + (eglot--test-message + "Looks like we negotiated %S as the offset encoding" + (list eglot-move-to-linepos-function eglot-current-linepos-function)) (insert "p ") (eglot--signal-textDocument/didChange) (eglot--wait-for (c-notifs 2) (&key params &allow-other-keys) - (message "PARAMS=%S" params) - (should (equal 71 (eglot-tests--get + (should (equal expected-column + (eglot-tests--get params '(:contentChanges 0 :range :start :character))))) (beginning-of-line) - (should (eq eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos)) - (funcall eglot-move-to-linepos-function 71) + (funcall eglot-move-to-linepos-function expected-column) (should (looking-at "p"))))))) (ert-deftest eglot-test-lsp-abiding-column () commit 683e7462df3d5b17e7da8956302069415bba6998 Author: Joรฃo Tรกvora Date: Sat Nov 8 11:58:04 2025 +0000 Flymake: fix compatibility to older emacsen (bug#79769) * lisp/progmodes/flymake.el (flymake-diagnostics-buffer-mode-map): Don't use keymap-set. (Package-Requires): Require project 0.11.1 (Version): Bump to 1.4.3. diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 460969dd9a4..ca66a6cf2d8 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -4,9 +4,9 @@ ;; Author: Pavel Kobyakov ;; Maintainer: Spencer Baugh -;; Version: 1.4.2 +;; Version: 1.4.3 ;; Keywords: c languages tools -;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) +;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.11.1")) ;; This is a GNU ELPA :core package. Avoid functionality that is not ;; compatible with the version of Emacs recorded above. @@ -1926,12 +1926,12 @@ TYPE is usually keyword `:error', `:warning' or `:note'." (defvar flymake-diagnostics-buffer-mode-map (let ((map (make-sparse-keymap))) - (define-key map (kbd "RET") 'flymake-goto-diagnostic) - (define-key map (kbd "SPC") 'flymake-show-diagnostic) - (keymap-set map "C-o" #'flymake-show-diagnostic) - (keymap-set map "C-m" #'flymake-goto-diagnostic) - (keymap-set map "n" #'next-error-this-buffer-no-select) - (keymap-set map "p" #'previous-error-this-buffer-no-select) + (define-key map (kbd "RET") #'flymake-goto-diagnostic) + (define-key map (kbd "SPC") #'flymake-show-diagnostic) + (define-key map (kbd "C-o") #'flymake-show-diagnostic) + (define-key map (kbd "C-m") #'flymake-goto-diagnostic) + (define-key map (kbd "n") #'next-error-this-buffer-no-select) + (define-key map (kbd "p") #'previous-error-this-buffer-no-select) map)) (defun flymake-show-diagnostic (pos &optional other-window) commit 411e8068dcf20fcbe3391017d4753a6bff76fb5e Author: Spencer Baugh Date: Sat Nov 8 10:02:30 2025 +0000 Eglot: consider invisibility in eldoc one-liners (bug#79779) Since we keep the invisible characters of all the server-supplied markdown, we risk that the first lines are entirely invisible. This defeats the :echo calculation in eglot-hover-eldoc-function. Fallout of bug#79552. * lisp/progmodes/eglot.el (eglot-hover-eldoc-function): Fix. Co-authored-by: Joรฃo Tรกvora diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 27e79b2f816..9b84c38349a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3775,10 +3775,12 @@ for which LSP on-type-formatting should be requested." :textDocument/hover (eglot--TextDocumentPositionParams) :success-fn (eglot--lambda ((Hover) contents range) (eglot--when-buffer-window buf - (let ((info (unless (seq-empty-p contents) - (eglot--hover-info contents range)))) - (funcall cb info - :echo (and info (string-match "\n" info)))))) + (let* ((info (unless (seq-empty-p contents) + (eglot--hover-info contents range))) + (pos (and info (string-match "\n" info)))) + (while (and pos (get-text-property pos 'invisible info)) + (setq pos (string-match "\n" info (1+ pos)))) + (funcall cb info :echo pos)))) :hint :textDocument/hover)) t))