diff --git a/crates/vim/src/object.rs b/crates/vim/src/object.rs index 7b920c252f3b76e58c200bc93bbd742dbef2cdcf..06b40587c4fa06a1edfad9dff5c8b0953446ffdc 100644 --- a/crates/vim/src/object.rs +++ b/crates/vim/src/object.rs @@ -727,8 +727,25 @@ fn around_containing_word( relative_to: DisplayPoint, ignore_punctuation: bool, ) -> Option> { - in_word(map, relative_to, ignore_punctuation) - .map(|range| expand_to_include_whitespace(map, range, true)) + in_word(map, relative_to, ignore_punctuation).map(|range| { + let line_start = DisplayPoint::new(range.start.row(), 0); + let is_first_word = map + .buffer_chars_at(line_start.to_offset(map, Bias::Left)) + .take_while(|(ch, offset)| { + offset < &range.start.to_offset(map, Bias::Left) && ch.is_whitespace() + }) + .count() + > 0; + + if is_first_word { + // For first word on line, trim indentation + let mut expanded = expand_to_include_whitespace(map, range.clone(), true); + expanded.start = range.start; + expanded + } else { + expand_to_include_whitespace(map, range, true) + } + }) } fn around_next_word( @@ -2455,4 +2472,36 @@ mod test { Mode::Visual, ); } + #[gpui::test] + async fn test_around_containing_word_indent(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(" ˇconst f = (x: unknown) => {") + .await; + cx.simulate_shared_keystrokes("v a w").await; + cx.shared_state() + .await + .assert_eq(" «const ˇ»f = (x: unknown) => {"); + + cx.set_shared_state(" ˇconst f = (x: unknown) => {") + .await; + cx.simulate_shared_keystrokes("y a w").await; + cx.shared_clipboard().await.assert_eq("const "); + + cx.set_shared_state(" ˇconst f = (x: unknown) => {") + .await; + cx.simulate_shared_keystrokes("d a w").await; + cx.shared_state() + .await + .assert_eq(" ˇf = (x: unknown) => {"); + cx.shared_clipboard().await.assert_eq("const "); + + cx.set_shared_state(" ˇconst f = (x: unknown) => {") + .await; + cx.simulate_shared_keystrokes("c a w").await; + cx.shared_state() + .await + .assert_eq(" ˇf = (x: unknown) => {"); + cx.shared_clipboard().await.assert_eq("const "); + } } diff --git a/crates/vim/test_data/test_around_containing_word_indent.json b/crates/vim/test_data/test_around_containing_word_indent.json new file mode 100644 index 0000000000000000000000000000000000000000..6707ff6804de91701422ed929ff00eadafd42c34 --- /dev/null +++ b/crates/vim/test_data/test_around_containing_word_indent.json @@ -0,0 +1,23 @@ +{"Put":{"state":" ˇconst f = (x: unknown) => {"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"w"} +{"Get":{"state":" «const ˇ»f = (x: unknown) => {","mode":"Visual"}} +{"Put":{"state":" ˇconst f = (x: unknown) => {"}} +{"Key":"y"} +{"Key":"a"} +{"Key":"w"} +{"Get":{"state":" ˇconst f = (x: unknown) => {","mode":"Normal"}} +{"ReadRegister":{"name":"\"","value":"const "}} +{"Put":{"state":" ˇconst f = (x: unknown) => {"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"w"} +{"Get":{"state":" ˇf = (x: unknown) => {","mode":"Normal"}} +{"ReadRegister":{"name":"\"","value":"const "}} +{"Put":{"state":" ˇconst f = (x: unknown) => {"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"w"} +{"Get":{"state":" ˇf = (x: unknown) => {","mode":"Insert"}} +{"ReadRegister":{"name":"\"","value":"const "}}