on master help sign in
Refactor view.first_line/first_col into view.offset (Position)
9776553Blaž Hrastnik
helix-term/src/commands.rs+11−11
@@ -118,7 +118,7 @@ fn align_view(doc: &Document, view: &mut View, align: Align) {
118 Align::Bottom => height,
118 Align::Bottom => height,
119 };
119 };
120
120
121− view.first_line = line.saturating_sub(relative);
121+ view.offset.row = line.saturating_sub(relative);
122}
122}
123
123
124/// A command is composed of a static name, and a function that takes the current state plus a count,
124/// 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) {
465 let last_line = view.last_line(doc);
465 let last_line = view.last_line(doc);
466
466
467 let line = match align {
467 let line = match align {
468− Align::Top => (view.first_line + scrolloff),
468+ Align::Top => (view.offset.row + scrolloff),
469− Align::Center => (view.first_line + (height / 2)),
469+ Align::Center => (view.offset.row + (height / 2)),
470 Align::Bottom => last_line.saturating_sub(scrolloff),
470 Align::Bottom => last_line.saturating_sub(scrolloff),
471 }
471 }
472 .min(last_line.saturating_sub(scrolloff));
472 .min(last_line.saturating_sub(scrolloff));
@@ -892,7 +892,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
892
892
893 let last_line = view.last_line(doc);
893 let last_line = view.last_line(doc);
894
894
895− if direction == Backward && view.first_line == 0
895+ if direction == Backward && view.offset.row == 0
896 || direction == Forward && last_line == doc_last_line
896 || direction == Forward && last_line == doc_last_line
897 {
897 {
898 return;
898 return;
@@ -904,9 +904,9 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
904 .scrolloff
904 .scrolloff
905 .min(view.area.height as usize / 2);
905 .min(view.area.height as usize / 2);
906
906
907− view.first_line = match direction {
907+ view.offset.row = match direction {
908− Forward => view.first_line + offset,
908+ Forward => view.offset.row + offset,
909− Backward => view.first_line.saturating_sub(offset),
909+ Backward => view.offset.row.saturating_sub(offset),
910 }
910 }
911 .min(doc_last_line);
911 .min(doc_last_line);
912
912
@@ -916,7 +916,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
916 // clamp into viewport
916 // clamp into viewport
917 let line = cursor
917 let line = cursor
918 .row
918 .row
919− .max(view.first_line + scrolloff)
919+ .max(view.offset.row + scrolloff)
920 .min(last_line.saturating_sub(scrolloff));
920 .min(last_line.saturating_sub(scrolloff));
921
921
922 let text = doc.text().slice(..);
922 let text = doc.text().slice(..);
@@ -4058,13 +4058,13 @@ fn split(cx: &mut Context, action: Action) {
4058 let (view, doc) = current!(cx.editor);
4058 let (view, doc) = current!(cx.editor);
4059 let id = doc.id();
4059 let id = doc.id();
4060 let selection = doc.selection(view.id).clone();
4060 let selection = doc.selection(view.id).clone();
4061− let first_line = view.first_line;
4061+ let offset = view.offset;
4062
4062
4063 cx.editor.switch(id, action);
4063 cx.editor.switch(id, action);
4064
4064
4065 // match the selection in the previous view
4065 // match the selection in the previous view
4066 let (view, doc) = current!(cx.editor);
4066 let (view, doc) = current!(cx.editor);
4067− view.first_line = first_line;
4067+ view.offset = offset;
4068 doc.set_selection(view.id, selection);
4068 doc.set_selection(view.id, selection);
4069}
4069}
4070
4070
@@ -4113,7 +4113,7 @@ fn align_view_middle(cx: &mut Context) {
4113 .cursor(doc.text().slice(..));
4113 .cursor(doc.text().slice(..));
4114 let pos = coords_at_pos(doc.text().slice(..), pos);
4114 let pos = coords_at_pos(doc.text().slice(..), pos);
4115
4115
4116− view.first_col = pos.col.saturating_sub(
4116+ view.offset.col = pos.col.saturating_sub(
4117 ((view.area.width as usize).saturating_sub(crate::ui::editor::GUTTER_OFFSET as usize)) / 2,
4117 ((view.area.width as usize).saturating_sub(crate::ui::editor::GUTTER_OFFSET as usize)) / 2,
4118 );
4118 );
4119}
4119}
helix-term/src/ui/completion.rs+1−1
@@ -261,7 +261,7 @@ impl Component for Completion {
261 .primary()
261 .primary()
262 .cursor(doc.text().slice(..));
262 .cursor(doc.text().slice(..));
263 let cursor_pos = (helix_core::coords_at_pos(doc.text().slice(..), cursor_pos).row
263 let cursor_pos = (helix_core::coords_at_pos(doc.text().slice(..), cursor_pos).row
264− - view.first_line) as u16;
264+ - view.offset.row) as u16;
265
265
266 let mut doc = match &option.documentation {
266 let mut doc = match &option.documentation {
267 Some(lsp::Documentation::String(contents))
267 Some(lsp::Documentation::String(contents))
helix-term/src/ui/editor.rs+7−8
@@ -80,10 +80,9 @@ impl EditorView {
80 view.area.width - GUTTER_OFFSET,
80 view.area.width - GUTTER_OFFSET,
81 view.area.height.saturating_sub(1),
81 view.area.height.saturating_sub(1),
82 ); // - 1 for statusline
82 ); // - 1 for statusline
83− let offset = Position::new(view.first_line, view.first_col);
84 let height = view.area.height.saturating_sub(1); // - 1 for statusline
83 let height = view.area.height.saturating_sub(1); // - 1 for statusline
85
84
86− let highlights = Self::doc_syntax_highlights(doc, offset, height, theme, loader);
85+ let highlights = Self::doc_syntax_highlights(doc, view.offset, height, theme, loader);
87 let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme));
86 let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme));
88 let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
87 let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
89 Box::new(syntax::merge(
88 Box::new(syntax::merge(
@@ -94,7 +93,7 @@ impl EditorView {
94 Box::new(highlights)
93 Box::new(highlights)
95 };
94 };
96
95
97− Self::render_text_highlights(doc, offset, area, surface, theme, highlights);
96+ Self::render_text_highlights(doc, view.offset, area, surface, theme, highlights);
98 Self::render_gutter(doc, view, area, surface, theme, config);
97 Self::render_gutter(doc, view, area, surface, theme, config);
99
98
100 if is_focused {
99 if is_focused {
@@ -382,7 +381,7 @@ impl EditorView {
382 let selection = doc.selection(view.id);
381 let selection = doc.selection(view.id);
383 let last_line = view.last_line(doc);
382 let last_line = view.last_line(doc);
384 let screen = {
383 let screen = {
385− let start = text.line_to_char(view.first_line);
384+ let start = text.line_to_char(view.offset.row);
386 let end = text.line_to_char(last_line + 1) + 1; // +1 for cursor at end of text.
385 let end = text.line_to_char(last_line + 1) + 1; // +1 for cursor at end of text.
387 Range::new(start, end)
386 Range::new(start, end)
388 };
387 };
@@ -408,7 +407,7 @@ impl EditorView {
408 );
407 );
409 if let Some(head) = head {
408 if let Some(head) = head {
410 // Highlight line number for selected lines.
409 // Highlight line number for selected lines.
411− let line_number = view.first_line + head.row;
410+ let line_number = view.offset.row + head.row;
412 let line_number_text = if line_number == last_line && !draw_last {
411 let line_number_text = if line_number == last_line && !draw_last {
413 " ~".into()
412 " ~".into()
414 } else {
413 } else {
@@ -435,8 +434,8 @@ impl EditorView {
435
434
436 if let Some(pos) = pos {
435 if let Some(pos) = pos {
437 // ensure col is on screen
436 // ensure col is on screen
438− if (pos.col as u16) < viewport.width + view.first_col as u16
437+ if (pos.col as u16) < viewport.width + view.offset.col as u16
439− && pos.col >= view.first_col
438+ && pos.col >= view.offset.col
440 {
439 {
441 let style = theme.try_get("ui.cursor.match").unwrap_or_else(|| {
440 let style = theme.try_get("ui.cursor.match").unwrap_or_else(|| {
442 Style::default()
441 Style::default()
@@ -479,7 +478,7 @@ impl EditorView {
479 let current_line = doc
478 let current_line = doc
480 .text()
479 .text()
481 .char_to_line(doc.selection(view.id).primary().anchor);
480 .char_to_line(doc.selection(view.id).primary().anchor);
482− for (i, line) in (view.first_line..(last_line + 1)).enumerate() {
481+ for (i, line) in (view.offset.row..(last_line + 1)).enumerate() {
483 use helix_core::diagnostic::Severity;
482 use helix_core::diagnostic::Severity;
484 if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) {
483 if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) {
485 surface.set_stringn(
484 surface.set_stringn(
helix-view/src/editor.rs+2−2
@@ -180,7 +180,7 @@ impl Editor {
180 view.jumps.push(jump);
180 view.jumps.push(jump);
181 view.last_accessed_doc = Some(view.doc);
181 view.last_accessed_doc = Some(view.doc);
182 view.doc = id;
182 view.doc = id;
183− view.first_line = 0;
183+ view.offset = Position::default();
184
184
185 let (view, doc) = current!(self);
185 let (view, doc) = current!(self);
186
186
@@ -194,7 +194,7 @@ impl Editor {
194 .primary()
194 .primary()
195 .cursor(doc.text().slice(..));
195 .cursor(doc.text().slice(..));
196 let line = doc.text().char_to_line(pos);
196 let line = doc.text().char_to_line(pos);
197− view.first_line = line.saturating_sub(view.area.height as usize / 2);
197+ view.offset.row = line.saturating_sub(view.area.height as usize / 2);
198
198
199 return;
199 return;
200 }
200 }
helix-view/src/view.rs+16−18
@@ -61,8 +61,7 @@ impl JumpList {
61pub struct View {
61pub struct View {
62 pub id: ViewId,
62 pub id: ViewId,
63 pub doc: DocumentId,
63 pub doc: DocumentId,
64− pub first_line: usize,
64+ pub offset: Position,
65− pub first_col: usize,
66 pub area: Rect,
65 pub area: Rect,
67 pub jumps: JumpList,
66 pub jumps: JumpList,
68 /// the last accessed file before the current one
67 /// the last accessed file before the current one
@@ -74,8 +73,7 @@ impl View {
74 Self {
73 Self {
75 id: ViewId::default(),
74 id: ViewId::default(),
76 doc,
75 doc,
77− first_line: 0,
76+ offset: Position::new(0, 0),
78− first_col: 0,
79 area: Rect::default(), // will get calculated upon inserting into tree
77 area: Rect::default(), // will get calculated upon inserting into tree
80 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
78 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
81 last_accessed_doc: None,
79 last_accessed_doc: None,
@@ -91,7 +89,7 @@ impl View {
91 let line = pos.row;
89 let line = pos.row;
92 let col = pos.col;
90 let col = pos.col;
93 let height = self.area.height.saturating_sub(1); // - 1 for statusline
91 let height = self.area.height.saturating_sub(1); // - 1 for statusline
94− let last_line = (self.first_line + height as usize).saturating_sub(1);
92+ let last_line = (self.offset.row + height as usize).saturating_sub(1);
95
93
96 // - 1 so we have at least one gap in the middle.
94 // - 1 so we have at least one gap in the middle.
97 // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
95 // 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 {
100
98
101 // TODO: not ideal
99 // TODO: not ideal
102 const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
100 const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
103− let last_col = (self.first_col + self.area.width as usize).saturating_sub(OFFSET + 1);
101+ let last_col = (self.offset.col + self.area.width as usize).saturating_sub(OFFSET + 1);
104
102
105 if line > last_line.saturating_sub(scrolloff) {
103 if line > last_line.saturating_sub(scrolloff) {
106 // scroll down
104 // scroll down
107− self.first_line += line - (last_line.saturating_sub(scrolloff));
105+ self.offset.row += line - (last_line.saturating_sub(scrolloff));
108− } else if line < self.first_line + scrolloff {
106+ } else if line < self.offset.row + scrolloff {
109 // scroll up
107 // scroll up
110− self.first_line = line.saturating_sub(scrolloff);
108+ self.offset.row = line.saturating_sub(scrolloff);
111 }
109 }
112
110
113 if col > last_col.saturating_sub(scrolloff) {
111 if col > last_col.saturating_sub(scrolloff) {
114 // scroll right
112 // scroll right
115− self.first_col += col - (last_col.saturating_sub(scrolloff));
113+ self.offset.col += col - (last_col.saturating_sub(scrolloff));
116− } else if col < self.first_col + scrolloff {
114+ } else if col < self.offset.col + scrolloff {
117 // scroll left
115 // scroll left
118− self.first_col = col.saturating_sub(scrolloff);
116+ self.offset.col = col.saturating_sub(scrolloff);
119 }
117 }
120 }
118 }
121
119
@@ -125,7 +123,7 @@ impl View {
125 let height = self.area.height.saturating_sub(1); // - 1 for statusline
123 let height = self.area.height.saturating_sub(1); // - 1 for statusline
126 std::cmp::min(
124 std::cmp::min(
127 // Saturating subs to make it inclusive zero indexing.
125 // Saturating subs to make it inclusive zero indexing.
128− (self.first_line + height as usize).saturating_sub(1),
126+ (self.offset.row + height as usize).saturating_sub(1),
129 doc.text().len_lines().saturating_sub(1),
127 doc.text().len_lines().saturating_sub(1),
130 )
128 )
131 }
129 }
@@ -141,7 +139,7 @@ impl View {
141 ) -> Option<Position> {
139 ) -> Option<Position> {
142 let line = text.char_to_line(pos);
140 let line = text.char_to_line(pos);
143
141
144− if line < self.first_line || line > self.last_line(doc) {
142+ if line < self.offset.row || line > self.last_line(doc) {
145 // Line is not visible on screen
143 // Line is not visible on screen
146 return None;
144 return None;
147 }
145 }
@@ -161,8 +159,8 @@ impl View {
161 }
159 }
162
160
163 // It is possible for underflow to occur if the buffer length is larger than the terminal width.
161 // It is possible for underflow to occur if the buffer length is larger than the terminal width.
164− let row = line.saturating_sub(self.first_line);
162+ let row = line.saturating_sub(self.offset.row);
165− let col = col.saturating_sub(self.first_col);
163+ let col = col.saturating_sub(self.offset.col);
166
164
167 Some(Position::new(row, col))
165 Some(Position::new(row, col))
168 }
166 }
@@ -186,7 +184,7 @@ impl View {
186 return None;
184 return None;
187 }
185 }
188
186
189− let line_number = (row - self.area.y) as usize + self.first_line;
187+ let line_number = (row - self.area.y) as usize + self.offset.row;
190
188
191 if line_number > text.len_lines() - 1 {
189 if line_number > text.len_lines() - 1 {
192 return Some(text.len_chars());
190 return Some(text.len_chars());
@@ -196,7 +194,7 @@ impl View {
196
194
197 let current_line = text.line(line_number);
195 let current_line = text.line(line_number);
198
196
199− let target = (column - OFFSET - self.area.x) as usize + self.first_col;
197+ let target = (column - OFFSET - self.area.x) as usize + self.offset.col;
200 let mut selected = 0;
198 let mut selected = 0;
201
199
202 for grapheme in RopeGraphemes::new(current_line) {
200 for grapheme in RopeGraphemes::new(current_line) {