Scroll cursor and page together (neovim-like scrolling) (#8015)

* neovim like scroll function

* clear line annotations outside of move_vertically/_visual

* add nvim scroll function to commands

* assign nvim-scroll to C-d and C-u (half page scrolls)

* dont remove backspace and space mapping

* move non-softwrap logic to seperate function, call this in nvim-scroll fn

* Revert "move non-softwrap logic to seperate function, call this in nvim-scroll fn"

This reverts commit e4905729c3.

* Revert "clear line annotations outside of move_vertically/_visual"

This reverts commit 1df3fefe55.

* add TODO for when inline diagnostics gets merged

* move nvim-scroll logic into scroll(), dont respect scrolloff

* run cargo fmt

* run cargo clippy

* update documenation for Ctrl-d and Ctrl-u remap
pull/9664/head
AlexanderDickie 4 months ago committed by GitHub
parent 6432669822
commit 9ab3f9d01a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -53,8 +53,8 @@ Normal mode is the default mode when you launch helix. You can return to it from
| `End` | Move to the end of the line | `goto_line_end` | | `End` | Move to the end of the line | `goto_line_end` |
| `Ctrl-b`, `PageUp` | Move page up | `page_up` | | `Ctrl-b`, `PageUp` | Move page up | `page_up` |
| `Ctrl-f`, `PageDown` | Move page down | `page_down` | | `Ctrl-f`, `PageDown` | Move page down | `page_down` |
| `Ctrl-u` | Move half page up | `half_page_up` | | `Ctrl-u` | Move cursor and page half page up | `page_cursor_half_up` |
| `Ctrl-d` | Move half page down | `half_page_down` | | `Ctrl-d` | Move cursor and page half page down | `page_cursor_half_down` |
| `Ctrl-i` | Jump forward on the jumplist | `jump_forward` | | `Ctrl-i` | Jump forward on the jumplist | `jump_forward` |
| `Ctrl-o` | Jump backward on the jumplist | `jump_backward` | | `Ctrl-o` | Jump backward on the jumplist | `jump_backward` |
| `Ctrl-s` | Save the current selection to the jumplist | `save_selection` | | `Ctrl-s` | Save the current selection to the jumplist | `save_selection` |
@ -182,18 +182,18 @@ normal mode) is persistent and can be exited using the escape key. This is
useful when you're simply looking over text and not actively editing it. useful when you're simply looking over text and not actively editing it.
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `z`, `c` | Vertically center the line | `align_view_center` | | `z`, `c` | Vertically center the line | `align_view_center` |
| `t` | Align the line to the top of the screen | `align_view_top` | | `t` | Align the line to the top of the screen | `align_view_top` |
| `b` | Align the line to the bottom of the screen | `align_view_bottom` | | `b` | Align the line to the bottom of the screen | `align_view_bottom` |
| `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` | | `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` |
| `j`, `down` | Scroll the view downwards | `scroll_down` | | `j`, `down` | Scroll the view downwards | `scroll_down` |
| `k`, `up` | Scroll the view upwards | `scroll_up` | | `k`, `up` | Scroll the view upwards | `scroll_up` |
| `Ctrl-f`, `PageDown` | Move page down | `page_down` | | `Ctrl-f`, `PageDown` | Move page down | `page_down` |
| `Ctrl-b`, `PageUp` | Move page up | `page_up` | | `Ctrl-b`, `PageUp` | Move page up | `page_up` |
| `Ctrl-d` | Move half page down | `half_page_down` | | `Ctrl-u` | Move cursor and page half page up | `page_cursor_half_up` |
| `Ctrl-u` | Move half page up | `half_page_up` | | `Ctrl-d` | Move cursor and page half page down | `page_cursor_half_down` |
#### Goto mode #### Goto mode

