@@ -212,7 +212,19 @@ impl Vim {
}
}
- Mode::HelixNormal => {}
+ Mode::HelixNormal => {
+ if selection.is_empty() {
+ // Handle empty selection by operating on the whole word
+ let (word_range, _) = snapshot.surrounding_word(selection.start, false);
+ let word_start = snapshot.offset_to_point(word_range.start);
+ let word_end = snapshot.offset_to_point(word_range.end);
+ ranges.push(word_start..word_end);
+ cursor_positions.push(selection.start..selection.start);
+ } else {
+ ranges.push(selection.start..selection.end);
+ cursor_positions.push(selection.start..selection.end);
+ }
+ }
Mode::Insert | Mode::Normal | Mode::Replace => {
let start = selection.start;
let mut end = start;
@@ -245,12 +257,16 @@ impl Vim {
})
});
});
- self.switch_mode(Mode::Normal, true, window, cx)
+ if self.mode != Mode::HelixNormal {
+ self.switch_mode(Mode::Normal, true, window, cx)
+ }
}
}
#[cfg(test)]
mod test {
+ use crate::test::VimTestContext;
+
use crate::{state::Mode, test::NeovimBackedTestContext};
#[gpui::test]
@@ -419,4 +435,25 @@ mod test {
.await
.assert_eq("ˇnopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM");
}
+
+ #[gpui::test]
+ async fn test_change_case_helix_mode(cx: &mut gpui::TestAppContext) {
+ let mut cx = VimTestContext::new(cx, true).await;
+
+ // Explicit selection
+ cx.set_state("«hello worldˇ»", Mode::HelixNormal);
+ cx.simulate_keystrokes("~");
+ cx.assert_state("«HELLO WORLDˇ»", Mode::HelixNormal);
+
+ // Cursor-only (empty) selection
+ cx.set_state("The ˇquick brown", Mode::HelixNormal);
+ cx.simulate_keystrokes("~");
+ cx.assert_state("The ˇQUICK brown", Mode::HelixNormal);
+
+ // With `e` motion (which extends selection to end of word in Helix)
+ cx.set_state("The ˇquick brown fox", Mode::HelixNormal);
+ cx.simulate_keystrokes("e");
+ cx.simulate_keystrokes("~");
+ cx.assert_state("The «QUICKˇ» brown fox", Mode::HelixNormal);
+ }
}