Fix panic in vim increment (#50311) (cherry-pick to stable) (#50338)
zed-zippy[bot]
and
Conrad Irwin
created
Cherry-pick of #50311 to stable
----
Fixes ZED-59V
Release Notes:
- vim: Fixed panic when incrementing a number preceded by a multibyte
character
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
@@ -203,20 +203,25 @@ fn find_target(
let start_offset = start.to_offset(snapshot);
let end_offset = end.to_offset(snapshot);
- let mut offset = start_offset;
let mut first_char_is_num = snapshot
- .chars_at(offset)
+ .chars_at(start_offset)
.next()
.map_or(false, |ch| ch.is_ascii_hexdigit());
let mut pre_char = String::new();
- let next_offset = offset
+ let next_offset = start_offset
+ snapshot
.chars_at(start_offset)
.next()
.map_or(0, |ch| ch.len_utf8());
- // Backward scan to find the start of the number, but stop at start_offset
+ // Backward scan to find the start of the number, but stop at start_offset.
+ // We track `offset` as the start position of the current character. Initialize
+ // to `next_offset` and decrement at the start of each iteration so that `offset`
+ // always lands on a valid character boundary (not in the middle of a multibyte char).
+ let mut offset = next_offset;
for ch in snapshot.reversed_chars_at(next_offset) {
+ offset -= ch.len_utf8();
+
// Search boundaries
if offset.0 == 0 || ch.is_whitespace() || (need_range && offset <= start_offset) {
break;
@@ -238,7 +243,6 @@ fn find_target(
}
pre_char.insert(0, ch);
- offset -= ch.len_utf8();
}
// The backward scan breaks on whitespace, including newlines. Without this
@@ -895,4 +899,15 @@ mod test {
.await
.assert_eq("# Title\n2. item\nĖ2. item\n3. item");
}
+
+ #[gpui::test]
+ async fn test_increment_with_multibyte_characters(cx: &mut gpui::TestAppContext) {
+ let mut cx = VimTestContext::new(cx, true).await;
+
+ // Test cursor after a multibyte character - this would panic before the fix
+ // because the backward scan would land in the middle of the Korean character
+ cx.set_state("ģ§Ė1", Mode::Normal);
+ cx.simulate_keystrokes("ctrl-a");
+ cx.assert_state("ģ§Ė2", Mode::Normal);
+ }
}