From 768b2de368697a559a038f65e61aff81dc99f041 Mon Sep 17 00:00:00 2001 From: Lucas Vieira Date: Mon, 18 Aug 2025 12:57:53 -0300 Subject: [PATCH] vim: Fix `ap` text object selection when there is line wrapping (#35485) In Vim mode, `ap` text object (used in `vap`, `dap`, `cap`) was selecting multiple paragraphs when soft wrap was enabled. The bug was caused by using DisplayRow coordinates for arithmetic instead of buffer row coordinates in the paragraph boundary calculation. Fix by converting to buffer coordinates before arithmetic, then back to display coordinates for the final result. Closes #35085 --------- Co-authored-by: Conrad Irwin --- crates/vim/src/normal/delete.rs | 22 +++++ crates/vim/src/object.rs | 93 ++++++++++++++++++- crates/vim/src/visual.rs | 33 +++++++ ...hange_paragraph_object_with_soft_wrap.json | 72 ++++++++++++++ ...elete_paragraph_object_with_soft_wrap.json | 72 ++++++++++++++ .../test_delete_paragraph_whitespace.json | 5 + ...isual_paragraph_object_with_soft_wrap.json | 72 ++++++++++++++ 7 files changed, 365 insertions(+), 4 deletions(-) create mode 100644 crates/vim/test_data/test_change_paragraph_object_with_soft_wrap.json create mode 100644 crates/vim/test_data/test_delete_paragraph_object_with_soft_wrap.json create mode 100644 crates/vim/test_data/test_delete_paragraph_whitespace.json create mode 100644 crates/vim/test_data/test_visual_paragraph_object_with_soft_wrap.json diff --git a/crates/vim/src/normal/delete.rs b/crates/vim/src/normal/delete.rs index 1b7557371a..d7a6932baa 100644 --- a/crates/vim/src/normal/delete.rs +++ b/crates/vim/src/normal/delete.rs @@ -2,6 +2,7 @@ use crate::{ Vim, motion::{Motion, MotionKind}, object::Object, + state::Mode, }; use collections::{HashMap, HashSet}; use editor::{ @@ -102,8 +103,20 @@ impl Vim { // Emulates behavior in vim where if we expanded backwards to include a newline // the cursor gets set back to the start of the line let mut should_move_to_start: HashSet<_> = Default::default(); + + // Emulates behavior in vim where after deletion the cursor should try to move + // to the same column it was before deletion if the line is not empty or only + // contains whitespace + let mut column_before_move: HashMap<_, _> = Default::default(); + let target_mode = object.target_visual_mode(vim.mode, around); + editor.change_selections(Default::default(), window, cx, |s| { s.move_with(|map, selection| { + let cursor_point = selection.head().to_point(map); + if target_mode == Mode::VisualLine { + column_before_move.insert(selection.id, cursor_point.column); + } + object.expand_selection(map, selection, around, times); let offset_range = selection.map(|p| p.to_offset(map, Bias::Left)).range(); let mut move_selection_start_to_previous_line = @@ -164,6 +177,15 @@ impl Vim { let mut cursor = selection.head(); if should_move_to_start.contains(&selection.id) { *cursor.column_mut() = 0; + } else if let Some(column) = column_before_move.get(&selection.id) + && *column > 0 + { + let mut cursor_point = cursor.to_point(map); + cursor_point.column = *column; + cursor = map + .buffer_snapshot + .clip_point(cursor_point, Bias::Left) + .to_display_point(map); } cursor = map.clip_point(cursor, Bias::Left); selection.collapse_to(cursor, selection.goal) diff --git a/crates/vim/src/object.rs b/crates/vim/src/object.rs index 63139d7e94..cff23c4bd4 100644 --- a/crates/vim/src/object.rs +++ b/crates/vim/src/object.rs @@ -1444,14 +1444,15 @@ fn paragraph( return None; } - let paragraph_start_row = paragraph_start.row(); - if paragraph_start_row.0 != 0 { + let paragraph_start_buffer_point = paragraph_start.to_point(map); + if paragraph_start_buffer_point.row != 0 { let previous_paragraph_last_line_start = - Point::new(paragraph_start_row.0 - 1, 0).to_display_point(map); + Point::new(paragraph_start_buffer_point.row - 1, 0).to_display_point(map); paragraph_start = start_of_paragraph(map, previous_paragraph_last_line_start); } } else { - let mut start_row = paragraph_end_row.0 + 1; + let paragraph_end_buffer_point = paragraph_end.to_point(map); + let mut start_row = paragraph_end_buffer_point.row + 1; if i > 0 { start_row += 1; } @@ -1903,6 +1904,90 @@ mod test { } } + #[gpui::test] + async fn test_change_paragraph_object_with_soft_wrap(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + const WRAPPING_EXAMPLE: &str = indoc! {" + ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines. + + ˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly. + + ˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.ˇ + "}; + + cx.set_shared_wrap(20).await; + + cx.simulate_at_each_offset("c i p", WRAPPING_EXAMPLE) + .await + .assert_matches(); + cx.simulate_at_each_offset("c a p", WRAPPING_EXAMPLE) + .await + .assert_matches(); + } + + #[gpui::test] + async fn test_delete_paragraph_object_with_soft_wrap(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + const WRAPPING_EXAMPLE: &str = indoc! {" + ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines. + + ˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly. + + ˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.ˇ + "}; + + cx.set_shared_wrap(20).await; + + cx.simulate_at_each_offset("d i p", WRAPPING_EXAMPLE) + .await + .assert_matches(); + cx.simulate_at_each_offset("d a p", WRAPPING_EXAMPLE) + .await + .assert_matches(); + } + + #[gpui::test] + async fn test_delete_paragraph_whitespace(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {" + a + ˇ• + aaaaaaaaaaaaa + "}) + .await; + + cx.simulate_shared_keystrokes("d i p").await; + cx.shared_state().await.assert_eq(indoc! {" + a + aaaaaaaˇaaaaaa + "}); + } + + #[gpui::test] + async fn test_visual_paragraph_object_with_soft_wrap(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + const WRAPPING_EXAMPLE: &str = indoc! {" + ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines. + + ˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly. + + ˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.ˇ + "}; + + cx.set_shared_wrap(20).await; + + cx.simulate_at_each_offset("v i p", WRAPPING_EXAMPLE) + .await + .assert_matches(); + cx.simulate_at_each_offset("v a p", WRAPPING_EXAMPLE) + .await + .assert_matches(); + } + // Test string with "`" for opening surrounders and "'" for closing surrounders const SURROUNDING_MARKER_STRING: &str = indoc! {" ˇTh'ˇe ˇ`ˇ'ˇquˇi`ˇck broˇ'wn` diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index 7bfd8dc8be..3b789b1f3e 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -414,6 +414,8 @@ impl Vim { ); } + let original_point = selection.tail().to_point(&map); + if let Some(range) = object.range(map, mut_selection, around, count) { if !range.is_empty() { let expand_both_ways = object.always_expands_both_ways() @@ -462,6 +464,37 @@ impl Vim { }; selection.end = new_selection_end.to_display_point(map); } + + // To match vim, if the range starts of the same line as it originally + // did, we keep the tail of the selection in the same place instead of + // snapping it to the start of the line + if target_mode == Mode::VisualLine { + let new_start_point = selection.start.to_point(map); + if new_start_point.row == original_point.row { + if selection.end.to_point(map).row > new_start_point.row { + if original_point.column + == map + .buffer_snapshot + .line_len(MultiBufferRow(original_point.row)) + { + selection.start = movement::saturating_left( + map, + original_point.to_display_point(map), + ) + } else { + selection.start = original_point.to_display_point(map) + } + } else { + selection.end = movement::saturating_right( + map, + original_point.to_display_point(map), + ); + if original_point.column > 0 { + selection.reversed = true + } + } + } + } } }); }); diff --git a/crates/vim/test_data/test_change_paragraph_object_with_soft_wrap.json b/crates/vim/test_data/test_change_paragraph_object_with_soft_wrap.json new file mode 100644 index 0000000000..47d68e13a6 --- /dev/null +++ b/crates/vim/test_data/test_change_paragraph_object_with_soft_wrap.json @@ -0,0 +1,72 @@ +{"SetOption":{"value":"wrap"}} +{"SetOption":{"value":"columns=20"}} +{"Put":{"state":"ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"ˇ\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"ˇ\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.ˇ\n"}} +{"Key":"c"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ\n","mode":"Insert"}} +{"Put":{"state":"ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"ˇ\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"ˇ\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ","mode":"Insert"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.ˇ\n"}} +{"Key":"c"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ","mode":"Insert"}} diff --git a/crates/vim/test_data/test_delete_paragraph_object_with_soft_wrap.json b/crates/vim/test_data/test_delete_paragraph_object_with_soft_wrap.json new file mode 100644 index 0000000000..19dcd175b3 --- /dev/null +++ b/crates/vim/test_data/test_delete_paragraph_object_with_soft_wrap.json @@ -0,0 +1,72 @@ +{"SetOption":{"value":"wrap"}} +{"SetOption":{"value":"columns=20"}} +{"Put":{"state":"ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"ˇ\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"ˇ\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.ˇ\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ","mode":"Normal"}} +{"Put":{"state":"ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"ˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"Second paragraph that is also quite long and will definitely wrap under soft wrap conditions andˇ should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nThird paragraph with additional long text content that will also wrap when line length is constraˇined by the wrapping settings.\n","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\nˇ","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\nˇ","mode":"Normal"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.ˇ\n"}} +{"Key":"d"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\nˇ","mode":"Normal"}} diff --git a/crates/vim/test_data/test_delete_paragraph_whitespace.json b/crates/vim/test_data/test_delete_paragraph_whitespace.json new file mode 100644 index 0000000000..e07b18eaa3 --- /dev/null +++ b/crates/vim/test_data/test_delete_paragraph_whitespace.json @@ -0,0 +1,5 @@ +{"Put":{"state":"a\n ˇ•\naaaaaaaaaaaaa\n"}} +{"Key":"d"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"a\naaaaaaaˇaaaaaa\n","mode":"Normal"}} diff --git a/crates/vim/test_data/test_visual_paragraph_object_with_soft_wrap.json b/crates/vim/test_data/test_visual_paragraph_object_with_soft_wrap.json new file mode 100644 index 0000000000..6bfce2f955 --- /dev/null +++ b/crates/vim/test_data/test_visual_paragraph_object_with_soft_wrap.json @@ -0,0 +1,72 @@ +{"SetOption":{"value":"wrap"}} +{"SetOption":{"value":"columns=20"}} +{"Put":{"state":"ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"«Fˇ»irst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"«ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is l»imited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\n«Sˇ»econd paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\n«ˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and s»hould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\n«Tˇ»hird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\n«ˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping s»ettings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.ˇ\n"}} +{"Key":"v"} +{"Key":"i"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\n«ˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.»\n","mode":"VisualLine"}} +{"Put":{"state":"ˇFirst paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"«First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇ»Second paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is ˇlimited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is «limited making it span multiple display lines.\n\nˇ»Second paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nˇSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\n«Second paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇ»Third paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and ˇshould be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and «should be handled correctly.\n\nˇ»Third paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nˇThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\n«Third paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.\nˇ»","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping ˇsettings.\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping «settings.\nˇ»","mode":"VisualLine"}} +{"Put":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings.ˇ\n"}} +{"Key":"v"} +{"Key":"a"} +{"Key":"p"} +{"Get":{"state":"First paragraph with very long text that will wrap when soft wrap is enabled and line length is limited making it span multiple display lines.\n\nSecond paragraph that is also quite long and will definitely wrap under soft wrap conditions and should be handled correctly.\n\nThird paragraph with additional long text content that will also wrap when line length is constrained by the wrapping settings«.\nˇ»","mode":"VisualLine"}}