introduce helper functions on Document .view_offset, set_view_offset

pull/10559/head
Ingrid 2 months ago
parent 6494301e3c
commit 83e3ce09ed

@ -1023,7 +1023,7 @@ fn goto_window(cx: &mut Context, align: Align) {
let count = cx.count() - 1; let count = cx.count() - 1;
let config = cx.editor.config(); let config = cx.editor.config();
let (view, doc) = current!(cx.editor); 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(); let height = view.inner_height();
@ -1668,7 +1668,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor
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);
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 range = doc.selection(view.id).primary();
let text = doc.text().slice(..); 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 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 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, doc_text,
view_offset.anchor, view_offset.anchor,
view_offset.vertical_offset as isize + offset, 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, &text_fmt,
&annotations, &annotations,
); );
let view_data = doc.view_data_mut(view.id); doc.set_view_offset(view.id, view_offset);
view_data.view_position.anchor = new_anchor;
view_data.view_position.vertical_offset = new_vertical_offset;
let doc_text = doc.text().slice(..); let doc_text = doc.text().slice(..);
let mut annotations = view.text_annotations(&*doc, None); 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; return;
} }
let view_offset = doc.view_data(view.id).view_position; let view_offset = doc.view_offset(view.id);
let mut head; let mut head;
match direction { match direction {
@ -5142,7 +5140,7 @@ fn split(editor: &mut Editor, action: Action) {
let (view, doc) = current!(editor); let (view, doc) = current!(editor);
let id = doc.id(); let id = doc.id();
let selection = doc.selection(view.id).clone(); 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); editor.switch(id, action);
@ -5151,7 +5149,7 @@ fn split(editor: &mut Editor, action: Action) {
doc.set_selection(view.id, selection); doc.set_selection(view.id, selection);
// match the view scroll offset (switch doesn't handle this fully // match the view scroll offset (switch doesn't handle this fully
// since the selection is only matched after the split) // 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) { 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 = doc.selection(view.id).primary().cursor(doc_text);
let pos = visual_offset_from_block( let pos = visual_offset_from_block(
doc_text, doc_text,
doc.view_data(view.id).view_position.anchor, doc.view_offset(view.id).anchor,
pos, pos,
&text_fmt, &text_fmt,
&annotations, &annotations,
) )
.0; .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 .col
.saturating_sub((view.inner_area(doc).width as usize) / 2); .saturating_sub((view.inner_area(doc).width as usize) / 2);
doc.set_view_offset(view.id, offset);
} }
fn scroll_up(cx: &mut Context) { 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. // 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. // 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 end = text.line_to_char(view.estimate_last_doc_line(doc) + 1);
let primary_selection = doc.selection(view.id).primary(); let primary_selection = doc.selection(view.id).primary();

@ -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 // than computing all the hints for the full file (which could be dozens of time
// longer than the view is). // longer than the view is).
let view_height = view.inner_height(); let view_height = view.inner_height();
let first_visible_line = doc_text.char_to_line( let first_visible_line =
doc.view_data(view_id) doc_text.char_to_line(doc.view_offset(view_id).anchor.min(doc_text.len_chars()));
.view_position
.anchor
.min(doc_text.len_chars()),
);
let first_line = first_visible_line.saturating_sub(view_height); let first_line = first_visible_line.saturating_sub(view_height);
let last_line = first_visible_line let last_line = first_visible_line
.saturating_add(view_height.saturating_mul(2)) .saturating_add(view_height.saturating_mul(2))

@ -1554,12 +1554,7 @@ fn tree_sitter_highlight_name(
// Query the same range as the one used in syntax highlighting. // Query the same range as the one used in syntax highlighting.
let range = { let range = {
// Calculate viewport byte ranges: // Calculate viewport byte ranges:
let row = text.char_to_line( let row = text.char_to_line(doc.view_offset(view.id).anchor.min(text.len_chars()));
doc.view_data(view.id)
.view_position
.anchor
.min(text.len_chars()),
);
// Saturating subs to make it inclusive zero indexing. // Saturating subs to make it inclusive zero indexing.
let last_line = text.len_lines().saturating_sub(1); let last_line = text.len_lines().saturating_sub(1);
let height = view.inner_area(doc).height; let height = view.inner_area(doc).height;

@ -93,7 +93,7 @@ impl EditorView {
let theme = &editor.theme; let theme = &editor.theme;
let config = editor.config(); 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 text_annotations = view.text_annotations(doc, Some(theme));
let mut line_decorations: Vec<Box<dyn LineDecoration>> = Vec::new(); let mut line_decorations: Vec<Box<dyn LineDecoration>> = Vec::new();
@ -251,7 +251,7 @@ impl EditorView {
.and_then(|config| config.rulers.as_ref()) .and_then(|config| config.rulers.as_ref())
.unwrap_or(editor_rulers); .unwrap_or(editor_rulers);
let view_offset = doc.view_data(view.id).view_position; let view_offset = doc.view_offset(view.id);
rulers rulers
.iter() .iter()
@ -827,7 +827,7 @@ impl EditorView {
let inner_area = view.inner_area(doc); let inner_area = view.inner_area(doc);
let selection = doc.selection(view.id); 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 primary = selection.primary();
let text_format = doc.text_format(viewport.width, None); let text_format = doc.text_format(viewport.width, None);
for range in selection.iter() { for range in selection.iter() {

@ -82,7 +82,7 @@ pub fn raw_regex_prompt(
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
let doc_id = view.doc; let doc_id = view.doc;
let snapshot = doc.selection(view.id).clone(); 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 config = cx.editor.config();
let mut prompt = Prompt::new( let mut prompt = Prompt::new(
@ -94,7 +94,7 @@ pub fn raw_regex_prompt(
PromptEvent::Abort => { PromptEvent::Abort => {
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
doc.set_selection(view.id, snapshot.clone()); 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 => { PromptEvent::Update | PromptEvent::Validate => {
// skip empty input // skip empty input
@ -135,7 +135,7 @@ pub fn raw_regex_prompt(
Err(err) => { Err(err) => {
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
doc.set_selection(view.id, snapshot.clone()); 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 { if event == PromptEvent::Validate {
let callback = async move { let callback = async move {

@ -1734,19 +1734,28 @@ impl Document {
&self.selections &self.selections
} }
pub(crate) fn get_view_data(&self, view_id: ViewId) -> Option<&ViewData> { fn view_data(&self, view_id: ViewId) -> &ViewData {
self.view_data.get(&view_id)
}
pub fn view_data(&self, view_id: ViewId) -> &ViewData {
self.view_data self.view_data
.get(&view_id) .get(&view_id)
.expect("This should only be called after ensure_view_init") .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() self.view_data.entry(view_id).or_default()
} }
pub(crate) fn get_view_offset(&self, view_id: ViewId) -> Option<ViewPosition> {
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<Cow<Path>> { pub fn relative_path(&self) -> Option<Cow<Path>> {
self.path self.path
.as_deref() .as_deref()
@ -2023,7 +2032,7 @@ impl Document {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ViewData { pub struct ViewData {
pub view_position: ViewPosition, view_position: ViewPosition,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

@ -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 cursor = doc.selection(view.id).primary().cursor(doc_text);
let viewport = view.inner_area(doc); let viewport = view.inner_area(doc);
let last_line_height = viewport.height.saturating_sub(1); let last_line_height = viewport.height.saturating_sub(1);
let mut view_offset = doc.view_offset(view.id);
let relative = match align { let relative = match align {
Align::Center => last_line_height / 2, 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 text_fmt = doc.text_format(viewport.width, None);
let annotations = view.text_annotations(doc, 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, doc_text,
cursor, cursor,
-(relative as isize), -(relative as isize),
@ -68,9 +69,7 @@ pub fn align_view(doc: &mut Document, view: &View, align: Align) {
&text_fmt, &text_fmt,
&annotations, &annotations,
); );
let view_data = doc.view_data_mut(view.id); doc.set_view_offset(view.id, view_offset);
view_data.view_position.anchor = new_anchor;
view_data.view_position.vertical_offset = new_vertical_offset;
} }
pub use document::Document; pub use document::Document;

@ -207,7 +207,7 @@ impl View {
doc: &Document, doc: &Document,
scrolloff: usize, scrolloff: usize,
) -> Option<ViewPosition> { ) -> Option<ViewPosition> {
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 doc_text = doc.text().slice(..);
let viewport = self.inner_area(doc); let viewport = self.inner_area(doc);
let vertical_viewport_end = view_offset.vertical_offset + viewport.height as usize; 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) { pub fn ensure_cursor_in_view(&self, doc: &mut Document, scrolloff: usize) {
if let Some(offset) = self.offset_coords_to_in_view_center::<false>(doc, scrolloff) { if let Some(offset) = self.offset_coords_to_in_view_center::<false>(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) { pub fn ensure_cursor_in_view_center(&self, doc: &mut Document, scrolloff: usize) {
if let Some(offset) = self.offset_coords_to_in_view_center::<true>(doc, scrolloff) { if let Some(offset) = self.offset_coords_to_in_view_center::<true>(doc, scrolloff) {
doc.view_data_mut(self.id).view_position = offset; doc.set_view_offset(self.id, offset);
} else { } else {
align_view(doc, self, Align::Center); align_view(doc, self, Align::Center);
} }
@ -322,12 +322,7 @@ impl View {
#[inline] #[inline]
pub fn estimate_last_doc_line(&self, doc: &Document) -> usize { pub fn estimate_last_doc_line(&self, doc: &Document) -> usize {
let doc_text = doc.text().slice(..); let doc_text = doc.text().slice(..);
let line = doc_text.char_to_line( let line = doc_text.char_to_line(doc.view_offset(self.id).anchor.min(doc_text.len_chars()));
doc.view_data(self.id)
.view_position
.anchor
.min(doc_text.len_chars()),
);
// Saturating subs to make it inclusive zero indexing. // Saturating subs to make it inclusive zero indexing.
(line + self.inner_height()) (line + self.inner_height())
.min(doc_text.len_lines()) .min(doc_text.len_lines())
@ -341,11 +336,10 @@ impl View {
let viewport = self.inner_area(doc); let viewport = self.inner_area(doc);
let text_fmt = doc.text_format(viewport.width, None); let text_fmt = doc.text_format(viewport.width, None);
let annotations = self.text_annotations(doc, 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 // last visual line in view is trivial to compute
let visual_height = let visual_height = doc.view_offset(self.id).vertical_offset + viewport.height as usize;
doc.view_data(self.id).view_position.vertical_offset + viewport.height as usize;
// fast path when the EOF is not visible on the screen, // fast path when the EOF is not visible on the screen,
if self.estimate_last_doc_line(doc) < doc_text.len_lines() - 1 { if self.estimate_last_doc_line(doc) < doc_text.len_lines() - 1 {
@ -378,7 +372,7 @@ impl View {
text: RopeSlice, text: RopeSlice,
pos: usize, pos: usize,
) -> Option<Position> { ) -> Option<Position> {
let view_offset = doc.view_data(self.id).view_position; let view_offset = doc.view_offset(self.id);
if pos < view_offset.anchor { if pos < view_offset.anchor {
// Line is not visible on screen // Line is not visible on screen
@ -500,7 +494,7 @@ impl View {
ignore_virtual_text: bool, ignore_virtual_text: bool,
) -> Option<usize> { ) -> Option<usize> {
let text = doc.text().slice(..); 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_row = row as usize + view_offset.vertical_offset;
let text_col = column as usize + view_offset.horizontal_offset; let text_col = column as usize + view_offset.horizontal_offset;

Loading…
Cancel
Save