vim: Fix dot repeat after macro replay not capturing insertion text (#57684)

Closes #47251

Fix dot (`.`) repeat not correctly repeating the last change after
replaying a macro (`@register`)
([#47251](https://github.com/zed-industries/zed/issues/47251))

When replaying a macro that contains text insertions,
`replay_insert_event` calls `handle_input` directly and never emits
`InputHandled`, so the `observe_insertion` subscription never fires.
This left the dot register stale — `.` after `@register` would repeat an
earlier change instead of the last one made by the macro.

Fix by calling `observe_insertion` explicitly in the
`ReplayableAction::Insertion` branch of `Replayer::next`.

Release Notes:

- Fixed dot (`.`) repeat not repeating the last change made by a macro
(`@register`).

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
Fanteria 2026-05-27 16:36:41 +02:00 committed by GitHub
parent 0464de8fdd
commit 80a4042ff5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 0 deletions

View file

@ -34,6 +34,12 @@ impl Editor {
cx.emit(EditorEvent::InputIgnored { text: text.into() });
return;
}
cx.emit(EditorEvent::InputHandled {
utf16_range_to_replace: relative_utf16_range.clone(),
text: text.into(),
});
if let Some(relative_utf16_range) = relative_utf16_range {
let selections = self
.selections

View file

@ -457,6 +457,34 @@ mod test {
cx.run_until_parked();
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("THE QUICK ˇbrown fox");
// "q l" (note after macro should be used last change made by macro)
cx.set_shared_state("ˇ").await;
cx.simulate_shared_keystrokes("q l shift-o h e l l o space w o r l d escape q")
.await;
cx.simulate_shared_keystrokes("@ l").await;
cx.shared_state()
.await
.assert_eq("hello worlˇd\nhello world\n");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state()
.await
.assert_eq("hello worlˇd\nhello world\nhello world\n");
}
#[gpui::test]
async fn test_dot_repeat_after_macro_change_motion(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("ˇfoo foo", Mode::Normal);
cx.simulate_keystrokes("q l c f o x escape q");
cx.assert_state("ˇxo foo", Mode::Normal);
cx.simulate_keystrokes("w @ l");
cx.assert_state("xo ˇxo", Mode::Normal);
cx.simulate_keystrokes(".");
cx.assert_state("xo ˇx", Mode::Normal);
}
#[gpui::test]

View file

@ -36,3 +36,25 @@
{"Put":{"state":"THE QUIˇck brown fox"}}
{"Key":"."}
{"Get":{"state":"THE QUICK ˇbrown fox","mode":"Normal"}}
{"Put":{"state":"ˇ"}}
{"Key":"q"}
{"Key":"l"}
{"Key":"shift-o"}
{"Key":"h"}
{"Key":"e"}
{"Key":"l"}
{"Key":"l"}
{"Key":"o"}
{"Key":"space"}
{"Key":"w"}
{"Key":"o"}
{"Key":"r"}
{"Key":"l"}
{"Key":"d"}
{"Key":"escape"}
{"Key":"q"}
{"Key":"@"}
{"Key":"l"}
{"Get":{"state":"hello worlˇd\nhello world\n","mode":"Normal"}}
{"Key":"."}
{"Get":{"state":"hello worlˇd\nhello world\nhello world\n","mode":"Normal"}}