Merge a828867aeb
into 633ce23ae9
This commit is contained in:
commit
8f6cc2c1f9
2 changed files with 187 additions and 3 deletions
|
@ -433,7 +433,7 @@
|
|||
"g c": "vim::WindowMiddle",
|
||||
"g b": "vim::WindowBottom",
|
||||
|
||||
"x": "editor::SelectLine",
|
||||
"x": "vim::HelixSelectLine",
|
||||
"shift-x": "editor::SelectLine",
|
||||
"%": "editor::SelectAll",
|
||||
// Window mode
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use editor::display_map::DisplaySnapshot;
|
||||
use editor::{DisplayPoint, Editor, SelectionEffects, ToOffset, ToPoint, movement};
|
||||
use editor::{
|
||||
DisplayPoint, Editor, HideMouseCursorOrigin, SelectionEffects, ToOffset, ToPoint, movement,
|
||||
};
|
||||
use gpui::{Action, actions};
|
||||
use gpui::{Context, Window};
|
||||
use language::{CharClassifier, CharKind};
|
||||
use language::{CharClassifier, CharKind, Point};
|
||||
use text::{Bias, SelectionGoal};
|
||||
|
||||
use crate::motion;
|
||||
|
@ -23,11 +25,14 @@ actions!(
|
|||
HelixInsert,
|
||||
/// Appends at the end of the selection.
|
||||
HelixAppend,
|
||||
/// Select entire line or multiple lines, extending downwards.
|
||||
HelixSelectLine,
|
||||
]
|
||||
);
|
||||
|
||||
pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
|
||||
Vim::action(editor, cx, Vim::helix_normal_after);
|
||||
Vim::action(editor, cx, Vim::helix_select_lines);
|
||||
Vim::action(editor, cx, Vim::helix_insert);
|
||||
Vim::action(editor, cx, Vim::helix_append);
|
||||
Vim::action(editor, cx, Vim::helix_yank);
|
||||
|
@ -430,6 +435,47 @@ impl Vim {
|
|||
});
|
||||
self.switch_mode(Mode::HelixNormal, true, window, cx);
|
||||
}
|
||||
|
||||
pub fn helix_select_lines(
|
||||
&mut self,
|
||||
_: &HelixSelectLine,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let count = Vim::take_count(cx).unwrap_or(1);
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
editor.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
|
||||
let display_map = editor.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = editor.selections.all::<Point>(cx);
|
||||
let max_point = display_map.buffer_snapshot.max_point();
|
||||
let buffer_snapshot = &display_map.buffer_snapshot;
|
||||
|
||||
for selection in &mut selections {
|
||||
// Start always goes to column 0 of the first selected line
|
||||
let start_row = selection.start.row;
|
||||
let current_end_row = selection.end.row;
|
||||
|
||||
// Check if cursor is on empty line by checking first character
|
||||
let line_start_offset = buffer_snapshot.point_to_offset(Point::new(start_row, 0));
|
||||
let first_char = buffer_snapshot.chars_at(line_start_offset).next();
|
||||
let extra_line = if first_char == Some('\n') { 1 } else { 0 };
|
||||
|
||||
let end_row = current_end_row + count as u32 + extra_line;
|
||||
|
||||
selection.start = Point::new(start_row, 0);
|
||||
selection.end = if end_row > max_point.row {
|
||||
max_point
|
||||
} else {
|
||||
Point::new(end_row, 0)
|
||||
};
|
||||
selection.reversed = false;
|
||||
}
|
||||
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select(selections);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -763,4 +809,142 @@ mod test {
|
|||
cx.shared_clipboard().assert_eq("worl");
|
||||
cx.assert_state("hello «worlˇ»d", Mode::HelixNormal);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_helix_select_lines(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
cx.set_state(
|
||||
"line one\nline ˇtwo\nline three\nline four",
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("2 x");
|
||||
cx.assert_state(
|
||||
"line one\n«line two\nline three\nˇ»line four",
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
|
||||
// Test extending existing line selection
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
li«ˇne one
|
||||
li»ne two
|
||||
line three
|
||||
line four"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
«line one
|
||||
line two
|
||||
ˇ»line three
|
||||
line four"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
|
||||
// Pressing x in empty line, select next line (because helix considers cursor a selection)
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
line one
|
||||
ˇ
|
||||
line three
|
||||
line four"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
line one
|
||||
«
|
||||
line three
|
||||
ˇ»line four"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
|
||||
// Empty line with count selects extra + count lines
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
line one
|
||||
ˇ
|
||||
line three
|
||||
line four
|
||||
line five"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("2 x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
line one
|
||||
«
|
||||
line three
|
||||
line four
|
||||
ˇ»line five"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
|
||||
// Compare empty vs non-empty line behavior
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
ˇnon-empty line
|
||||
line two
|
||||
line three"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
«non-empty line
|
||||
ˇ»line two
|
||||
line three"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
|
||||
// Same test but with empty line - should select one extra
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
ˇ
|
||||
line two
|
||||
line three"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
«
|
||||
line two
|
||||
ˇ»line three"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
|
||||
// Test selecting multiple lines with count
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
ˇline one
|
||||
line two
|
||||
line threeˇ
|
||||
line four
|
||||
line five"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
«line one
|
||||
ˇ»line two
|
||||
«line three
|
||||
ˇ»line four
|
||||
line five"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
cx.simulate_keystrokes("x");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
«line one
|
||||
line two
|
||||
line three
|
||||
line four
|
||||
ˇ»line five"},
|
||||
Mode::HelixNormal,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue