vim: Fix Helix jump on selected lines (#57565)
Resolves https://github.com/zed-industries/zed/issues/57486 This diff fixes `g w` after selecting lines with `x` in Helix mode. `x` leaves Zed in Helix normal mode with a non-empty selection, but jump target collection treated non-visual selections as ranges to skip. As a result, words on the selected line did not receive jump labels. With this change, Helix normal mode keeps existing selection ranges eligible for jump targets, matching Helix's behavior where normal mode can still carry selections. The regression covers `x` followed by `g w` targeting a word inside the selected line. Release Notes: - Fixed `g w` not targeting words on lines selected with `x` in Helix mode. --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
1 parent
35ba059398
commit
3e57e2b546
3 files changed
+30
-8
No files matched your search
+24
-7
@@ -1004,8 +1004,9 @@ impl Vim {
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let is_visual = self.mode.is_visual();
|
||||
let Some(data) = self.collect_helix_jump_data(is_visual, window, cx) else {
|
||||
let allow_targets_in_selection = self.mode.has_selection();
|
||||
let Some(data) = self.collect_helix_jump_data(allow_targets_in_selection, window, cx)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -1031,7 +1032,7 @@ impl Vim {
|
||||
|
||||
fn collect_helix_jump_data(
|
||||
&mut self,
|
||||
is_visual: bool,
|
||||
allow_targets_in_selection: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<HelixJumpUiData> {
|
||||
@@ -1044,7 +1045,11 @@ impl Vim {
|
||||
let end_offset = buffer_snapshot.point_to_offset(visible_range.end);
|
||||
|
||||
let selections = editor.selections.all::<Point>(&display_snapshot);
|
||||
let skip_data = Self::selection_skip_offsets(buffer_snapshot, &selections, is_visual);
|
||||
let skip_data = Self::selection_skip_offsets(
|
||||
buffer_snapshot,
|
||||
&selections,
|
||||
allow_targets_in_selection,
|
||||
);
|
||||
|
||||
// Get the primary cursor position for alternating forward/backward labeling
|
||||
let cursor_offset = selections
|
||||
@@ -1254,7 +1259,7 @@ impl Vim {
|
||||
fn selection_skip_offsets(
|
||||
buffer: &MultiBufferSnapshot,
|
||||
selections: &[Selection<Point>],
|
||||
is_visual: bool,
|
||||
allow_targets_in_selection: bool,
|
||||
) -> HelixJumpSkipData {
|
||||
let mut skip_points = Vec::with_capacity(selections.len());
|
||||
let mut skip_ranges = Vec::new();
|
||||
@@ -1263,8 +1268,7 @@ impl Vim {
|
||||
let head_offset = buffer.point_to_offset(selection.head());
|
||||
skip_points.push(head_offset);
|
||||
|
||||
// In visual mode, don't skip ranges so we can shrink the selection
|
||||
if !is_visual && selection.start != selection.end {
|
||||
if !allow_targets_in_selection && selection.start != selection.end {
|
||||
let mut start = buffer.point_to_offset(selection.start);
|
||||
let mut end = buffer.point_to_offset(selection.end);
|
||||
if start > end {
|
||||
@@ -3489,6 +3493,19 @@ mod test {
|
||||
assert_eq!(cx.active_operator(), None);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_helix_jump_includes_line_selection_targets(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
cx.enable_helix();
|
||||
cx.set_state("alpha beta\nˇfoo bar baz\nqux quux", Mode::HelixNormal);
|
||||
|
||||
cx.simulate_keystrokes("x");
|
||||
jump_to_word(&mut cx, "bar");
|
||||
|
||||
cx.assert_state("alpha beta\nfoo «barˇ» baz\nqux quux", Mode::HelixNormal);
|
||||
assert_eq!(cx.active_operator(), None);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_vim_jump_moves_to_target_word_start(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
@@ -80,6 +80,11 @@ impl Mode {
|
||||
matches!(self, Self::HelixNormal | Self::HelixSelect)
|
||||
}
|
||||
|
||||
/// `HelixNormal` qualifies because its cursor is itself a one-character selection.
|
||||
pub fn has_selection(&self) -> bool {
|
||||
self.is_visual() || matches!(self, Self::HelixNormal)
|
||||
}
|
||||
|
||||
pub fn is_normal(&self) -> bool {
|
||||
matches!(self, Self::Normal | Self::HelixNormal)
|
||||
}
|
||||
|
||||
@@ -2233,7 +2233,7 @@ impl Vim {
|
||||
input_enabled: self.editor_input_enabled(),
|
||||
expects_character_input: self.expects_character_input(),
|
||||
autoindent: self.should_autoindent(),
|
||||
cursor_offset_on_selection: self.mode.is_visual() || self.mode.is_helix(),
|
||||
cursor_offset_on_selection: self.mode.has_selection(),
|
||||
line_mode: matches!(self.mode, Mode::VisualLine),
|
||||
hide_edit_predictions: !matches!(self.mode, Mode::Insert | Mode::Replace)
|
||||
&& !(self.mode.is_normal()
|
||||
|
||||
Reference in new issue
Block a user