From 4fad96b1796ce39d1d24880fa340c3d4852c580a Mon Sep 17 00:00:00 2001 From: Hans Date: Tue, 30 Apr 2024 09:38:14 +0800 Subject: [PATCH] Add yss operation support for vim surrounds: (#11084) The Motion::CurrentLine operation will contain the newline of the current line, so we need to deal with this edge case Release Notes: - N/A --- assets/keymaps/vim.json | 6 +++++ crates/vim/src/surrounds.rs | 52 +++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 1f9fbda076..f73f23426a 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -435,6 +435,12 @@ ] } }, + { + "context": "Editor && vim_operator == ys", + "bindings": { + "s": "vim::CurrentLine" + } + }, { "context": "Editor && VimObject", "bindings": { diff --git a/crates/vim/src/surrounds.rs b/crates/vim/src/surrounds.rs index 4ff911e706..f86e2dc21f 100644 --- a/crates/vim/src/surrounds.rs +++ b/crates/vim/src/surrounds.rs @@ -1,5 +1,5 @@ use crate::{motion::Motion, object::Object, state::Mode, Vim}; -use editor::{scroll::Autoscroll, Bias}; +use editor::{movement, scroll::Autoscroll, Bias}; use gpui::WindowContext; use language::BracketPair; use serde::Deserialize; @@ -47,13 +47,32 @@ pub fn add_surrounds(text: Arc, target: SurroundsType, cx: &mut WindowConte SurroundsType::Object(object) => { object.range(&display_map, selection.clone(), false) } - SurroundsType::Motion(motion) => motion.range( - &display_map, - selection.clone(), - Some(1), - true, - &text_layout_details, - ), + SurroundsType::Motion(motion) => { + let range = motion + .range( + &display_map, + selection.clone(), + Some(1), + true, + &text_layout_details, + ) + .map(|mut range| { + // The Motion::CurrentLine operation will contain the newline of the current line, + // so we need to deal with this edge case + if let Motion::CurrentLine = motion { + let offset = range.end.to_offset(&display_map, Bias::Left); + if let Some((last_ch, _)) = + display_map.reverse_buffer_chars_at(offset).next() + { + if last_ch == '\n' { + range.end = movement::left(&display_map, range.end); + } + } + } + range + }); + range + } }; if let Some(range) = range { @@ -591,6 +610,23 @@ mod test { the laˇ1zy dog.1"}, Mode::Normal, ); + + // test add surrounds with motion current line + cx.set_state( + indoc! {" + The quˇick brown + fox jumps over + the lazy dog."}, + Mode::Normal, + ); + cx.simulate_keystrokes(["y", "s", "s", "{"]); + cx.assert_state( + indoc! {" + ˇ{ The quick brown } + fox jumps over + the lazy dog."}, + Mode::Normal, + ); } #[gpui::test]