diff --git a/crates/gpui/src/keymap/matcher.rs b/crates/gpui/src/keymap/matcher.rs index 934becb0d1..be7204aa67 100644 --- a/crates/gpui/src/keymap/matcher.rs +++ b/crates/gpui/src/keymap/matcher.rs @@ -73,9 +73,7 @@ impl KeystrokeMatcher { if !found_actions.is_empty() { self.pending_keystrokes.clear(); return KeyMatch::Some(found_actions); - } - - if let Some(pending_key) = pending_key { + } else if let Some(pending_key) = pending_key { self.pending_keystrokes.push(pending_key); KeyMatch::Pending } else { diff --git a/crates/vim/src/normal/search.rs b/crates/vim/src/normal/search.rs index 31fda7788f..68a8ada984 100644 --- a/crates/vim/src/normal/search.rs +++ b/crates/vim/src/normal/search.rs @@ -3,7 +3,12 @@ use search::{buffer_search, BufferSearchBar, SearchMode, SearchOptions}; use serde_derive::Deserialize; use workspace::{searchable::Direction, Workspace}; -use crate::{motion::Motion, normal::move_cursor, state::SearchState, Vim}; +use crate::{ + motion::Motion, + normal::move_cursor, + state::{Mode, SearchState}, + Vim, +}; #[derive(Clone, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] @@ -145,6 +150,7 @@ pub fn move_to_internal( Vim::update(cx, |vim, cx| { let pane = workspace.active_pane().clone(); let count = vim.take_count(cx).unwrap_or(1); + pane.update(cx, |pane, cx| { if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { let search = search_bar.update(cx, |search_bar, cx| { @@ -176,6 +182,11 @@ pub fn move_to_internal( } } }); + + if vim.state().mode.is_visual() { + vim.switch_mode(Mode::Normal, false, cx) + } + vim.clear_operator(cx); }); } @@ -465,6 +476,13 @@ mod test { cx.simulate_keystrokes(["/", "b"]); cx.simulate_keystrokes(["enter"]); cx.assert_state("aa\nˇbb\ndd\ncc\nbb\n", Mode::Normal); + + // check that searching switches to normal mode if in visual mode + cx.set_state("ˇone two one", Mode::Normal); + cx.simulate_keystrokes(["v", "l", "l"]); + cx.assert_editor_state("«oneˇ» two one"); + cx.simulate_keystrokes(["*"]); + cx.assert_state("one two ˇone", Mode::Normal); } #[gpui::test] @@ -488,5 +506,6 @@ mod test { cx.set_shared_state("ˇa.c. abcd a.c. abcd").await; cx.simulate_shared_keystrokes(["v", "3", "l", "*"]).await; cx.assert_shared_state("a.c. abcd ˇa.c. abcd").await; + cx.assert_shared_mode(Mode::Normal).await; } } diff --git a/crates/vim/src/test/neovim_backed_test_context.rs b/crates/vim/src/test/neovim_backed_test_context.rs index 384722286c..7753a4e850 100644 --- a/crates/vim/src/test/neovim_backed_test_context.rs +++ b/crates/vim/src/test/neovim_backed_test_context.rs @@ -277,6 +277,24 @@ impl NeovimBackedTestContext { self.neovim.mode().await.unwrap() } + pub async fn assert_shared_mode(&mut self, mode: Mode) { + let neovim = self.neovim_mode().await; + let editor = self.cx.mode(); + + if neovim != mode || editor != mode { + panic!( + indoc! {"Test failed (zed does not match nvim behaviour) + # desired mode: + {:?} + # neovim mode: + {:?} + # zed mode: + {:?}"}, + mode, neovim, editor, + ) + } + } + pub async fn assert_state_matches(&mut self) { self.is_dirty = false; let neovim = self.neovim_state().await;