vim: Ensure vgl does not select newline in helix mode (#54238)

Release Notes:

- Fixed Helix vgl now correctly selects to end of line without
including the newline character in the selection.

---------

Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
This commit is contained in:
Cavebat Software 2026-04-22 09:08:32 -04:00 committed by GitHub
parent 565f4d07fb
commit 8d1fc1a5db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -157,6 +157,23 @@ impl Vim {
}
let (new_head, goal) = match motion {
// EndOfLine positions after the last character, but in
// helix visual mode we want the selection to end ON the
// last character. Adjust left here so the subsequent
// right-expansion (below) includes the last char without
// spilling into the newline.
Motion::EndOfLine { .. } => {
let (point, goal) = motion
.move_point(
map,
current_head,
selection.goal,
times,
&text_layout_details,
)
.unwrap_or((current_head, selection.goal));
(movement::saturating_left(map, point), goal)
}
// Going to next word start is special cased
// since Vim differs from Helix in that motion
// Vim: `w` goes to the first character of a word
@ -1991,6 +2008,23 @@ mod test {
cx.assert_state("h«ellˇ»o", Mode::HelixSelect);
}
#[gpui::test]
async fn test_helix_select_end_of_line(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.enable_helix();
// v g l d should delete to end of line without consuming the newline
cx.set_state("ˇThe quick brown\nfox jumps over", Mode::HelixNormal);
cx.simulate_keystrokes("v g l d");
cx.assert_state("ˇ\nfox jumps over", Mode::HelixNormal);
// same from the middle of a line — cursor lands on the last
// remaining character (the space) after delete
cx.set_state("The ˇquick brown\nfox jumps over", Mode::HelixNormal);
cx.simulate_keystrokes("v g l d");
cx.assert_state("Theˇ \nfox jumps over", Mode::HelixNormal);
}
#[gpui::test]
async fn test_helix_select_mode_motion_multiple_cursors(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;