diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index f23802616ac4d..6a624ded28362 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -85,7 +85,12 @@ impl View { self.area.clip_left(OFFSET).clip_bottom(1) // -1 for statusline } - pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) { + // + pub fn offset_coords_to_in_view( + &self, + doc: &Document, + scrolloff: usize, + ) -> Option<(usize, usize)> { let cursor = doc .selection(self.id) .primary() @@ -104,50 +109,41 @@ impl View { let last_col = self.offset.col + inner_area.width.saturating_sub(1) as usize; - if line > last_line.saturating_sub(scrolloff) { + let row = if line > last_line.saturating_sub(scrolloff) { // scroll down - self.offset.row += line - (last_line.saturating_sub(scrolloff)); + self.offset.row + line - (last_line.saturating_sub(scrolloff)) } else if line < self.offset.row + scrolloff { // scroll up - self.offset.row = line.saturating_sub(scrolloff); - } + line.saturating_sub(scrolloff) + } else { + self.offset.row + }; - if col > last_col.saturating_sub(scrolloff) { + let col = if col > last_col.saturating_sub(scrolloff) { // scroll right - self.offset.col += col - (last_col.saturating_sub(scrolloff)); + self.offset.col + col - (last_col.saturating_sub(scrolloff)) } else if col < self.offset.col + scrolloff { // scroll left - self.offset.col = col.saturating_sub(scrolloff); + col.saturating_sub(scrolloff) + } else { + self.offset.col + }; + if row == self.offset.row && col == self.offset.col { + None + } else { + Some((row, col)) } } - pub fn is_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) -> bool { - let cursor = doc - .selection(self.id) - .primary() - .cursor(doc.text().slice(..)); - - let Position { col, row: line } = - visual_coords_at_pos(doc.text().slice(..), cursor, doc.tab_width()); - - let inner_area = self.inner_area(); - let last_line = (self.offset.row + inner_area.height as usize).saturating_sub(1); - - // - 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 - // as we type - let scrolloff = scrolloff.min(inner_area.height.saturating_sub(1) as usize / 2); - - let last_col = self.offset.col + inner_area.width.saturating_sub(1) as usize; - - if (line > last_line.saturating_sub(scrolloff)) || (line < self.offset.row + scrolloff) { - return false; + pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) { + if let Some((row, col)) = self.offset_coords_to_in_view(doc, scrolloff) { + self.offset.row = row; + self.offset.col = col; } + } - if (col > last_col.saturating_sub(scrolloff)) || (col < self.offset.col + scrolloff) { - return false; - } - true + pub fn is_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) -> bool { + self.offset_coords_to_in_view(doc, scrolloff).is_none() } /// Calculates the last visible line on screen