diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 07aef95d0..0d13582f4 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1501,6 +1501,57 @@ fn switch_to_lowercase(cx: &mut Context) { }); } +pub fn scroll_page_and_cursor(cx: &mut Context, offset: usize, direction: Direction) { + let config = cx.editor.config(); + let cursor_pos = cx.editor.cursor().0.unwrap(); + let (view, doc) = current!(cx.editor); + + let height = view.inner_height(); + let scrolloff = config.scrolloff.min(height.saturating_sub(1) / 2); + + let offset = match direction { + Direction::Forward => offset as isize, + Direction::Backward => -(offset as isize), + }; + + let doc_text = doc.text().slice(..); + let viewport = view.inner_area(doc); + let text_fmt = doc.text_format(viewport.width, None); + let mut annotations = view.text_annotations(doc, None); + + (view.offset.anchor, view.offset.vertical_offset) = char_idx_at_visual_offset( + doc_text, + view.offset.anchor, + view.offset.vertical_offset as isize + offset, + 0, + &text_fmt, + &annotations, + ); + + let movement = match cx.editor.mode { + Mode::Select => Movement::Extend, + _ => Movement::Move, + }; + + let mut offset = offset.abs() as usize; + if cursor_pos.row <= scrolloff { + offset += scrolloff - cursor_pos.row + 1; + } + + let selection = doc.selection(view.id).clone().transform(|range| { + move_vertically_visual( + doc_text, + range, + direction, + offset, + movement, + &text_fmt, + &mut annotations, + ) + }); + doc.set_selection(view.id, selection); +} + pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) { use Direction::*; let config = cx.editor.config();