Refactor view.first_line/first_col into view.offset (Position)

pull/624/head
Blaž Hrastnik 3 years ago
parent 115754c5ee
commit 9776553ad0

@ -118,7 +118,7 @@ fn align_view(doc: &Document, view: &mut View, align: Align) {
Align::Bottom => height, Align::Bottom => height,
}; };
view.first_line = line.saturating_sub(relative); view.offset.row = line.saturating_sub(relative);
} }
/// A command is composed of a static name, and a function that takes the current state plus a count, /// A command is composed of a static name, and a function that takes the current state plus a count,
@ -465,8 +465,8 @@ fn goto_window(cx: &mut Context, align: Align) {
let last_line = view.last_line(doc); let last_line = view.last_line(doc);
let line = match align { let line = match align {
Align::Top => (view.first_line + scrolloff), Align::Top => (view.offset.row + scrolloff),
Align::Center => (view.first_line + (height / 2)), Align::Center => (view.offset.row + (height / 2)),
Align::Bottom => last_line.saturating_sub(scrolloff), Align::Bottom => last_line.saturating_sub(scrolloff),
} }
.min(last_line.saturating_sub(scrolloff)); .min(last_line.saturating_sub(scrolloff));
@ -892,7 +892,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
let last_line = view.last_line(doc); let last_line = view.last_line(doc);
if direction == Backward && view.first_line == 0 if direction == Backward && view.offset.row == 0
|| direction == Forward && last_line == doc_last_line || direction == Forward && last_line == doc_last_line
{ {
return; return;
@ -904,9 +904,9 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
.scrolloff .scrolloff
.min(view.area.height as usize / 2); .min(view.area.height as usize / 2);
view.first_line = match direction { view.offset.row = match direction {
Forward => view.first_line + offset, Forward => view.offset.row + offset,
Backward => view.first_line.saturating_sub(offset), Backward => view.offset.row.saturating_sub(offset),
} }
.min(doc_last_line); .min(doc_last_line);
@ -916,7 +916,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
// clamp into viewport // clamp into viewport
let line = cursor let line = cursor
.row .row
.max(view.first_line + scrolloff) .max(view.offset.row + scrolloff)
.min(last_line.saturating_sub(scrolloff)); .min(last_line.saturating_sub(scrolloff));
let text = doc.text().slice(..); let text = doc.text().slice(..);
@ -4058,13 +4058,13 @@ fn split(cx: &mut Context, action: Action) {
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
let id = doc.id(); let id = doc.id();
let selection = doc.selection(view.id).clone(); let selection = doc.selection(view.id).clone();
let first_line = view.first_line; let offset = view.offset;
cx.editor.switch(id, action); cx.editor.switch(id, action);
// match the selection in the previous view // match the selection in the previous view
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
view.first_line = first_line; view.offset = offset;
doc.set_selection(view.id, selection); doc.set_selection(view.id, selection);
} }
@ -4113,7 +4113,7 @@ fn align_view_middle(cx: &mut Context) {
.cursor(doc.text().slice(..)); .cursor(doc.text().slice(..));
let pos = coords_at_pos(doc.text().slice(..), pos); let pos = coords_at_pos(doc.text().slice(..), pos);
view.first_col = pos.col.saturating_sub( view.offset.col = pos.col.saturating_sub(
((view.area.width as usize).saturating_sub(crate::ui::editor::GUTTER_OFFSET as usize)) / 2, ((view.area.width as usize).saturating_sub(crate::ui::editor::GUTTER_OFFSET as usize)) / 2,
); );
} }

@ -261,7 +261,7 @@ impl Component for Completion {
.primary() .primary()
.cursor(doc.text().slice(..)); .cursor(doc.text().slice(..));
let cursor_pos = (helix_core::coords_at_pos(doc.text().slice(..), cursor_pos).row let cursor_pos = (helix_core::coords_at_pos(doc.text().slice(..), cursor_pos).row
- view.first_line) as u16; - view.offset.row) as u16;
let mut doc = match &option.documentation { let mut doc = match &option.documentation {
Some(lsp::Documentation::String(contents)) Some(lsp::Documentation::String(contents))

@ -80,10 +80,9 @@ impl EditorView {
view.area.width - GUTTER_OFFSET, view.area.width - GUTTER_OFFSET,
view.area.height.saturating_sub(1), view.area.height.saturating_sub(1),
); // - 1 for statusline ); // - 1 for statusline
let offset = Position::new(view.first_line, view.first_col);
let height = view.area.height.saturating_sub(1); // - 1 for statusline let height = view.area.height.saturating_sub(1); // - 1 for statusline
let highlights = Self::doc_syntax_highlights(doc, offset, height, theme, loader); let highlights = Self::doc_syntax_highlights(doc, view.offset, height, theme, loader);
let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme)); let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme));
let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused { let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
Box::new(syntax::merge( Box::new(syntax::merge(
@ -94,7 +93,7 @@ impl EditorView {
Box::new(highlights) Box::new(highlights)
}; };
Self::render_text_highlights(doc, offset, area, surface, theme, highlights); Self::render_text_highlights(doc, view.offset, area, surface, theme, highlights);
Self::render_gutter(doc, view, area, surface, theme, config); Self::render_gutter(doc, view, area, surface, theme, config);
if is_focused { if is_focused {
@ -382,7 +381,7 @@ impl EditorView {
let selection = doc.selection(view.id); let selection = doc.selection(view.id);
let last_line = view.last_line(doc); let last_line = view.last_line(doc);
let screen = { let screen = {
let start = text.line_to_char(view.first_line); let start = text.line_to_char(view.offset.row);
let end = text.line_to_char(last_line + 1) + 1; // +1 for cursor at end of text. let end = text.line_to_char(last_line + 1) + 1; // +1 for cursor at end of text.
Range::new(start, end) Range::new(start, end)
}; };
@ -408,7 +407,7 @@ impl EditorView {
); );
if let Some(head) = head { if let Some(head) = head {
// Highlight line number for selected lines. // Highlight line number for selected lines.
let line_number = view.first_line + head.row; let line_number = view.offset.row + head.row;
let line_number_text = if line_number == last_line && !draw_last { let line_number_text = if line_number == last_line && !draw_last {
" ~".into() " ~".into()
} else { } else {
@ -435,8 +434,8 @@ impl EditorView {
if let Some(pos) = pos { if let Some(pos) = pos {
// ensure col is on screen // ensure col is on screen
if (pos.col as u16) < viewport.width + view.first_col as u16 if (pos.col as u16) < viewport.width + view.offset.col as u16
&& pos.col >= view.first_col && pos.col >= view.offset.col
{ {
let style = theme.try_get("ui.cursor.match").unwrap_or_else(|| { let style = theme.try_get("ui.cursor.match").unwrap_or_else(|| {
Style::default() Style::default()
@ -479,7 +478,7 @@ impl EditorView {
let current_line = doc let current_line = doc
.text() .text()
.char_to_line(doc.selection(view.id).primary().anchor); .char_to_line(doc.selection(view.id).primary().anchor);
for (i, line) in (view.first_line..(last_line + 1)).enumerate() { for (i, line) in (view.offset.row..(last_line + 1)).enumerate() {
use helix_core::diagnostic::Severity; use helix_core::diagnostic::Severity;
if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) { if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) {
surface.set_stringn( surface.set_stringn(

@ -180,7 +180,7 @@ impl Editor {
view.jumps.push(jump); view.jumps.push(jump);
view.last_accessed_doc = Some(view.doc); view.last_accessed_doc = Some(view.doc);
view.doc = id; view.doc = id;
view.first_line = 0; view.offset = Position::default();
let (view, doc) = current!(self); let (view, doc) = current!(self);
@ -194,7 +194,7 @@ impl Editor {
.primary() .primary()
.cursor(doc.text().slice(..)); .cursor(doc.text().slice(..));
let line = doc.text().char_to_line(pos); let line = doc.text().char_to_line(pos);
view.first_line = line.saturating_sub(view.area.height as usize / 2); view.offset.row = line.saturating_sub(view.area.height as usize / 2);
return; return;
} }

@ -61,8 +61,7 @@ impl JumpList {
pub struct View { pub struct View {
pub id: ViewId, pub id: ViewId,
pub doc: DocumentId, pub doc: DocumentId,
pub first_line: usize, pub offset: Position,
pub first_col: usize,
pub area: Rect, pub area: Rect,
pub jumps: JumpList, pub jumps: JumpList,
/// the last accessed file before the current one /// the last accessed file before the current one
@ -74,8 +73,7 @@ impl View {
Self { Self {
id: ViewId::default(), id: ViewId::default(),
doc, doc,
first_line: 0, offset: Position::new(0, 0),
first_col: 0,
area: Rect::default(), // will get calculated upon inserting into tree area: Rect::default(), // will get calculated upon inserting into tree
jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
last_accessed_doc: None, last_accessed_doc: None,
@ -91,7 +89,7 @@ impl View {
let line = pos.row; let line = pos.row;
let col = pos.col; let col = pos.col;
let height = self.area.height.saturating_sub(1); // - 1 for statusline let height = self.area.height.saturating_sub(1); // - 1 for statusline
let last_line = (self.first_line + height as usize).saturating_sub(1); let last_line = (self.offset.row + height as usize).saturating_sub(1);
// - 1 so we have at least one gap in the middle. // - 1 so we have at least one gap in the middle.
// a height of 6 with padding of 3 on each side will keep shifting the view back and forth // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
@ -100,22 +98,22 @@ impl View {
// TODO: not ideal // TODO: not ideal
const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
let last_col = (self.first_col + self.area.width as usize).saturating_sub(OFFSET + 1); let last_col = (self.offset.col + self.area.width as usize).saturating_sub(OFFSET + 1);
if line > last_line.saturating_sub(scrolloff) { if line > last_line.saturating_sub(scrolloff) {
// scroll down // scroll down
self.first_line += line - (last_line.saturating_sub(scrolloff)); self.offset.row += line - (last_line.saturating_sub(scrolloff));
} else if line < self.first_line + scrolloff { } else if line < self.offset.row + scrolloff {
// scroll up // scroll up
self.first_line = line.saturating_sub(scrolloff); self.offset.row = line.saturating_sub(scrolloff);
} }
if col > last_col.saturating_sub(scrolloff) { if col > last_col.saturating_sub(scrolloff) {
// scroll right // scroll right
self.first_col += col - (last_col.saturating_sub(scrolloff)); self.offset.col += col - (last_col.saturating_sub(scrolloff));
} else if col < self.first_col + scrolloff { } else if col < self.offset.col + scrolloff {
// scroll left // scroll left
self.first_col = col.saturating_sub(scrolloff); self.offset.col = col.saturating_sub(scrolloff);
} }
} }
@ -125,7 +123,7 @@ impl View {
let height = self.area.height.saturating_sub(1); // - 1 for statusline let height = self.area.height.saturating_sub(1); // - 1 for statusline
std::cmp::min( std::cmp::min(
// Saturating subs to make it inclusive zero indexing. // Saturating subs to make it inclusive zero indexing.
(self.first_line + height as usize).saturating_sub(1), (self.offset.row + height as usize).saturating_sub(1),
doc.text().len_lines().saturating_sub(1), doc.text().len_lines().saturating_sub(1),
) )
} }
@ -141,7 +139,7 @@ impl View {
) -> Option<Position> { ) -> Option<Position> {
let line = text.char_to_line(pos); let line = text.char_to_line(pos);
if line < self.first_line || line > self.last_line(doc) { if line < self.offset.row || line > self.last_line(doc) {
// Line is not visible on screen // Line is not visible on screen
return None; return None;
} }
@ -161,8 +159,8 @@ impl View {
} }
// It is possible for underflow to occur if the buffer length is larger than the terminal width. // It is possible for underflow to occur if the buffer length is larger than the terminal width.
let row = line.saturating_sub(self.first_line); let row = line.saturating_sub(self.offset.row);
let col = col.saturating_sub(self.first_col); let col = col.saturating_sub(self.offset.col);
Some(Position::new(row, col)) Some(Position::new(row, col))
} }
@ -186,7 +184,7 @@ impl View {
return None; return None;
} }
let line_number = (row - self.area.y) as usize + self.first_line; let line_number = (row - self.area.y) as usize + self.offset.row;
if line_number > text.len_lines() - 1 { if line_number > text.len_lines() - 1 {
return Some(text.len_chars()); return Some(text.len_chars());
@ -196,7 +194,7 @@ impl View {
let current_line = text.line(line_number); let current_line = text.line(line_number);
let target = (column - OFFSET - self.area.x) as usize + self.first_col; let target = (column - OFFSET - self.area.x) as usize + self.offset.col;
let mut selected = 0; let mut selected = 0;
for grapheme in RopeGraphemes::new(current_line) { for grapheme in RopeGraphemes::new(current_line) {

Loading…
Cancel
Save