From d2efa12e16943a527e89b821a5d5bac863192631 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 19 Jul 2024 13:26:55 -0600 Subject: [PATCH] vim: Fix gv after actions (#14829) Fixes: #13720 Co-Authored-By: Release Notes: - vim: Fixed `gv` after `y`, `d`, etc. ([#13760](https://github.com/zed-industries/zed/issues/13760)). --- crates/vim/src/normal/case.rs | 2 ++ crates/vim/src/normal/increment.rs | 1 + crates/vim/src/normal/paste.rs | 2 ++ crates/vim/src/normal/search.rs | 1 + crates/vim/src/normal/substitute.rs | 1 + crates/vim/src/vim.rs | 17 +++++++++++++---- crates/vim/src/visual.rs | 12 ++++++++++++ 7 files changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/vim/src/normal/case.rs b/crates/vim/src/normal/case.rs index 71c206dcc8..f9254ce5f0 100644 --- a/crates/vim/src/normal/case.rs +++ b/crates/vim/src/normal/case.rs @@ -125,7 +125,9 @@ where { Vim::update(cx, |vim, cx| { vim.record_current_action(cx); + vim.store_visual_marks(cx); let count = vim.take_count(cx).unwrap_or(1) as u32; + vim.update_active_editor(cx, |vim, editor, cx| { let mut ranges = Vec::new(); let mut cursor_positions = Vec::new(); diff --git a/crates/vim/src/normal/increment.rs b/crates/vim/src/normal/increment.rs index ffecfa17a5..e0638f50de 100644 --- a/crates/vim/src/normal/increment.rs +++ b/crates/vim/src/normal/increment.rs @@ -44,6 +44,7 @@ pub fn register(workspace: &mut Workspace, _: &mut ViewContext) { } fn increment(vim: &mut Vim, mut delta: i32, step: i32, cx: &mut WindowContext) { + vim.store_visual_marks(cx); vim.update_active_editor(cx, |vim, editor, cx| { let mut edits = Vec::new(); let mut new_anchors = Vec::new(); diff --git a/crates/vim/src/normal/paste.rs b/crates/vim/src/normal/paste.rs index dfc0ff84c3..e2ddf80408 100644 --- a/crates/vim/src/normal/paste.rs +++ b/crates/vim/src/normal/paste.rs @@ -30,7 +30,9 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext fn paste(_: &mut Workspace, action: &Paste, cx: &mut ViewContext) { Vim::update(cx, |vim, cx| { vim.record_current_action(cx); + vim.store_visual_marks(cx); let count = vim.take_count(cx).unwrap_or(1); + vim.update_active_editor(cx, |vim, editor, cx| { let text_layout_details = editor.text_layout_details(cx); editor.transact(cx, |editor, cx| { diff --git a/crates/vim/src/normal/search.rs b/crates/vim/src/normal/search.rs index ab69d9dbc6..7356faf1ec 100644 --- a/crates/vim/src/normal/search.rs +++ b/crates/vim/src/normal/search.rs @@ -155,6 +155,7 @@ fn search_deploy(_: &mut Workspace, _: &buffer_search::Deploy, cx: &mut ViewCont fn search_submit(workspace: &mut Workspace, _: &SearchSubmit, cx: &mut ViewContext) { let mut motion = None; Vim::update(cx, |vim, cx| { + vim.store_visual_marks(cx); let pane = workspace.active_pane().clone(); pane.update(cx, |pane, cx| { if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { diff --git a/crates/vim/src/normal/substitute.rs b/crates/vim/src/normal/substitute.rs index 1d9f9b3066..39576819d6 100644 --- a/crates/vim/src/normal/substitute.rs +++ b/crates/vim/src/normal/substitute.rs @@ -29,6 +29,7 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext } pub fn substitute(vim: &mut Vim, count: Option, line_mode: bool, cx: &mut WindowContext) { + vim.store_visual_marks(cx); vim.update_active_editor(cx, |vim, editor, cx| { editor.set_clip_at_line_ends(false, cx); editor.transact(cx, |editor, cx| { diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 74c17f7bf1..17e4449be4 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -391,6 +391,15 @@ impl Vim { self.stop_recording(); } + // When handling an action, you must create visual marks if you will switch to normal + // mode without the default selection behaviour. + fn store_visual_marks(&mut self, cx: &mut WindowContext) { + let mode = self.state().mode; + if mode.is_visual() { + create_visual_marks(self, mode, cx); + } + } + fn switch_mode(&mut self, mode: Mode, leave_selections: bool, cx: &mut WindowContext) { let state = self.state(); let last_mode = state.mode; @@ -412,14 +421,14 @@ impl Vim { // Sync editor settings like clip mode self.sync_vim_settings(cx); - if !mode.is_visual() && last_mode.is_visual() { - create_visual_marks(self, last_mode, cx); - } - if leave_selections { return; } + if !mode.is_visual() && last_mode.is_visual() { + create_visual_marks(self, last_mode, cx); + } + // Adjust selections self.update_active_editor(cx, |_, editor, cx| { if last_mode != Mode::VisualBlock && last_mode.is_visual() && mode == Mode::VisualBlock diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index 379e2972b4..8d8f848997 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -410,6 +410,7 @@ pub fn other_end(_: &mut Workspace, _: &OtherEnd, cx: &mut ViewContext = Default::default(); let line_mode = line_mode || editor.selections.line_mode; @@ -463,6 +464,7 @@ pub fn delete(vim: &mut Vim, line_mode: bool, cx: &mut WindowContext) { } pub fn yank(vim: &mut Vim, cx: &mut WindowContext) { + vim.store_visual_marks(cx); vim.update_active_editor(cx, |vim, editor, cx| { let line_mode = editor.selections.line_mode; yank_selections_content(vim, editor, line_mode, cx); @@ -1357,5 +1359,15 @@ mod test { "}, Mode::Visual, ); + cx.simulate_keystrokes("y g v"); + cx.assert_state( + indoc! {" + «fishˇ» one + «fishˇ» two + «fishˇ» red + «fishˇ» blue + "}, + Mode::Visual, + ); } }