vim: Don't enter visual mode in search/go to definition

Conrad Irwin created

Fixes: zed-industries/community#1514
Contributes: zed-industries/community#1284

Change summary

crates/editor/src/editor.rs | 15 +++++++++++++++
crates/editor/src/items.rs  |  5 ++---
crates/vim/src/vim.rs       |  4 ++++
3 files changed, 21 insertions(+), 3 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -544,6 +544,7 @@ pub struct Editor {
     pending_rename: Option<RenameState>,
     searchable: bool,
     cursor_shape: CursorShape,
+    collapse_matches: bool,
     workspace: Option<(WeakViewHandle<Workspace>, i64)>,
     keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
     input_enabled: bool,
@@ -1376,6 +1377,7 @@ impl Editor {
             searchable: true,
             override_text_style: None,
             cursor_shape: Default::default(),
+            collapse_matches: false,
             workspace: None,
             keymap_context_layers: Default::default(),
             input_enabled: true,
@@ -1515,6 +1517,17 @@ impl Editor {
         cx.notify();
     }
 
+    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
+        self.collapse_matches = collapse_matches;
+    }
+
+    fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
+        if self.collapse_matches {
+            return range.start..range.start;
+        }
+        range.clone()
+    }
+
     pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
         if self.display_map.read(cx).clip_at_line_ends != clip {
             self.display_map
@@ -6233,6 +6246,7 @@ impl Editor {
                 .to_offset(definition.target.buffer.read(cx));
 
             if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
+                let range = self.range_for_match(&range);
                 self.change_selections(Some(Autoscroll::fit()), cx, |s| {
                     s.select_ranges([range]);
                 });
@@ -6245,6 +6259,7 @@ impl Editor {
                         // When selecting a definition in a different buffer, disable the nav history
                         // to avoid creating a history entry at the previous cursor location.
                         pane.update(cx, |pane, _| pane.disable_history());
+                        let range = target_editor.range_for_match(&range);
                         target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
                             s.select_ranges([range]);
                         });

crates/editor/src/items.rs 🔗

@@ -936,9 +936,8 @@ impl SearchableItem for Editor {
         cx: &mut ViewContext<Self>,
     ) {
         self.unfold_ranges([matches[index].clone()], false, true, cx);
-        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
-            s.select_ranges([matches[index].clone()])
-        });
+        let range = self.range_for_match(&matches[index]);
+        self.change_selections(Some(Autoscroll::fit()), cx, |s| s.select_ranges([range]));
     }
 
     fn match_index_for_direction(

crates/vim/src/vim.rs 🔗

@@ -295,11 +295,15 @@ impl Vim {
             if self.enabled && editor.mode() == EditorMode::Full {
                 editor.set_cursor_shape(cursor_shape, cx);
                 editor.set_clip_at_line_ends(state.clip_at_line_end(), cx);
+                editor.set_collapse_matches(true);
                 editor.set_input_enabled(!state.vim_controlled());
                 editor.selections.line_mode = matches!(state.mode, Mode::Visual { line: true });
                 let context_layer = state.keymap_context_layer();
                 editor.set_keymap_context_layer::<Self>(context_layer, cx);
             } else {
+                // Note: set_collapse_matches is not in unhook_vim_settings, as that method is called on blur,
+                // but we need collapse_matches to persist when the search bar is focused.
+                editor.set_collapse_matches(false);
                 Self::unhook_vim_settings(editor, cx);
             }
         });