Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--helix-term/src/application.rs6
-rw-r--r--helix-term/src/commands.rs57
-rw-r--r--helix-term/src/commands/lsp.rs3
-rw-r--r--helix-term/src/commands/typed.rs2
-rw-r--r--helix-term/src/ui/editor.rs21
-rw-r--r--helix-term/src/ui/mod.rs6
-rw-r--r--helix-view/src/document.rs51
-rw-r--r--helix-view/src/editor.rs15
-rw-r--r--helix-view/src/lib.rs9
-rw-r--r--helix-view/src/view.rs64
10 files changed, 150 insertions, 84 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index b7123e97..60bc5b7c 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -395,9 +395,9 @@ impl Application {
// reset view position in case softwrap was enabled/disabled
let scrolloff = self.editor.config().scrolloff;
- for (view, _) in self.editor.tree.views_mut() {
- let doc = &self.editor.documents[&view.doc];
- view.ensure_cursor_in_view(doc, scrolloff)
+ for (view, _) in self.editor.tree.views() {
+ let doc = doc_mut!(self.editor, &view.doc);
+ view.ensure_cursor_in_view(doc, scrolloff);
}
}
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 7e0bee92..2c5d2783 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1032,6 +1032,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_offset(view.id);
let height = view.inner_height();
@@ -1044,15 +1045,15 @@ fn goto_window(cx: &mut Context, align: Align) {
let last_visual_line = view.last_visual_line(doc);
let visual_line = match align {
- Align::Top => view.offset.vertical_offset + scrolloff + count,
- Align::Center => view.offset.vertical_offset + (last_visual_line / 2),
+ Align::Top => view_offset.vertical_offset + scrolloff + count,
+ Align::Center => view_offset.vertical_offset + (last_visual_line / 2),
Align::Bottom => {
- view.offset.vertical_offset + last_visual_line.saturating_sub(scrolloff + count)
+ view_offset.vertical_offset + last_visual_line.saturating_sub(scrolloff + count)
}
};
let visual_line = visual_line
- .max(view.offset.vertical_offset + scrolloff)
- .min(view.offset.vertical_offset + last_visual_line.saturating_sub(scrolloff));
+ .max(view_offset.vertical_offset + scrolloff)
+ .min(view_offset.vertical_offset + last_visual_line.saturating_sub(scrolloff));
let pos = view
.pos_at_visual_coords(doc, visual_line as u16, 0, false)
@@ -1665,6 +1666,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 mut view_offset = doc.view_offset(view.id);
let range = doc.selection(view.id).primary();
let text = doc.text().slice(..);
@@ -1681,15 +1683,19 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor
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(
+ (view_offset.anchor, view_offset.vertical_offset) = char_idx_at_visual_offset(
doc_text,
- view.offset.anchor,
- view.offset.vertical_offset as isize + offset,
+ view_offset.anchor,
+ view_offset.vertical_offset as isize + offset,
0,
&text_fmt,
- &annotations,
+ // &annotations,
+ &view.text_annotations(&*doc, None),
);
+ doc.set_view_offset(view.id, view_offset);
+
+ let doc_text = doc.text().slice(..);
+ let mut annotations = view.text_annotations(&*doc, None);
if sync_cursor {
let movement = match cx.editor.mode {
@@ -1716,14 +1722,16 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor
return;
}
+ let view_offset = doc.view_offset(view.id);
+
let mut head;
match direction {
Forward => {
let off;
(head, off) = char_idx_at_visual_offset(
doc_text,
- view.offset.anchor,
- (view.offset.vertical_offset + scrolloff) as isize,
+ view_offset.anchor,
+ (view_offset.vertical_offset + scrolloff) as isize,
0,
&text_fmt,
&annotations,
@@ -1736,8 +1744,8 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor
Backward => {
head = char_idx_at_visual_offset(
doc_text,
- view.offset.anchor,
- (view.offset.vertical_offset + height - scrolloff - 1) as isize,
+ view_offset.anchor,
+ (view_offset.vertical_offset + height - scrolloff - 1) as isize,
0,
&text_fmt,
&annotations,
@@ -5124,7 +5132,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 = view.offset;
+ let offset = doc.view_offset(view.id);
editor.switch(id, action);
@@ -5133,7 +5141,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)
- view.offset = offset;
+ doc.set_view_offset(view.id, offset);
}
fn hsplit(cx: &mut Context) {
@@ -5228,14 +5236,21 @@ fn align_view_middle(cx: &mut Context) {
return;
}
let doc_text = doc.text().slice(..);
- let annotations = view.text_annotations(doc, None);
let pos = doc.selection(view.id).primary().cursor(doc_text);
- let pos =
- visual_offset_from_block(doc_text, view.offset.anchor, pos, &text_fmt, &annotations).0;
+ let pos = visual_offset_from_block(
+ doc_text,
+ doc.view_offset(view.id).anchor,
+ pos,
+ &text_fmt,
+ &view.text_annotations(doc, None),
+ )
+ .0;
- view.offset.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) {
@@ -6117,7 +6132,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(view.offset.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 3b9efb43..9194377c 100644
--- a/helix-term/src/commands/lsp.rs
+++ b/helix-term/src/commands/lsp.rs
@@ -1299,7 +1299,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(view.offset.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 530d7809..720d32ac 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1587,7 +1587,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(view.offset.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 c151a7dd..f7541fe2 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -93,6 +93,8 @@ impl EditorView {
let theme = &editor.theme;
let config = editor.config();
+ let view_offset = doc.view_offset(view.id);
+
let text_annotations = view.text_annotations(doc, Some(theme));
let mut decorations = DecorationManager::default();
@@ -119,13 +121,13 @@ impl EditorView {
}
let syntax_highlights =
- Self::doc_syntax_highlights(doc, view.offset.anchor, inner.height, theme);
+ Self::doc_syntax_highlights(doc, view_offset.anchor, inner.height, theme);
let mut overlay_highlights =
- Self::empty_highlight_iter(doc, view.offset.anchor, inner.height);
+ Self::empty_highlight_iter(doc, view_offset.anchor, inner.height);
let overlay_syntax_highlights = Self::overlay_syntax_highlights(
doc,
- view.offset.anchor,
+ view_offset.anchor,
inner.height,
&text_annotations,
);
@@ -203,7 +205,7 @@ impl EditorView {
surface,
inner,
doc,
- view.offset,
+ view_offset,
&text_annotations,
syntax_highlights,
overlay_highlights,
@@ -259,11 +261,13 @@ impl EditorView {
.and_then(|config| config.rulers.as_ref())
.unwrap_or(editor_rulers);
+ let view_offset = doc.view_offset(view.id);
+
rulers
.iter()
// View might be horizontally scrolled, convert from absolute distance
// from the 1st column to relative distance from left of viewport
- .filter_map(|ruler| ruler.checked_sub(1 + view.offset.horizontal_offset as u16))
+ .filter_map(|ruler| ruler.checked_sub(1 + view_offset.horizontal_offset as u16))
.filter(|ruler| ruler < &viewport.width)
.map(|ruler| viewport.clip_left(ruler).with_width(1))
.for_each(|area| surface.set_style(area, ruler_theme))
@@ -825,6 +829,7 @@ impl EditorView {
let inner_area = view.inner_area(doc);
let selection = doc.selection(view.id);
+ 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() {
@@ -835,11 +840,11 @@ impl EditorView {
visual_offset_from_block(text, cursor, cursor, &text_format, text_annotations).0;
// if the cursor is horizontally in the view
- if col >= view.offset.horizontal_offset
- && inner_area.width > (col - view.offset.horizontal_offset) as u16
+ if col >= view_offset.horizontal_offset
+ && inner_area.width > (col - view_offset.horizontal_offset) as u16
{
let area = Rect::new(
- inner_area.x + (col - view.offset.horizontal_offset) as u16,
+ inner_area.x + (col - view_offset.horizontal_offset) as u16,
view.area.y,
1,
view.area.height,
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index 10f4104a..6a3e198c 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -83,7 +83,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 = view.offset;
+ let offset_snapshot = doc.view_offset(view.id);
let config = cx.editor.config();
let mut prompt = Prompt::new(
@@ -95,7 +95,7 @@ pub fn raw_regex_prompt(
PromptEvent::Abort => {
let (view, doc) = current!(cx.editor);
doc.set_selection(view.id, snapshot.clone());
- view.offset = offset_snapshot;
+ doc.set_view_offset(view.id, offset_snapshot);
}
PromptEvent::Update | PromptEvent::Validate => {
// skip empty input
@@ -136,7 +136,7 @@ pub fn raw_regex_prompt(
Err(err) => {
let (view, doc) = current!(cx.editor);
doc.set_selection(view.id, snapshot.clone());
- view.offset = 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 f3ace89e..532f4c34 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -37,9 +37,12 @@ use helix_core::{
ChangeSet, Diagnostic, LineEnding, Range, Rope, RopeBuilder, Selection, Syntax, Transaction,
};
-use crate::editor::Config;
-use crate::events::{DocumentDidChange, SelectionDidChange};
-use crate::{DocumentId, Editor, Theme, View, ViewId};
+use crate::{
+ editor::Config,
+ events::{DocumentDidChange, SelectionDidChange},
+ view::ViewPosition,
+ DocumentId, Editor, Theme, View, ViewId,
+};
/// 8kB of buffer space for encoding and decoding `Rope`s.
const BUF_SIZE: usize = 8192;
@@ -130,6 +133,7 @@ pub struct Document {
pub(crate) id: DocumentId,
text: Rope,
selections: HashMap<ViewId, Selection>,
+ view_data: HashMap<ViewId, ViewData>,
/// Inlay hints annotations for the document, by view.
///
@@ -265,6 +269,7 @@ impl fmt::Debug for Document {
.field("selections", &self.selections)
.field("inlay_hints_oudated", &self.inlay_hints_oudated)
.field("text_annotations", &self.inlay_hints)
+ .field("view_data", &self.view_data)
.field("path", &self.path)
.field("encoding", &self.encoding)
.field("restore_cursor", &self.restore_cursor)
@@ -656,6 +661,7 @@ impl Document {
selections: HashMap::default(),
inlay_hints: HashMap::default(),
inlay_hints_oudated: false,
+ view_data: Default::default(),
indent_style: DEFAULT_INDENT,
line_ending,
restore_cursor: false,
@@ -1184,12 +1190,14 @@ impl Document {
self.set_selection(view_id, Selection::single(origin.anchor, origin.head));
}
- /// Initializes a new selection for the given view if it does not
- /// already have one.
+ /// Initializes a new selection and view_data for the given view
+ /// if it does not already have them.
pub fn ensure_view_init(&mut self, view_id: ViewId) {
if self.selections.get(&view_id).is_none() {
self.reset_selection(view_id);
}
+
+ self.view_data_mut(view_id);
}
/// Mark document as recent used for MRU sorting
@@ -1235,6 +1243,12 @@ impl Document {
.ensure_invariants(self.text.slice(..));
}
+ for view_data in self.view_data.values_mut() {
+ view_data.view_position.anchor = transaction
+ .changes()
+ .map_pos(view_data.view_position.anchor, Assoc::Before);
+ }
+
// if specified, the current selection should instead be replaced by transaction.selection
if let Some(selection) = transaction.selection() {
self.selections.insert(
@@ -1759,6 +1773,28 @@ impl Document {
&self.selections
}
+ fn view_data(&self, view_id: ViewId) -> &ViewData {
+ self.view_data
+ .get(&view_id)
+ .expect("This should only be called after ensure_view_init")
+ }
+
+ 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()
@@ -2034,6 +2070,11 @@ impl Document {
}
}
+#[derive(Debug, Default)]
+pub struct ViewData {
+ view_position: ViewPosition,
+}
+
#[derive(Clone, Debug)]
pub enum FormatterError {
SpawningFailed {
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index cead30d7..ba7337f2 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -1,5 +1,4 @@
use crate::{
- align_view,
annotations::diagnostics::{DiagnosticFilter, InlineDiagnosticsConfig},
document::{
DocumentOpenError, DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint,
@@ -11,8 +10,7 @@ use crate::{
register::Registers,
theme::{self, Theme},
tree::{self, Tree},
- view::ViewPosition,
- Align, Document, DocumentId, View, ViewId,
+ Document, DocumentId, View, ViewId,
};
use dap::StackFrame;
use helix_vcs::DiffProviderRegistry;
@@ -1530,16 +1528,17 @@ impl Editor {
}
fn replace_document_in_view(&mut self, current_view: ViewId, doc_id: DocumentId) {
+ let scrolloff = self.config().scrolloff;
let view = self.tree.get_mut(current_view);
- view.doc = doc_id;
- view.offset = ViewPosition::default();
+ view.doc = doc_id;
let doc = doc_mut!(self, &doc_id);
+
doc.ensure_view_init(view.id);
view.sync_changes(doc);
doc.mark_as_focused();
- align_view(doc, view, Align::Center);
+ view.ensure_cursor_in_view(doc, scrolloff)
}
pub fn switch(&mut self, id: DocumentId, action: Action) {
@@ -1899,8 +1898,8 @@ impl Editor {
pub fn ensure_cursor_in_view(&mut self, id: ViewId) {
let config = self.config();
- let view = self.tree.get_mut(id);
- let doc = &self.documents[&view.doc];
+ let view = self.tree.get(id);
+ let doc = doc_mut!(self, &view.doc);
view.ensure_cursor_in_view(doc, config.scrolloff)
}
diff --git a/helix-view/src/lib.rs b/helix-view/src/lib.rs
index 5628c830..d54b49ef 100644
--- a/helix-view/src/lib.rs
+++ b/helix-view/src/lib.rs
@@ -47,11 +47,12 @@ pub enum Align {
Bottom,
}
-pub fn align_view(doc: &Document, view: &mut View, align: Align) {
+pub fn align_view(doc: &mut Document, view: &View, align: Align) {
let doc_text = doc.text().slice(..);
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,15 +61,15 @@ pub fn align_view(doc: &Document, view: &mut View, align: Align) {
};
let text_fmt = doc.text_format(viewport.width, None);
- let 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,
cursor,
-(relative as isize),
0,
&text_fmt,
- &annotations,
+ &view.text_annotations(doc, None),
);
+ 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 af4fdfe4..fb83c4b8 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -128,7 +128,6 @@ pub struct ViewPosition {
#[derive(Clone)]
pub struct View {
pub id: ViewId,
- pub offset: ViewPosition,
pub area: Rect,
pub doc: DocumentId,
pub jumps: JumpList,
@@ -173,11 +172,6 @@ impl View {
Self {
id: ViewId::default(),
doc,
- offset: ViewPosition {
- anchor: 0,
- horizontal_offset: 0,
- vertical_offset: 0,
- },
area: Rect::default(), // will get calculated upon inserting into tree
jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
docs_access_history: Vec::new(),
@@ -240,9 +234,10 @@ impl View {
doc: &Document,
scrolloff: usize,
) -> Option<ViewPosition> {
+ 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 = self.offset.vertical_offset + viewport.height as usize;
+ let vertical_viewport_end = view_offset.vertical_offset + viewport.height as usize;
let text_fmt = doc.text_format(viewport.width, None);
let annotations = self.text_annotations(doc, None);
@@ -256,7 +251,7 @@ impl View {
};
let cursor = doc.selection(self.id).primary().cursor(doc_text);
- let mut offset = self.offset;
+ let mut offset = view_offset;
let off = visual_offset_from_anchor(
doc_text,
offset.anchor,
@@ -321,22 +316,22 @@ impl View {
}
// if we are not centering return None if view position is unchanged
- if !CENTERING && offset == self.offset {
+ if !CENTERING && offset == view_offset {
return None;
}
Some(offset)
}
- pub fn ensure_cursor_in_view(&mut self, doc: &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) {
- self.offset = offset;
+ doc.set_view_offset(self.id, offset);
}
}
- pub fn ensure_cursor_in_view_center(&mut self, doc: &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) {
- self.offset = offset;
+ doc.set_view_offset(self.id, offset);
} else {
align_view(doc, self, Align::Center);
}
@@ -354,7 +349,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(self.offset.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())
@@ -368,9 +363,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_offset(self.id);
// last visual line in view is trivial to compute
- let visual_height = self.offset.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 {
@@ -380,7 +376,7 @@ impl View {
// translate to document line
let pos = visual_offset_from_anchor(
doc_text,
- self.offset.anchor,
+ view_offset.anchor,
usize::MAX,
&text_fmt,
&annotations,
@@ -388,7 +384,7 @@ impl View {
);
match pos {
- Ok((Position { row, .. }, _)) => row.saturating_sub(self.offset.vertical_offset),
+ Ok((Position { row, .. }, _)) => row.saturating_sub(view_offset.vertical_offset),
Err(PosAfterMaxRow) => visual_height.saturating_sub(1),
Err(PosBeforeAnchorRow) => 0,
}
@@ -403,13 +399,15 @@ impl View {
text: RopeSlice,
pos: usize,
) -> Option<Position> {
+ let view_offset = doc.view_offset(self.id);
+
let viewport = self.inner_area(doc);
let text_fmt = doc.text_format(viewport.width, None);
let annotations = self.text_annotations(doc, None);
let mut pos = visual_offset_from_anchor(
text,
- self.offset.anchor,
+ view_offset.anchor,
pos,
&text_fmt,
&annotations,
@@ -417,14 +415,14 @@ impl View {
)
.ok()?
.0;
- if pos.row < self.offset.vertical_offset {
+ if pos.row < view_offset.vertical_offset {
return None;
}
- pos.row -= self.offset.vertical_offset;
+ pos.row -= view_offset.vertical_offset;
if pos.row >= viewport.height as usize {
return None;
}
- pos.col = pos.col.saturating_sub(self.offset.horizontal_offset);
+ pos.col = pos.col.saturating_sub(view_offset.horizontal_offset);
Some(pos)
}
@@ -488,7 +486,7 @@ impl View {
doc,
cursor,
width,
- self.offset.horizontal_offset,
+ doc.view_offset(self.id).horizontal_offset,
config,
));
}
@@ -535,13 +533,14 @@ impl View {
ignore_virtual_text: bool,
) -> Option<usize> {
let text = doc.text().slice(..);
+ let view_offset = doc.view_offset(self.id);
- let text_row = row as usize + self.offset.vertical_offset;
- let text_col = column as usize + self.offset.horizontal_offset;
+ let text_row = row as usize + view_offset.vertical_offset;
+ let text_col = column as usize + view_offset.horizontal_offset;
let (char_idx, virt_lines) = char_idx_at_visual_offset(
text,
- self.offset.anchor,
+ view_offset.anchor,
text_row as isize,
text_col,
&text_fmt,
@@ -689,11 +688,12 @@ mod tests {
let mut view = View::new(DocumentId::default(), GutterConfig::default());
view.area = Rect::new(40, 40, 40, 40);
let rope = Rope::from_str("abc\n\tdef");
- let doc = Document::from(
+ let mut doc = Document::from(
rope,
None,
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
);
+ doc.ensure_view_init(view.id);
assert_eq!(
view.text_pos_at_screen_coords(
@@ -863,11 +863,12 @@ mod tests {
);
view.area = Rect::new(40, 40, 40, 40);
let rope = Rope::from_str("abc\n\tdef");
- let doc = Document::from(
+ let mut doc = Document::from(
rope,
None,
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
);
+ doc.ensure_view_init(view.id);
assert_eq!(
view.text_pos_at_screen_coords(
&doc,
@@ -892,11 +893,12 @@ mod tests {
);
view.area = Rect::new(40, 40, 40, 40);
let rope = Rope::from_str("abc\n\tdef");
- let doc = Document::from(
+ let mut doc = Document::from(
rope,
None,
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
);
+ doc.ensure_view_init(view.id);
assert_eq!(
view.text_pos_at_screen_coords(
&doc,
@@ -915,11 +917,12 @@ mod tests {
let mut view = View::new(DocumentId::default(), GutterConfig::default());
view.area = Rect::new(40, 40, 40, 40);
let rope = Rope::from_str("Hi! こんにちは皆さん");
- let doc = Document::from(
+ let mut doc = Document::from(
rope,
None,
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
);
+ doc.ensure_view_init(view.id);
assert_eq!(
view.text_pos_at_screen_coords(
@@ -998,11 +1001,12 @@ mod tests {
let mut view = View::new(DocumentId::default(), GutterConfig::default());
view.area = Rect::new(40, 40, 40, 40);
let rope = Rope::from_str("Hèl̀l̀ò world!");
- let doc = Document::from(
+ let mut doc = Document::from(
rope,
None,
Arc::new(ArcSwap::new(Arc::new(Config::default()))),
);
+ doc.ensure_view_init(view.id);
assert_eq!(
view.text_pos_at_screen_coords(