vim: Make indenting selected lines with `>` and `<` in Helix mode no longer deselect them (#37665)

Jonathan Hart created

Improves Helix compatibility by making the Indent keybinds `<` and `>`
no longer deselect lines if they're selected.

Post Indent action current Zed release:
<img width="485" height="271" alt="image"
src="https://github.com/user-attachments/assets/41fd3d94-9c89-49dd-adc5-f696dbd79827"
/>
(Cursor is on the beginning of the first line)

Post Indent action in Helix:
<img width="376" height="144" alt="image"
src="https://github.com/user-attachments/assets/fdd1a489-cf3a-4638-9199-3adffa63ef61"
/>

Post Indent action in this PR:
<img width="463" height="300" alt="image"
src="https://github.com/user-attachments/assets/8edd3b81-e446-4b55-bc90-61cac3661ed7"
/>

Release Notes:

- Fixed selected lines indented with `<` and `>` deselecting in Helix
mode

Change summary

crates/vim/src/indent.rs | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)

Detailed changes

crates/vim/src/indent.rs 🔗

@@ -5,6 +5,8 @@ use editor::{Bias, Editor, display_map::ToDisplayPoint};
 use gpui::actions;
 use gpui::{Context, Window};
 use language::SelectionGoal;
+use settings::Settings;
+use vim_mode_setting::HelixModeSetting;
 
 #[derive(PartialEq, Eq)]
 pub(crate) enum IndentDirection {
@@ -37,7 +39,9 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
                 for _ in 0..count {
                     editor.indent(&Default::default(), window, cx);
                 }
-                vim.restore_selection_cursors(editor, window, cx, original_positions);
+                if !HelixModeSetting::get_global(cx).0 {
+                    vim.restore_selection_cursors(editor, window, cx, original_positions);
+                }
             });
         });
         if vim.mode.is_visual() {
@@ -56,7 +60,9 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
                 for _ in 0..count {
                     editor.outdent(&Default::default(), window, cx);
                 }
-                vim.restore_selection_cursors(editor, window, cx, original_positions);
+                if !HelixModeSetting::get_global(cx).0 {
+                    vim.restore_selection_cursors(editor, window, cx, original_positions);
+                }
             });
         });
         if vim.mode.is_visual() {
@@ -183,6 +189,20 @@ mod test {
             .assert_eq("«    hello\n ˇ»   world\n");
     }
 
+    #[gpui::test]
+    async fn test_indent_hx(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+        cx.enable_helix();
+
+        cx.set_state("«Hello\nWorldˇ»\n", Mode::HelixNormal);
+
+        cx.simulate_keystrokes(">");
+        cx.assert_state("    «Hello\n    Worldˇ»\n", Mode::HelixNormal);
+
+        cx.simulate_keystrokes("<");
+        cx.assert_state("«Hello\nWorldˇ»\n", Mode::HelixNormal);
+    }
+
     #[gpui::test]
     async fn test_autoindent_op(cx: &mut gpui::TestAppContext) {
         let mut cx = VimTestContext::new(cx, true).await;