From d5c2973cd10c38512f6e568f097bedca46ff5f48 Mon Sep 17 00:00:00 2001
From: Jaakko Paju <jaakko.paju@wolt.com>
Date: Sat, 23 Mar 2024 08:25:08 +0200
Subject: [PATCH] Fix repeat last motion for goto next/prev diagnostic (#9966)

---
 book/src/keymap.md         |  2 +-
 helix-term/src/commands.rs | 69 +++++++++++++++++++++-----------------
 2 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/book/src/keymap.md b/book/src/keymap.md
index bb09b031..60ada4a2 100644
--- a/book/src/keymap.md
+++ b/book/src/keymap.md
@@ -49,7 +49,7 @@ Normal mode is the default mode when you launch helix. You can return to it from
 | `T`                   | Find 'till previous char                           | `till_prev_char`            |
 | `F`                   | Find previous char                                 | `find_prev_char`            |
 | `G`                   | Go to line number `<n>`                            | `goto_line`                 |
-| `Alt-.`               | Repeat last motion (`f`, `t` or `m`)               | `repeat_last_motion`        |
+| `Alt-.`               | Repeat last motion (`f`, `t`, `m`, `[` or `]`)     | `repeat_last_motion`        |
 | `Home`                | Move to the start of the line                      | `goto_line_start`           |
 | `End`                 | Move to the end of the line                        | `goto_line_end`             |
 | `Ctrl-b`, `PageUp`    | Move page up                                       | `page_up`                   |
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index a5e79a53..291ab1fe 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -3439,48 +3439,55 @@ fn goto_last_diag(cx: &mut Context) {
 }
 
 fn goto_next_diag(cx: &mut Context) {
-    let (view, doc) = current!(cx.editor);
+    let motion = move |editor: &mut Editor| {
+        let (view, doc) = current!(editor);
 
-    let cursor_pos = doc
-        .selection(view.id)
-        .primary()
-        .cursor(doc.text().slice(..));
+        let cursor_pos = doc
+            .selection(view.id)
+            .primary()
+            .cursor(doc.text().slice(..));
 
-    let diag = doc
-        .diagnostics()
-        .iter()
-        .find(|diag| diag.range.start > cursor_pos)
-        .or_else(|| doc.diagnostics().first());
+        let diag = doc
+            .diagnostics()
+            .iter()
+            .find(|diag| diag.range.start > cursor_pos)
+            .or_else(|| doc.diagnostics().first());
 
-    let selection = match diag {
-        Some(diag) => Selection::single(diag.range.start, diag.range.end),
-        None => return,
+        let selection = match diag {
+            Some(diag) => Selection::single(diag.range.start, diag.range.end),
+            None => return,
+        };
+        doc.set_selection(view.id, selection);
     };
-    doc.set_selection(view.id, selection);
+
+    cx.editor.apply_motion(motion);
 }
 
 fn goto_prev_diag(cx: &mut Context) {
-    let (view, doc) = current!(cx.editor);
+    let motion = move |editor: &mut Editor| {
+        let (view, doc) = current!(editor);
 
-    let cursor_pos = doc
-        .selection(view.id)
-        .primary()
-        .cursor(doc.text().slice(..));
+        let cursor_pos = doc
+            .selection(view.id)
+            .primary()
+            .cursor(doc.text().slice(..));
 
-    let diag = doc
-        .diagnostics()
-        .iter()
-        .rev()
-        .find(|diag| diag.range.start < cursor_pos)
-        .or_else(|| doc.diagnostics().last());
+        let diag = doc
+            .diagnostics()
+            .iter()
+            .rev()
+            .find(|diag| diag.range.start < cursor_pos)
+            .or_else(|| doc.diagnostics().last());
 
-    let selection = match diag {
-        // NOTE: the selection is reversed because we're jumping to the
-        // previous diagnostic.
-        Some(diag) => Selection::single(diag.range.end, diag.range.start),
-        None => return,
+        let selection = match diag {
+            // NOTE: the selection is reversed because we're jumping to the
+            // previous diagnostic.
+            Some(diag) => Selection::single(diag.range.end, diag.range.start),
+            None => return,
+        };
+        doc.set_selection(view.id, selection);
     };
-    doc.set_selection(view.id, selection);
+    cx.editor.apply_motion(motion)
 }
 
 fn goto_first_change(cx: &mut Context) {