diff --git a/crates/vim/src/mode_indicator.rs b/crates/vim/src/mode_indicator.rs index 7afa22b876..a093eab9a2 100644 --- a/crates/vim/src/mode_indicator.rs +++ b/crates/vim/src/mode_indicator.rs @@ -41,14 +41,9 @@ impl Render for ModeIndicator { return div().into_any(); }; - let text = match mode { - Mode::Normal => "-- NORMAL --", - Mode::Insert => "-- INSERT --", - Mode::Visual => "-- VISUAL --", - Mode::VisualLine => "-- VISUAL LINE --", - Mode::VisualBlock => "-- VISUAL BLOCK --", - }; - Label::new(text).size(LabelSize::Small).into_any_element() + Label::new(format!("-- {} --", mode)) + .size(LabelSize::Small) + .into_any_element() } } diff --git a/crates/vim/src/object.rs b/crates/vim/src/object.rs index f7718cd1b7..72aa189d9f 100644 --- a/crates/vim/src/object.rs +++ b/crates/vim/src/object.rs @@ -131,17 +131,22 @@ impl Object { pub fn target_visual_mode(self, current_mode: Mode) -> Mode { match self { - Object::Word { .. } if current_mode == Mode::VisualLine => Mode::Visual, - Object::Word { .. } => current_mode, - Object::Sentence + Object::Word { .. } + | Object::Sentence | Object::Quotes | Object::BackQuotes - | Object::DoubleQuotes - | Object::VerticalBars - | Object::Parentheses + | Object::DoubleQuotes => { + if current_mode == Mode::VisualBlock { + Mode::VisualBlock + } else { + Mode::Visual + } + } + Object::Parentheses | Object::SquareBrackets | Object::CurlyBrackets | Object::AngleBrackets + | Object::VerticalBars | Object::Argument => Mode::Visual, } } diff --git a/crates/vim/src/state.rs b/crates/vim/src/state.rs index 7a610f8820..994a8f2b76 100644 --- a/crates/vim/src/state.rs +++ b/crates/vim/src/state.rs @@ -1,4 +1,4 @@ -use std::{ops::Range, sync::Arc}; +use std::{fmt::Display, ops::Range, sync::Arc}; use collections::HashMap; use gpui::{Action, KeyContext}; @@ -17,6 +17,18 @@ pub enum Mode { VisualBlock, } +impl Display for Mode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Mode::Normal => write!(f, "NORMAL"), + Mode::Insert => write!(f, "INSERT"), + Mode::Visual => write!(f, "VISUAL"), + Mode::VisualLine => write!(f, "VISUAL LINE"), + Mode::VisualBlock => write!(f, "VISUAL BLOCK"), + } + } +} + impl Mode { pub fn is_visual(&self) -> bool { match self { diff --git a/crates/vim/src/test/neovim_backed_test_context.rs b/crates/vim/src/test/neovim_backed_test_context.rs index 0c12d64f58..0a01a62742 100644 --- a/crates/vim/src/test/neovim_backed_test_context.rs +++ b/crates/vim/src/test/neovim_backed_test_context.rs @@ -190,8 +190,10 @@ impl NeovimBackedTestContext { self.is_dirty = false; let marked_text = marked_text.replace("•", " "); let neovim = self.neovim_state().await; + let neovim_mode = self.neovim_mode().await; let editor = self.editor_state(); - if neovim == marked_text && neovim == editor { + let editor_mode = self.mode(); + if neovim == marked_text && neovim == editor && neovim_mode == editor_mode { return; } let initial_state = self @@ -213,16 +215,18 @@ impl NeovimBackedTestContext { {} # currently expected: {} - # neovim state: + # neovim ({}): {} - # zed state: + # zed ({}): {}"}, message, initial_state, self.recent_keystrokes.join(" "), marked_text.replace(" \n", "•\n"), + neovim_mode, neovim.replace(" \n", "•\n"), - editor.replace(" \n", "•\n") + editor_mode, + editor.replace(" \n", "•\n"), ) } @@ -296,27 +300,31 @@ impl NeovimBackedTestContext { pub async fn assert_state_matches(&mut self) { self.is_dirty = false; let neovim = self.neovim_state().await; + let neovim_mode = self.neovim_mode().await; let editor = self.editor_state(); + let editor_mode = self.mode(); let initial_state = self .last_set_state .as_ref() .unwrap_or(&"N/A".to_string()) .clone(); - if neovim != editor { + if neovim != editor || neovim_mode != editor_mode { panic!( indoc! {"Test failed (zed does not match nvim behaviour) # initial state: {} # keystrokes: {} - # neovim state: + # neovim ({}): {} - # zed state: + # zed ({}): {}"}, initial_state, self.recent_keystrokes.join(" "), + neovim_mode, neovim, + editor_mode, editor, ) } diff --git a/crates/vim/src/test/neovim_connection.rs b/crates/vim/src/test/neovim_connection.rs index 4de0943321..5ea82e3661 100644 --- a/crates/vim/src/test/neovim_connection.rs +++ b/crates/vim/src/test/neovim_connection.rs @@ -419,7 +419,7 @@ impl NeovimConnection { } } Some(Mode::Visual) | Some(Mode::VisualLine) | Some(Mode::VisualBlock) => { - if selection_col > cursor_col { + if (selection_row, selection_col) > (cursor_row, cursor_col) { let selection_line_length = self.read_position("echo strlen(getline(line('v')))").await; if selection_line_length > selection_col { diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index c2e1f0106f..64a14784cd 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -1005,7 +1005,6 @@ mod test { cx.simulate_shared_keystrokes(["ctrl-v", "l"]).await; cx.simulate_shared_keystrokes(["a", "]"]).await; cx.assert_shared_state("hello (in «[parens]ˇ» o)").await; - assert_eq!(cx.mode(), Mode::Visual); cx.simulate_shared_keystrokes(["i", "("]).await; cx.assert_shared_state("hello («in [parens] oˇ»)").await; @@ -1016,7 +1015,6 @@ mod test { assert_eq!(cx.mode(), Mode::VisualBlock); cx.simulate_shared_keystrokes(["o", "a", "s"]).await; cx.assert_shared_state("«ˇhello in a word» again.").await; - assert_eq!(cx.mode(), Mode::Visual); } #[gpui::test]