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 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();

@ -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))

@ -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;

@ -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<Box<dyn LineDecoration>> = 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() {

@ -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 {

@ -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<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>> {
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)]

@ -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;

@ -207,7 +207,7 @@ impl View {
doc: &Document,
scrolloff: usize,
) -> 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 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::<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) {
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 {
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<Position> {
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<usize> {
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;

Loading…
Cancel
Save