Subject: [PATCH] Add additional keybindings for flymake diagnostics modes
From: Jake <[email-masked]>
To: [email-masked]
Cc: Spencer Baugh <[email-masked]>, Matthew Tromp <[email-masked]>
Date: Wed, 28 May 2025 11:20:34 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

Flymake diagnostic buffers have `next-error` support, but their
keymaps do not make use of it.  The attached patch by Matthew Tromp
makes `flymake-diagnostics-buffer-mode-map` and
`flymake-project-diagnostics-mode-map` more consistent with the other
`next-error` buffer keymaps, like those from occur, grep, and compile.

As discussed on emacs-devel:
https://mail.gnu.org/archive/html/emacs-devel/2025-05/msg00370.html
From 68b6201a5d9d17e9ed89f9f191e467814f747a97 Mon Sep 17 00:00:00 2001
From: Matthew Tromp <[email-masked]>
Date: Mon, 19 May 2025 15:45:21 -0400
Subject: [PATCH] Add additional keybindings for flymake diagnostics modes

This adds keybindings for C-o and C-m, and changes the bindings for n
and m, in `flymake-diagnostics-buffer-mode' and
`flymake-project-diagnostics-mode' buffers.

Previously, `flymake-project-diagnostics-mode' did not use the
keybindings for `flymake-diagnostics-buffer-mode'. RET and SPC were
never bound in `flymake-project-diagnostics-mode' buffers. This seems to
have been an oversight: since the filename and message are buttons which
call `flymake-goto-diagnostic', pressing RET still brought users to the
diagnostic at point most of the time. This change adds a
`flymake-project-diagnostics-mode-map' which inherits from
`flymake-diagnostics-buffer-mode-map'.

C-o and C-m now show and jump to the diagnostic currently at point,
similar to how `compilation-mode' works.

n and p now show the diagnostic newly under point after moving up or
down a line, which is also intended to make behavior more similar to
`compilation-mode'.

In order that other next-error buffers do not interfere with navigation
in the diagnostics buffers, this change introduces and uses new
functions, `next-error-this-buffer-no-select' and
`previous-error-this-buffer-no-select'. If we instead used
`next-error-no-select' and `previous-error-no-select', then a user who
runs `flymake-show-diagnostics-buffer', then e.g. `compile', then
returns to the diagnostics buffer and presses 'n', would be navigated to
the next error in the compilation buffer.

* lisp/progmodes/flymake.el (flymake-diagnostics-buffer-mode-map): Add
bindings.
(flymake-project-diagnostics-mode-map): Inherit bindings from
`flymake-diagnostics-buffer-mode'
* lisp/simple.el (next-error-this-buffer-no-select):
(previous-error-this-buffer-no-select): Add new commands.
---
 lisp/progmodes/flymake.el |  9 +++++++++
 lisp/simple.el            | 20 ++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 8a072b94a17..e911faf603d 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -1891,6 +1891,10 @@ 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)
     map))
 
 (defun flymake-show-diagnostic (pos &optional other-window)
@@ -2187,6 +2191,11 @@ flymake-list-only-diagnostics
 
 (defvar-local flymake--project-diagnostic-list-project nil)
 
+(defvar flymake-project-diagnostics-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map flymake-diagnostics-buffer-mode-map)
+    map))
+
 (define-derived-mode flymake-project-diagnostics-mode tabulated-list-mode
   "Flymake diagnostics"
   "A mode for listing Flymake diagnostics in a project."
diff --git a/lisp/simple.el b/lisp/simple.el
index f686907ad68..fa173b26289 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -478,6 +478,16 @@ next-error-no-select
            '(nil (inhibit-same-window . t))))
       (next-error n))))
 
+(defun next-error-this-buffer-no-select (&optional n)
+  "Move point to the next error in the current buffer and highlight match.
+Prefix arg N says how many error messages to move forwards (or
+backwards, if negative).
+Finds and highlights the source line like \\[next-error], but does not
+select the source buffer."
+  (interactive "p")
+  (next-error-select-buffer (current-buffer))
+  (next-error-no-select n))
+
 (defun previous-error-no-select (&optional n)
   "Move point to the previous error in the `next-error' buffer and highlight match.
 Prefix arg N says how many error messages to move backwards (or
@@ -487,6 +497,16 @@ previous-error-no-select
   (interactive "p")
   (next-error-no-select (- (or n 1))))
 
+(defun previous-error-this-buffer-no-select (&optional n)
+  "Move point to the previous error in the current buffer and highlight match.
+Prefix arg N says how many error messages to move forwards (or
+backwards, if negative).
+Finds and highlights the source line like \\[previous-error], but does not
+select the source buffer."
+  (interactive "p")
+  (next-error-select-buffer (current-buffer))
+  (previous-error-no-select n))
+
 ;; Internal variable for `next-error-follow-mode-post-command-hook'.
 (defvar next-error-follow-last-line nil)
 
-- 
2.31.1