From 83e3ce09edc72dbe5ba79e1390101e846d0f0cc8 Mon Sep 17 00:00:00 2001 From: Ingrid Date: Fri, 26 Apr 2024 21:40:52 +0200 Subject: [PATCH] introduce helper functions on Document .view_offset, set_view_offset --- helix-term/src/commands.rs | 24 ++++++++++++------------ helix-term/src/commands/lsp.rs | 8 ++------ helix-term/src/commands/typed.rs | 7 +------ helix-term/src/ui/editor.rs | 6 +++--- helix-term/src/ui/mod.rs | 6 +++--- helix-view/src/document.rs | 21 +++++++++++++++------ helix-view/src/lib.rs | 7 +++---- helix-view/src/view.rs | 22 ++++++++-------------- 8 files changed, 47 insertions(+), 54 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 474f422c1..73262387a 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1023,7 +1023,7 @@ fn goto_window(cx: &mut Context, align: Align) { let count = cx.count() - 1; let config = cx.editor.config(); let (view, doc) = current!(cx.editor); - let view_offset = doc.view_data_mut(view.id).view_position; + let view_offset = doc.view_offset(view.id); let height = view.inner_height(); @@ -1668,7 +1668,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor use Direction::*; let config = cx.editor.config(); let (view, doc) = current!(cx.editor); - let view_offset = doc.view_data_mut(view.id).view_position; + let mut view_offset = doc.view_offset(view.id); let range = doc.selection(view.id).primary(); let text = doc.text().slice(..); @@ -1686,7 +1686,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor let viewport = view.inner_area(doc); let text_fmt = doc.text_format(viewport.width, None); let annotations = view.text_annotations(&*doc, None); - let (new_anchor, new_vertical_offset) = char_idx_at_visual_offset( + (view_offset.anchor, view_offset.vertical_offset) = char_idx_at_visual_offset( doc_text, view_offset.anchor, view_offset.vertical_offset as isize + offset, @@ -1694,9 +1694,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor &text_fmt, &annotations, ); - let view_data = doc.view_data_mut(view.id); - view_data.view_position.anchor = new_anchor; - view_data.view_position.vertical_offset = new_vertical_offset; + doc.set_view_offset(view.id, view_offset); let doc_text = doc.text().slice(..); let mut annotations = view.text_annotations(&*doc, None); @@ -1725,7 +1723,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor return; } - let view_offset = doc.view_data(view.id).view_position; + let view_offset = doc.view_offset(view.id); let mut head; match direction { @@ -5142,7 +5140,7 @@ fn split(editor: &mut Editor, action: Action) { let (view, doc) = current!(editor); let id = doc.id(); let selection = doc.selection(view.id).clone(); - let offset = doc.view_data(view.id).view_position; + let offset = doc.view_offset(view.id); editor.switch(id, action); @@ -5151,7 +5149,7 @@ fn split(editor: &mut Editor, action: Action) { doc.set_selection(view.id, selection); // match the view scroll offset (switch doesn't handle this fully // since the selection is only matched after the split) - doc.view_data_mut(view.id).view_position = offset; + doc.set_view_offset(view.id, offset); } fn hsplit(cx: &mut Context) { @@ -5250,16 +5248,18 @@ fn align_view_middle(cx: &mut Context) { let pos = doc.selection(view.id).primary().cursor(doc_text); let pos = visual_offset_from_block( doc_text, - doc.view_data(view.id).view_position.anchor, + doc.view_offset(view.id).anchor, pos, &text_fmt, &annotations, ) .0; - doc.view_data_mut(view.id).view_position.horizontal_offset = pos + let mut offset = doc.view_offset(view.id); + offset.horizontal_offset = pos .col .saturating_sub((view.inner_area(doc).width as usize) / 2); + doc.set_view_offset(view.id, offset); } fn scroll_up(cx: &mut Context) { @@ -6120,7 +6120,7 @@ fn jump_to_word(cx: &mut Context, behaviour: Movement) { // This is not necessarily exact if there is virtual text like soft wrap. // It's ok though because the extra jump labels will not be rendered. - let start = text.line_to_char(text.char_to_line(doc.view_data(view.id).view_position.anchor)); + let start = text.line_to_char(text.char_to_line(doc.view_offset(view.id).anchor)); let end = text.line_to_char(view.estimate_last_doc_line(doc) + 1); let primary_selection = doc.selection(view.id).primary(); diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index b2a2294a4..61512f491 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -1208,12 +1208,8 @@ fn compute_inlay_hints_for_view( // than computing all the hints for the full file (which could be dozens of time // longer than the view is). let view_height = view.inner_height(); - let first_visible_line = doc_text.char_to_line( - doc.view_data(view_id) - .view_position - .anchor - .min(doc_text.len_chars()), - ); + let first_visible_line = + doc_text.char_to_line(doc.view_offset(view_id).anchor.min(doc_text.len_chars())); let first_line = first_visible_line.saturating_sub(view_height); let last_line = first_visible_line .saturating_add(view_height.saturating_mul(2)) diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index fb4dd8e2e..fe2c0043a 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1554,12 +1554,7 @@ fn tree_sitter_highlight_name( // Query the same range as the one used in syntax highlighting. let range = { // Calculate viewport byte ranges: - let row = text.char_to_line( - doc.view_data(view.id) - .view_position - .anchor - .min(text.len_chars()), - ); + let row = text.char_to_line(doc.view_offset(view.id).anchor.min(text.len_chars())); // Saturating subs to make it inclusive zero indexing. let last_line = text.len_lines().saturating_sub(1); let height = view.inner_area(doc).height; diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index f757f2536..72c342c4a 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -93,7 +93,7 @@ impl EditorView { let theme = &editor.theme; let config = editor.config(); - let view_offset = doc.view_data(view.id).view_position; + let view_offset = doc.view_offset(view.id); let text_annotations = view.text_annotations(doc, Some(theme)); let mut line_decorations: Vec> = Vec::new(); @@ -251,7 +251,7 @@ impl EditorView { .and_then(|config| config.rulers.as_ref()) .unwrap_or(editor_rulers); - let view_offset = doc.view_data(view.id).view_position; + let view_offset = doc.view_offset(view.id); rulers .iter() @@ -827,7 +827,7 @@ impl EditorView { let inner_area = view.inner_area(doc); let selection = doc.selection(view.id); - let view_offset = doc.view_data(view.id).view_position; + let view_offset = doc.view_offset(view.id); let primary = selection.primary(); let text_format = doc.text_format(viewport.width, None); for range in selection.iter() { diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 55bf136e2..2cb05d488 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -82,7 +82,7 @@ pub fn raw_regex_prompt( let (view, doc) = current!(cx.editor); let doc_id = view.doc; let snapshot = doc.selection(view.id).clone(); - let offset_snapshot = doc.view_data(view.id).view_position; + let offset_snapshot = doc.view_offset(view.id); let config = cx.editor.config(); let mut prompt = Prompt::new( @@ -94,7 +94,7 @@ pub fn raw_regex_prompt( PromptEvent::Abort => { let (view, doc) = current!(cx.editor); doc.set_selection(view.id, snapshot.clone()); - doc.view_data_mut(view.id).view_position = offset_snapshot; + doc.set_view_offset(view.id, offset_snapshot); } PromptEvent::Update | PromptEvent::Validate => { // skip empty input @@ -135,7 +135,7 @@ pub fn raw_regex_prompt( Err(err) => { let (view, doc) = current!(cx.editor); doc.set_selection(view.id, snapshot.clone()); - doc.view_data_mut(view.id).view_position = offset_snapshot; + doc.set_view_offset(view.id, offset_snapshot); if event == PromptEvent::Validate { let callback = async move { diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index e0a1b191f..43c45c2f4 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -1734,19 +1734,28 @@ impl Document { &self.selections } - pub(crate) fn get_view_data(&self, view_id: ViewId) -> Option<&ViewData> { - self.view_data.get(&view_id) - } - pub fn view_data(&self, view_id: ViewId) -> &ViewData { + fn view_data(&self, view_id: ViewId) -> &ViewData { self.view_data .get(&view_id) .expect("This should only be called after ensure_view_init") } - pub fn view_data_mut(&mut self, view_id: ViewId) -> &mut ViewData { + fn view_data_mut(&mut self, view_id: ViewId) -> &mut ViewData { self.view_data.entry(view_id).or_default() } + pub(crate) fn get_view_offset(&self, view_id: ViewId) -> Option { + Some(self.view_data.get(&view_id)?.view_position) + } + + pub fn view_offset(&self, view_id: ViewId) -> ViewPosition { + self.view_data(view_id).view_position + } + + pub fn set_view_offset(&mut self, view_id: ViewId, new_offset: ViewPosition) { + self.view_data_mut(view_id).view_position = new_offset; + } + pub fn relative_path(&self) -> Option> { self.path .as_deref() @@ -2023,7 +2032,7 @@ impl Document { #[derive(Debug, Default)] pub struct ViewData { - pub view_position: ViewPosition, + view_position: ViewPosition, } #[derive(Clone, Debug)] diff --git a/helix-view/src/lib.rs b/helix-view/src/lib.rs index 4563df48e..1b67b4878 100644 --- a/helix-view/src/lib.rs +++ b/helix-view/src/lib.rs @@ -51,6 +51,7 @@ pub fn align_view(doc: &mut Document, view: &View, align: Align) { let cursor = doc.selection(view.id).primary().cursor(doc_text); let viewport = view.inner_area(doc); let last_line_height = viewport.height.saturating_sub(1); + let mut view_offset = doc.view_offset(view.id); let relative = match align { Align::Center => last_line_height / 2, @@ -60,7 +61,7 @@ pub fn align_view(doc: &mut Document, view: &View, align: Align) { let text_fmt = doc.text_format(viewport.width, None); let annotations = view.text_annotations(doc, None); - let (new_anchor, new_vertical_offset) = char_idx_at_visual_offset( + (view_offset.anchor, view_offset.vertical_offset) = char_idx_at_visual_offset( doc_text, cursor, -(relative as isize), @@ -68,9 +69,7 @@ pub fn align_view(doc: &mut Document, view: &View, align: Align) { &text_fmt, &annotations, ); - let view_data = doc.view_data_mut(view.id); - view_data.view_position.anchor = new_anchor; - view_data.view_position.vertical_offset = new_vertical_offset; + doc.set_view_offset(view.id, view_offset); } pub use document::Document; diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 873104960..89c412309 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -207,7 +207,7 @@ impl View { doc: &Document, scrolloff: usize, ) -> Option { - let view_offset = doc.get_view_data(self.id)?.view_position; + let view_offset = doc.get_view_offset(self.id)?; let doc_text = doc.text().slice(..); let viewport = self.inner_area(doc); let vertical_viewport_end = view_offset.vertical_offset + viewport.height as usize; @@ -298,13 +298,13 @@ impl View { pub fn ensure_cursor_in_view(&self, doc: &mut Document, scrolloff: usize) { if let Some(offset) = self.offset_coords_to_in_view_center::(doc, scrolloff) { - doc.view_data_mut(self.id).view_position = offset; + doc.set_view_offset(self.id, offset); } } pub fn ensure_cursor_in_view_center(&self, doc: &mut Document, scrolloff: usize) { if let Some(offset) = self.offset_coords_to_in_view_center::(doc, scrolloff) { - doc.view_data_mut(self.id).view_position = offset; + doc.set_view_offset(self.id, offset); } else { align_view(doc, self, Align::Center); } @@ -322,12 +322,7 @@ impl View { #[inline] pub fn estimate_last_doc_line(&self, doc: &Document) -> usize { let doc_text = doc.text().slice(..); - let line = doc_text.char_to_line( - doc.view_data(self.id) - .view_position - .anchor - .min(doc_text.len_chars()), - ); + let line = doc_text.char_to_line(doc.view_offset(self.id).anchor.min(doc_text.len_chars())); // Saturating subs to make it inclusive zero indexing. (line + self.inner_height()) .min(doc_text.len_lines()) @@ -341,11 +336,10 @@ impl View { let viewport = self.inner_area(doc); let text_fmt = doc.text_format(viewport.width, None); let annotations = self.text_annotations(doc, None); - let view_offset = doc.view_data(self.id).view_position; + let view_offset = doc.view_offset(self.id); // last visual line in view is trivial to compute - let visual_height = - doc.view_data(self.id).view_position.vertical_offset + viewport.height as usize; + let visual_height = doc.view_offset(self.id).vertical_offset + viewport.height as usize; // fast path when the EOF is not visible on the screen, if self.estimate_last_doc_line(doc) < doc_text.len_lines() - 1 { @@ -378,7 +372,7 @@ impl View { text: RopeSlice, pos: usize, ) -> Option { - let view_offset = doc.view_data(self.id).view_position; + let view_offset = doc.view_offset(self.id); if pos < view_offset.anchor { // Line is not visible on screen @@ -500,7 +494,7 @@ impl View { ignore_virtual_text: bool, ) -> Option { let text = doc.text().slice(..); - let view_offset = doc.view_data(self.id).view_position; + let view_offset = doc.view_offset(self.id); let text_row = row as usize + view_offset.vertical_offset; let text_col = column as usize + view_offset.horizontal_offset;