vim: Fix gv after actions (#14829)

Fixes: #13720

Co-Authored-By: <tobbe@tlundberg.com>



Release Notes:

- vim: Fixed `gv` after `y`, `d`, etc.
([#13760](https://github.com/zed-industries/zed/issues/13760)).
This commit is contained in:
Conrad Irwin 2024-07-19 13:26:55 -06:00 committed by GitHub
parent 5e635b8914
commit d2efa12e16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 32 additions and 4 deletions

View File

@ -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();

View File

@ -44,6 +44,7 @@ pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
}
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();

View File

@ -30,7 +30,9 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>
fn paste(_: &mut Workspace, action: &Paste, cx: &mut ViewContext<Workspace>) {
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| {

View File

@ -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<Workspace>) {
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::<BufferSearchBar>() {

View File

@ -29,6 +29,7 @@ pub(crate) fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>
}
pub fn substitute(vim: &mut Vim, count: Option<usize>, 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| {

View File

@ -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

View File

@ -410,6 +410,7 @@ pub fn other_end(_: &mut Workspace, _: &OtherEnd, cx: &mut ViewContext<Workspace
}
pub fn delete(vim: &mut Vim, line_mode: bool, cx: &mut WindowContext) {
vim.store_visual_marks(cx);
vim.update_active_editor(cx, |vim, editor, cx| {
let mut original_columns: HashMap<_, _> = 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,
);
}
}