From 15d59fcda9aa8f03e178b0045bf64c2aca8e4011 Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Wed, 28 May 2025 06:30:51 +0530 Subject: [PATCH] =?UTF-8?q?vim:=20Fix=20crash=20when=20using=20=E2=80=98ge?= =?UTF-8?q?=E2=80=99=20motion=20on=20multibyte=20character=20(#31566)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #30919 - [x] Test Release Notes: - Fixed the issue where using the Vim motion `ge` on multibyte character would cause Zed to crash. --- crates/vim/src/motion.rs | 18 ++++++++++++++++-- .../vim/test_data/test_previous_word_end.json | 4 ++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index b207307f2d..080f051db5 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -1701,7 +1701,9 @@ fn previous_word_end( let mut point = point.to_point(map); if point.column < map.buffer_snapshot.line_len(MultiBufferRow(point.row)) { - point.column += 1; + if let Some(ch) = map.buffer_snapshot.chars_at(point).next() { + point.column += ch.len_utf8() as u32; + } } for _ in 0..times { let new_point = movement::find_preceding_boundary_point( @@ -1874,7 +1876,9 @@ fn previous_subword_end( let mut point = point.to_point(map); if point.column < map.buffer_snapshot.line_len(MultiBufferRow(point.row)) { - point.column += 1; + if let Some(ch) = map.buffer_snapshot.chars_at(point).next() { + point.column += ch.len_utf8() as u32; + } } for _ in 0..times { let new_point = movement::find_preceding_boundary_point( @@ -3613,6 +3617,16 @@ mod test { 4;5.6 567 678 789 890 901 "}); + + // With multi byte char + cx.set_shared_state(indoc! {r" + bar ˇó + "}) + .await; + cx.simulate_shared_keystrokes("g e").await; + cx.shared_state().await.assert_eq(indoc! {" + baˇr ó + "}); } #[gpui::test] diff --git a/crates/vim/test_data/test_previous_word_end.json b/crates/vim/test_data/test_previous_word_end.json index 11e7552ce9..f1e3540240 100644 --- a/crates/vim/test_data/test_previous_word_end.json +++ b/crates/vim/test_data/test_previous_word_end.json @@ -27,3 +27,7 @@ {"Key":"g"} {"Key":"shift-e"} {"Get":{"state":"123 234 34ˇ5\n4;5.6 567 678\n789 890 901\n","mode":"Normal"}} +{"Put":{"state":"bar ˇó\n"}} +{"Key":"g"} +{"Key":"e"} +{"Get":{"state":"baˇr ó\n","mode":"Normal"}}