From 5d751cd407441a192296ae694bbbae81061ef98d Mon Sep 17 00:00:00 2001 From: Dino Date: Sat, 22 Feb 2025 02:24:54 +0000 Subject: [PATCH] vim: Handle visual selection when jumping to mark (#25360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix how vim mode handles jumping to mark, when one of vim's visual modes is active, in order to behave just like neovim. Here's a quick video showing the updated behavior ↓ https://github.com/user-attachments/assets/db91f574-d7e8-429d-952e-3435c43e31bd Closes #18131 Release Notes: - Fixed vim's visual selections when jumping to marks --- crates/vim/src/normal/mark.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/crates/vim/src/normal/mark.rs b/crates/vim/src/normal/mark.rs index 4cc717133019c0..72194b728c330c 100644 --- a/crates/vim/src/normal/mark.rs +++ b/crates/vim/src/normal/mark.rs @@ -105,7 +105,7 @@ impl Vim { _ => self.marks.get(&*text).cloned(), }; - let Some(anchors) = anchors else { return }; + let Some(mut anchors) = anchors else { return }; let is_active_operator = self.active_operator().is_some(); if is_active_operator { @@ -120,6 +120,12 @@ impl Vim { ) } } else { + // Save the last anchor so as to jump to it later. + let anchor: Option = anchors.last_mut().map(|anchor| *anchor); + let should_jump = self.mode == Mode::Visual + || self.mode == Mode::VisualLine + || self.mode == Mode::VisualBlock; + self.update_editor(window, cx, |_, editor, window, cx| { let map = editor.snapshot(window, cx); let mut ranges: Vec> = Vec::new(); @@ -132,14 +138,24 @@ impl Vim { .buffer_snapshot .anchor_before(point.to_point(&map.display_snapshot)); } + if ranges.last() != Some(&(anchor..anchor)) { ranges.push(anchor..anchor); } } - editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| { - s.select_anchor_ranges(ranges) - }) + + if !should_jump { + editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| { + s.select_anchor_ranges(ranges) + }); + } }); + + if should_jump { + if let Some(anchor) = anchor { + self.motion(Motion::Jump { anchor, line }, window, cx) + } + } } } }