@ -277,6 +277,10 @@ impl MappableCommand {
page_down, "Move page down", page_down, "Move page down",
half_page_up, "Move half page up", half_page_up, "Move half page up",
half_page_down, "Move half page down", half_page_down, "Move half page down",
page_cursor_up, "Move page and cursor up",
page_cursor_down, "Move page and cursor down",
page_cursor_half_up, "Move page and cursor half up",
page_cursor_half_down, "Move page and cursor half down",
select_all, "Select whole document", select_all, "Select whole document",
select_regex, "Select all regex matches inside selections", select_regex, "Select all regex matches inside selections",
split_selection, "Split selections on regex matches", split_selection, "Split selections on regex matches",
@ -1608,7 +1612,7 @@ fn switch_to_lowercase(cx: &mut Context) {
}); });
} }
pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) { pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor: bool) {
use Direction::*; use Direction::*;
let config = cx.editor.config(); let config = cx.editor.config();
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
@ -1628,7 +1632,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
let doc_text = doc.text().slice(..); let doc_text = doc.text().slice(..);
let viewport = view.inner_area(doc); let viewport = view.inner_area(doc);
let text_fmt = doc.text_format(viewport.width, None); let text_fmt = doc.text_format(viewport.width, None);
let annotations = view.text_annotations(doc, None); let mut annotations = view.text_annotations(doc, None);
(view.offset.anchor, view.offset.vertical_offset) = char_idx_at_visual_offset( (view.offset.anchor, view.offset.vertical_offset) = char_idx_at_visual_offset(
doc_text, doc_text,
view.offset.anchor, view.offset.anchor,
@ -1638,6 +1642,30 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
&annotations, &annotations,
); );
if sync_cursor {
let movement = match cx.editor.mode {
Mode::Select => Movement::Extend,
_ => Movement::Move,
};
// TODO: When inline diagnostics gets merged- 1. move_vertically_visual removes
// line annotations/diagnostics so the cursor may jump further than the view.
// 2. If the cursor lands on a complete line of virtual text, the cursor will
// jump a different distance than the view.
let selection = doc.selection(view.id).clone().transform(|range| {
move_vertically_visual(
doc_text,
range,
direction,
offset.unsigned_abs(),
movement,
&text_fmt,
&mut annotations,
)
});
doc.set_selection(view.id, selection);
return;
}
let mut head; let mut head;
match direction { match direction {
Forward => { Forward => {
@ -1688,25 +1716,49 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
fn page_up(cx: &mut Context) { fn page_up(cx: &mut Context) {
let view = view!(cx.editor); let view = view!(cx.editor);
let offset = view.inner_height(); let offset = view.inner_height();
scroll(cx, offset, Direction::Backward); scroll(cx, offset, Direction::Backward, false);
} }
fn page_down(cx: &mut Context) { fn page_down(cx: &mut Context) {
let view = view!(cx.editor); let view = view!(cx.editor);
let offset = view.inner_height(); let offset = view.inner_height();
scroll(cx, offset, Direction::Forward); scroll(cx, offset, Direction::Forward, false);
} }
fn half_page_up(cx: &mut Context) { fn half_page_up(cx: &mut Context) {
let view = view!(cx.editor); let view = view!(cx.editor);
let offset = view.inner_height() / 2; let offset = view.inner_height() / 2;
scroll(cx, offset, Direction::Backward); scroll(cx, offset, Direction::Backward, false);
} }
fn half_page_down(cx: &mut Context) { fn half_page_down(cx: &mut Context) {
let view = view!(cx.editor); let view = view!(cx.editor);
let offset = view.inner_height() / 2; let offset = view.inner_height() / 2;
scroll(cx, offset, Direction::Forward); scroll(cx, offset, Direction::Forward, false);
}
fn page_cursor_up(cx: &mut Context) {
let view = view!(cx.editor);
let offset = view.inner_height();
scroll(cx, offset, Direction::Backward, true);
}
fn page_cursor_down(cx: &mut Context) {
let view = view!(cx.editor);
let offset = view.inner_height();
scroll(cx, offset, Direction::Forward, true);
}
fn page_cursor_half_up(cx: &mut Context) {
let view = view!(cx.editor);
let offset = view.inner_height() / 2;
scroll(cx, offset, Direction::Backward, true);
}
fn page_cursor_half_down(cx: &mut Context) {
let view = view!(cx.editor);
let offset = view.inner_height() / 2;
scroll(cx, offset, Direction::Forward, true);
} }
#[allow(deprecated)] #[allow(deprecated)]
@ -4856,11 +4908,11 @@ fn align_view_middle(cx: &mut Context) {
} }
fn scroll_up(cx: &mut Context) { fn scroll_up(cx: &mut Context) {
scroll(cx, cx.count(), Direction::Backward); scroll(cx, cx.count(), Direction::Backward, false);
} }
fn scroll_down(cx: &mut Context) { fn scroll_down(cx: &mut Context) {
scroll(cx, cx.count(), Direction::Forward); scroll(cx, cx.count(), Direction::Forward, false);
} }
fn goto_ts_object_impl(cx: &mut Context, object: &'static str, direction: Direction) { fn goto_ts_object_impl(cx: &mut Context, object: &'static str, direction: Direction) {

@ -178,8 +178,8 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"esc" => normal_mode, "esc" => normal_mode,
"C-b" | "pageup" => page_up, "C-b" | "pageup" => page_up,
"C-f" | "pagedown" => page_down, "C-f" | "pagedown" => page_down,
"C-u" => half_page_up, "C-u" => page_cursor_half_up,
"C-d" => half_page_down, "C-d" => page_cursor_half_down,
"C-w" => { "Window" "C-w" => { "Window"
"C-w" | "w" => rotate_view, "C-w" | "w" => rotate_view,
@ -287,8 +287,8 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"j" | "down" => scroll_down, "j" | "down" => scroll_down,
"C-b" | "pageup" => page_up, "C-b" | "pageup" => page_up,
"C-f" | "pagedown" => page_down, "C-f" | "pagedown" => page_down,
"C-u" | "backspace" => half_page_up, "C-u" | "backspace" => page_cursor_half_up,
"C-d" | "space" => half_page_down, "C-d" | "space" => page_cursor_half_down,
"/" => search, "/" => search,
"?" => rsearch, "?" => rsearch,
@ -304,8 +304,8 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"j" | "down" => scroll_down, "j" | "down" => scroll_down,
"C-b" | "pageup" => page_up, "C-b" | "pageup" => page_up,
"C-f" | "pagedown" => page_down, "C-f" | "pagedown" => page_down,
"C-u" | "backspace" => half_page_up, "C-u" | "backspace" => page_cursor_half_up,
"C-d" | "space" => half_page_down, "C-d" | "space" => page_cursor_half_down,
"/" => search, "/" => search,
"?" => rsearch, "?" => rsearch,

@ -1156,7 +1156,7 @@ impl EditorView {
} }
let offset = config.scroll_lines.unsigned_abs(); let offset = config.scroll_lines.unsigned_abs();
commands::scroll(cxt, offset, direction); commands::scroll(cxt, offset, direction, false);
cxt.editor.tree.focus = current_view; cxt.editor.tree.focus = current_view;
cxt.editor.ensure_cursor_in_view(current_view); cxt.editor.ensure_cursor_in_view(current_view);

Loading…
Cancel
Save