vim: Fix change surround adding unwanted spaces with quotes (#42431)

Update `Vim.change_surround` in order to ensure that there's no
overlapping edits by keeping track of where the open string range ends
and ensuring that the closing string range start does not go lower than
the open string range end.

Closes #42316 

Release Notes:

- Fix vim's change surrounds `cs` inserting spaces with quotes by
preventing overlapping edits

---------

Co-authored-by: dino <dinojoaocosta@gmail.com>
This commit is contained in:
Hans
2025-11-12 13:04:24 +00:00
committed by GitHub
co-authored by dino
parent 7be76c74d6
commit e833d1af8d
+25 -6
View File
@@ -282,6 +282,7 @@ impl Vim {
// that the end replacement string does not exceed
// this value. Helpful when dealing with newlines.
let mut edit_len = 0;
let mut open_range_end = 0;
let mut chars_and_offset = display_map
.buffer_chars_at(range.start.to_offset(&display_map, Bias::Left))
.peekable();
@@ -290,11 +291,11 @@ impl Vim {
if ch.to_string() == will_replace_pair.start {
let mut open_str = pair.start.clone();
let start = offset;
let mut end = start + 1;
open_range_end = start + 1;
while let Some((next_ch, _)) = chars_and_offset.next()
&& next_ch.to_string() == " "
&& next_ch == ' '
{
end += 1;
open_range_end += 1;
if preserve_space {
open_str.push(next_ch);
@@ -305,8 +306,8 @@ impl Vim {
open_str.push(' ');
};
edit_len = end - start;
edits.push((start..end, open_str));
edit_len = open_range_end - start;
edits.push((start..open_range_end, open_str));
anchors.push(start..start);
break;
}
@@ -323,8 +324,9 @@ impl Vim {
let mut start = offset;
let end = start + 1;
while let Some((next_ch, _)) = reverse_chars_and_offsets.next()
&& next_ch.to_string() == " "
&& next_ch == ' '
&& close_str.len() < edit_len - 1
&& start > open_range_end
{
start -= 1;
@@ -1236,6 +1238,23 @@ mod test {
Mode::Normal,
);
// test spaces with quote change surrounds
cx.set_state(
indoc! {"
fn test_surround() {
\"ˇ \"
};"},
Mode::Normal,
);
cx.simulate_keystrokes("c s \" '");
cx.assert_state(
indoc! {"
fn test_surround() {
ˇ' '
};"},
Mode::Normal,
);
// Currently, the same test case but using the closing bracket `]`
// actually removes a whitespace before the closing bracket, something
// that might need to be fixed?