Fix select in Helix mode (#38117)

Hotfixes issue I have introduced in #37748.

Without this, helix mode select not working at all in `main` branch.

Release Notes:

- N/A
This commit is contained in:
Romans Malinovskis
2025-09-14 10:32:12 +02:00
committed by GitHub
parent e40a950bc4
commit 813a9bb0bc
3 changed files with 77 additions and 4 deletions
+1 -1
View File
@@ -328,7 +328,7 @@
{
"context": "vim_mode == helix_select",
"bindings": {
"escape": "vim::NormalBefore",
"v": "vim::NormalBefore",
";": "vim::HelixCollapseSelection",
"~": "vim::ChangeCase",
"ctrl-a": "vim::Increment",
+74
View File
@@ -53,6 +53,35 @@ impl Vim {
self.helix_move_cursor(motion, times, window, cx);
}
pub fn helix_select_motion(
&mut self,
motion: Motion,
times: Option<usize>,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.update_editor(cx, |_, editor, cx| {
let text_layout_details = editor.text_layout_details(window);
editor.change_selections(Default::default(), window, cx, |s| {
s.move_with(|map, selection| {
let current_head = selection.head();
let Some((new_head, goal)) = motion.move_point(
map,
current_head,
selection.goal,
times,
&text_layout_details,
) else {
return;
};
selection.set_head(new_head, goal);
})
});
});
}
/// Updates all selections based on where the cursors are.
fn helix_new_selections(
&mut self,
@@ -1033,4 +1062,49 @@ mod test {
Mode::HelixNormal,
);
}
#[gpui::test]
async fn test_helix_select_mode_motion(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
assert_eq!(cx.mode(), Mode::Normal);
cx.enable_helix();
cx.set_state("ˇhello", Mode::HelixNormal);
cx.simulate_keystrokes("l v l l");
cx.assert_state("h«ellˇ»o", Mode::HelixSelect);
}
#[gpui::test]
async fn test_helix_select_mode_motion_multiple_cursors(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
assert_eq!(cx.mode(), Mode::Normal);
cx.enable_helix();
// Start with multiple cursors (no selections)
cx.set_state("ˇhello\nˇworld", Mode::HelixNormal);
// Enter select mode and move right twice
cx.simulate_keystrokes("v l l");
// Each cursor should independently create and extend its own selection
cx.assert_state("«helˇ»lo\n«worˇ»ld", Mode::HelixSelect);
}
#[gpui::test]
async fn test_helix_select_word_motions(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("ˇone two", Mode::Normal);
cx.simulate_keystrokes("v w");
cx.assert_state("«one tˇ»wo", Mode::Visual);
// In Vim, this selects "t". In helix selections stops just before "t"
cx.enable_helix();
cx.set_state("ˇone two", Mode::HelixNormal);
cx.simulate_keystrokes("v w");
cx.assert_state("«one ˇ»two", Mode::HelixSelect);
}
}
+2 -3
View File
@@ -726,9 +726,8 @@ impl Vim {
self.visual_motion(motion, count, window, cx)
}
Mode::HelixNormal | Mode::HelixSelect => {
self.helix_normal_motion(motion, count, window, cx)
}
Mode::HelixNormal => self.helix_normal_motion(motion, count, window, cx),
Mode::HelixSelect => self.helix_select_motion(motion, count, window, cx),
}
self.clear_operator(window, cx);
if let Some(operator) = waiting_operator {