vim: Fix `d shift-g` not deleting until EOD if soft-wrap is on (#20160)
Thorsten Ball
created 1 year ago
This previously didn't work: `d G` would delete to the end of the "first
of the soft-wrapped lines" of the last line.
To fix it, we special case the delete behavior for `shift-g`, which is
what Neovim also seems to do.
Release Notes:
- Fixed `d G` in Vim mode not deleting until the actual end of the
document if soft-wrap is turned on.
Change summary
crates/vim/src/normal/delete.rs | 41 ++++---
crates/vim/src/test.rs | 18 +++
crates/vim/test_data/test_wrapped_delete_end_document.json | 10 +
3 files changed, 51 insertions(+), 18 deletions(-)
Detailed changes
@@ -28,25 +28,30 @@ impl Vim {
original_columns.insert(selection.id, original_head.column());
motion.expand_selection(map, selection, times, true, &text_layout_details);
- // Motion::NextWordStart on an empty line should delete it.
- if let Motion::NextWordStart {
- ignore_punctuation: _,
- } = motion
- {
- if selection.is_empty()
- && map
- .buffer_snapshot
- .line_len(MultiBufferRow(selection.start.to_point(map).row))
- == 0
- {
- selection.end = map
- .buffer_snapshot
- .clip_point(
- Point::new(selection.start.to_point(map).row + 1, 0),
- Bias::Left,
- )
- .to_display_point(map)
+ match motion {
+ // Motion::NextWordStart on an empty line should delete it.
+ Motion::NextWordStart { .. } => {
+ if selection.is_empty()
+ && map
+ .buffer_snapshot
+ .line_len(MultiBufferRow(selection.start.to_point(map).row))
+ == 0
+ {
+ selection.end = map
+ .buffer_snapshot
+ .clip_point(
+ Point::new(selection.start.to_point(map).row + 1, 0),
+ Bias::Left,
+ )
+ .to_display_point(map)
+ }
+ }
+ Motion::EndOfDocument {} => {
+ // Deleting until the end of the document includes the last line, including
+ // soft-wrapped lines.
+ selection.end = map.max_point()
}
+ _ => {}
}
});
});
@@ -730,6 +730,24 @@ async fn test_wrapped_motions(cx: &mut gpui::TestAppContext) {
});
}
+#[gpui::test]
+async fn test_wrapped_delete_end_document(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.set_shared_wrap(12).await;
+
+ cx.set_shared_state(indoc! {"
+ aaˇaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbb
+ cccccccccccccccccccc"
+ })
+ .await;
+ cx.simulate_shared_keystrokes("d shift-g i z z z").await;
+ cx.shared_state().await.assert_eq(indoc! {"
+ zzzˇ"
+ });
+}
+
#[gpui::test]
async fn test_paragraphs_dont_wrap(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
@@ -0,0 +1,10 @@
+{"SetOption":{"value":"wrap"}}
+{"SetOption":{"value":"columns=12"}}
+{"Put":{"state":"aaˇaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbbb\ncccccccccccccccccccc"}}
+{"Key":"d"}
+{"Key":"shift-g"}
+{"Key":"i"}
+{"Key":"z"}
+{"Key":"z"}
+{"Key":"z"}
+{"Get":{"state":"zzzˇ","mode":"Insert"}}