mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
vim: Fix cgn backwards movement when there is no matches (#10237)
Release Notes: - Fixed `cgn` backwards movement problem in #9982 There are two issues: - When there are no more matches, the next repetition still moves the cursor to the left. After that, the recording is cleared. For this I simply move the cursor to the right, but it doesn't work when the cursor is at the end of the line. - If `cgn` is used when there are no matches, it cleans the previous recorded actions. Maybe there should be a way to revert the recording. This also happens when using `c` and `esc` --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
0390df27d4
commit
f9bf60f017
@ -1100,6 +1100,11 @@ impl BufferSearchBar {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn match_exists(&mut self, cx: &mut ViewContext<Self>) -> bool {
|
||||
self.update_match_index(cx);
|
||||
self.active_match_index.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -172,6 +172,13 @@ pub(crate) fn repeat(cx: &mut WindowContext, from_insert_mode: bool) {
|
||||
editor.show_local_selections = false;
|
||||
})?;
|
||||
for action in actions {
|
||||
if !matches!(
|
||||
cx.update(|cx| Vim::read(cx).workspace_state.replaying),
|
||||
Ok(true)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
match action {
|
||||
ReplayableAction::Action(action) => {
|
||||
if should_replay(&action) {
|
||||
|
@ -341,6 +341,10 @@ impl Vim {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop_replaying(&mut self) {
|
||||
self.workspace_state.replaying = false;
|
||||
}
|
||||
|
||||
/// When finishing an action that modifies the buffer, stop recording.
|
||||
/// as you usually call this within a keystroke handler we also ensure that
|
||||
/// the current action is recorded.
|
||||
@ -499,6 +503,7 @@ impl Vim {
|
||||
self.sync_vim_settings(cx);
|
||||
popped_operator
|
||||
}
|
||||
|
||||
fn clear_operator(&mut self, cx: &mut WindowContext) {
|
||||
self.take_count(cx);
|
||||
self.update_state(|state| state.operator_stack.clear());
|
||||
|
@ -509,7 +509,6 @@ pub fn select_match(
|
||||
vim.update_active_editor(cx, |_, editor, _| {
|
||||
editor.set_collapse_matches(false);
|
||||
});
|
||||
|
||||
if vim_is_normal {
|
||||
pane.update(cx, |pane, cx| {
|
||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||
@ -521,21 +520,27 @@ pub fn select_match(
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
let latest = editor.selections.newest::<usize>(cx);
|
||||
start_selection = latest.start;
|
||||
end_selection = latest.end;
|
||||
});
|
||||
|
||||
let mut match_exists = false;
|
||||
pane.update(cx, |pane, cx| {
|
||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.update_match_index(cx);
|
||||
search_bar.select_match(direction, count, cx);
|
||||
match_exists = search_bar.match_exists(cx);
|
||||
});
|
||||
}
|
||||
});
|
||||
if !match_exists {
|
||||
vim.clear_operator(cx);
|
||||
vim.stop_replaying();
|
||||
return;
|
||||
}
|
||||
vim.update_active_editor(cx, |_, editor, cx| {
|
||||
let latest = editor.selections.newest::<usize>(cx);
|
||||
if vim_is_normal {
|
||||
@ -553,6 +558,7 @@ pub fn select_match(
|
||||
});
|
||||
editor.set_collapse_matches(true);
|
||||
});
|
||||
|
||||
match vim.maybe_pop_operator() {
|
||||
Some(Operator::Change) => substitute(vim, None, false, cx),
|
||||
Some(Operator::Delete) => {
|
||||
@ -561,7 +567,7 @@ pub fn select_match(
|
||||
}
|
||||
Some(Operator::Yank) => yank(vim, cx),
|
||||
_ => {} // Ignoring other operators
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1195,4 +1201,29 @@ mod test {
|
||||
cx.simulate_shared_keystrokes(["."]).await;
|
||||
cx.assert_shared_state("aa x ˇx aa aa").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_cgn_nomatch(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
||||
cx.set_shared_state("aaˇ aa aa aa aa").await;
|
||||
cx.simulate_shared_keystrokes(["/", "b", "b", "enter"])
|
||||
.await;
|
||||
cx.assert_shared_state("aaˇ aa aa aa aa").await;
|
||||
cx.simulate_shared_keystrokes(["c", "g", "n", "x", "escape"])
|
||||
.await;
|
||||
cx.assert_shared_state("aaˇaa aa aa aa").await;
|
||||
cx.simulate_shared_keystrokes(["."]).await;
|
||||
cx.assert_shared_state("aaˇa aa aa aa").await;
|
||||
|
||||
cx.set_shared_state("aaˇ bb aa aa aa").await;
|
||||
cx.simulate_shared_keystrokes(["/", "b", "b", "enter"])
|
||||
.await;
|
||||
cx.assert_shared_state("aa ˇbb aa aa aa").await;
|
||||
cx.simulate_shared_keystrokes(["c", "g", "n", "x", "escape"])
|
||||
.await;
|
||||
cx.assert_shared_state("aa ˇx aa aa aa").await;
|
||||
cx.simulate_shared_keystrokes(["."]).await;
|
||||
cx.assert_shared_state("aa ˇx aa aa aa").await;
|
||||
}
|
||||
}
|
||||
|
28
crates/vim/test_data/test_cgn_nomatch.json
Normal file
28
crates/vim/test_data/test_cgn_nomatch.json
Normal file
@ -0,0 +1,28 @@
|
||||
{"Put":{"state":"aaˇ aa aa aa aa"}}
|
||||
{"Key":"/"}
|
||||
{"Key":"b"}
|
||||
{"Key":"b"}
|
||||
{"Key":"enter"}
|
||||
{"Get":{"state":"aaˇ aa aa aa aa","mode":"Normal"}}
|
||||
{"Key":"c"}
|
||||
{"Key":"g"}
|
||||
{"Key":"n"}
|
||||
{"Key":"x"}
|
||||
{"Key":"escape"}
|
||||
{"Get":{"state":"aaˇaa aa aa aa","mode":"Normal"}}
|
||||
{"Key":"."}
|
||||
{"Get":{"state":"aaˇa aa aa aa","mode":"Normal"}}
|
||||
{"Put":{"state":"aaˇ bb aa aa aa"}}
|
||||
{"Key":"/"}
|
||||
{"Key":"b"}
|
||||
{"Key":"b"}
|
||||
{"Key":"enter"}
|
||||
{"Get":{"state":"aa ˇbb aa aa aa","mode":"Normal"}}
|
||||
{"Key":"c"}
|
||||
{"Key":"g"}
|
||||
{"Key":"n"}
|
||||
{"Key":"x"}
|
||||
{"Key":"escape"}
|
||||
{"Get":{"state":"aa ˇx aa aa aa","mode":"Normal"}}
|
||||
{"Key":"."}
|
||||
{"Get":{"state":"aa ˇx aa aa aa","mode":"Normal"}}
|
Loading…
Reference in New Issue
Block a user