diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index d9613bc865..20eb58e1e0 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -4,7 +4,7 @@ use editor::{ movement, Bias, CharKind, DisplayPoint, }; use gpui::{actions, impl_actions, MutableAppContext}; -use language::{Selection, SelectionGoal}; +use language::{Point, Selection, SelectionGoal}; use serde::Deserialize; use workspace::Workspace; @@ -189,7 +189,7 @@ impl Motion { EndOfLine => (end_of_line(map, point), SelectionGoal::None), CurrentLine => (end_of_line(map, point), SelectionGoal::None), StartOfDocument => (start_of_document(map, point, times), SelectionGoal::None), - EndOfDocument => (end_of_document(map, point), SelectionGoal::None), + EndOfDocument => (end_of_document(map, point, times), SelectionGoal::None), Matching => (matching(map, point), SelectionGoal::None), } } @@ -409,13 +409,17 @@ fn end_of_line(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint { } fn start_of_document(map: &DisplaySnapshot, point: DisplayPoint, line: usize) -> DisplayPoint { - let mut new_point = (line - 1).to_display_point(map); + let mut new_point = Point::new((line - 1) as u32, 0).to_display_point(map); *new_point.column_mut() = point.column(); map.clip_point(new_point, Bias::Left) } -fn end_of_document(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint { - let mut new_point = map.max_point(); +fn end_of_document(map: &DisplaySnapshot, point: DisplayPoint, line: usize) -> DisplayPoint { + let mut new_point = if line == 1 { + map.max_point() + } else { + Point::new((line - 1) as u32, 0).to_display_point(map) + }; *new_point.column_mut() = point.column(); map.clip_point(new_point, Bias::Left) } diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 4b786c4a5f..4720ed7373 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -566,10 +566,42 @@ mod test { .await; cx.assert_binding_matches( ["2", "g", "g"], + indoc! {" + ˇ + + brown fox jumps + over the lazydog"}, + ) + .await; + } + + #[gpui::test] + async fn test_end_of_document(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.assert_binding_matches_all( + ["shift-g"], + indoc! {" + The qˇuick + + brown fox jumps + over ˇthe laˇzy dog"}, + ) + .await; + cx.assert_binding_matches( + ["shift-g"], indoc! {" - brown fox juˇmps + brown fox jumps + over the laˇzy dog"}, + ) + .await; + cx.assert_binding_matches( + ["2", "shift-g"], + indoc! {" + ˇ + + brown fox jumps over the lazydog"}, ) .await; diff --git a/crates/vim/test_data/test_G.json b/crates/vim/test_data/test_G.json new file mode 100644 index 0000000000..de9e29e4aa --- /dev/null +++ b/crates/vim/test_data/test_G.json @@ -0,0 +1 @@ +[{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,5],"end":[3,5]}}] \ No newline at end of file diff --git a/crates/vim/test_data/test_end_of_document.json b/crates/vim/test_data/test_end_of_document.json new file mode 100644 index 0000000000..2570db66da --- /dev/null +++ b/crates/vim/test_data/test_end_of_document.json @@ -0,0 +1 @@ +[{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,5],"end":[3,5]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,5],"end":[3,5]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,11],"end":[3,11]}},{"Mode":"Normal"},{"Text":"\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,11],"end":[3,11]}},{"Mode":"Normal"},{"Text":"\n\nbrown fox jumps\nover the lazydog"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}] \ No newline at end of file