From 7bddb390cabefb177d9996dc580749d64e6ca3b6 Mon Sep 17 00:00:00 2001 From: 5brian Date: Fri, 7 Feb 2025 21:50:34 -0500 Subject: [PATCH] vim: Preserve trailing whitespace in inner text object selections (#24481) Closes #24438 Changes: Adjusted loop to only trim whitespace between last newline and closing marker, when using inner objects like `y/d/c i b` | Start | Fixed `vib` | Previous `vib` | | ---------- | ---------- | ---------- | | ![image](https://github.com/user-attachments/assets/3d64dd7d-ed3d-4a85-9f98-f2f83799a738) | ![image](https://github.com/user-attachments/assets/841beb59-31b1-475e-93f0-f4deaf18939c) | ![image](https://github.com/user-attachments/assets/736d4c6f-20e1-4563-9471-1e8195455df4) | Release Notes: - vim: Preserve trailing whitespace in inner text object selections --------- Co-authored-by: Conrad Irwin --- crates/vim/src/object.rs | 24 +++++++++++++++++-- .../test_anybrackets_trailing_space.json | 11 +++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 crates/vim/test_data/test_anybrackets_trailing_space.json diff --git a/crates/vim/src/object.rs b/crates/vim/src/object.rs index 285f79095a904e86cc361bc561e20a22f0b37a5f..eb2999cb7266065c7b6be5dbca30ddc5a4ffd948 100644 --- a/crates/vim/src/object.rs +++ b/crates/vim/src/object.rs @@ -1339,14 +1339,20 @@ fn surrounding_markers( } } + let mut last_newline_end = None; for (ch, range) in movement::chars_before(map, closing.start) { if !ch.is_whitespace() { break; } - if ch != '\n' { - closing.start = range.start + if ch == '\n' { + last_newline_end = Some(range.end); + break; } } + // Adjust closing.start to exclude whitespace after a newline, if present + if let Some(end) = last_newline_end { + closing.start = end; + } } let result = if around { @@ -2254,6 +2260,20 @@ mod test { } } + #[gpui::test] + async fn test_anybrackets_trailing_space(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state("(trailingˇ whitespace )") + .await; + cx.simulate_shared_keystrokes("v i b").await; + cx.shared_state().await.assert_matches(); + cx.simulate_shared_keystrokes("escape y i b").await; + cx.shared_clipboard() + .await + .assert_eq("trailing whitespace "); + } + #[gpui::test] async fn test_tags(cx: &mut gpui::TestAppContext) { let mut cx = VimTestContext::new_html(cx).await; diff --git a/crates/vim/test_data/test_anybrackets_trailing_space.json b/crates/vim/test_data/test_anybrackets_trailing_space.json new file mode 100644 index 0000000000000000000000000000000000000000..ed3f47df6c8c7c9f9249a52bcad9f008f79076d2 --- /dev/null +++ b/crates/vim/test_data/test_anybrackets_trailing_space.json @@ -0,0 +1,11 @@ +{"Put":{"state":"(trailingˇ whitespace )"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"b"} +{"Get":{"state":"(«trailing whitespace ˇ»)","mode":"Visual"}} +{"Key":"escape"} +{"Key":"y"} +{"Key":"i"} +{"Key":"b"} +{"Get":{"state":"(ˇtrailing whitespace )","mode":"Normal"}} +{"ReadRegister":{"name":"\"","value":"trailing whitespace "}}