@@ -7,9 +7,13 @@ use crate::{
9use helix_core::{
9use helix_core::{
10− char_idx_at_visual_offset, doc_formatter::TextFormat, syntax::Highlight,
10+ char_idx_at_visual_offset,
11+ doc_formatter::TextFormat,
13+ text_annotations::TextAnnotations,
11− text_annotations::TextAnnotations, visual_offset_from_anchor, visual_offset_from_block,
14+ visual_offset_from_anchor, visual_offset_from_block, Position, RopeSlice, Selection,
12− Position, RopeSlice, Selection, Transaction,
15+ Transaction,
16+ VisualOffsetError::{PosAfterMaxRow, PosBeforeAnchorRow},
@@ -213,46 +217,38 @@ impl View {
213 // - 1 so we have at least one gap in the middle.
217 // - 1 so we have at least one gap in the middle.
214 // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
218 // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
215 // as we type
219 // as we type
220+ let scrolloff = if CENTERING {
216− let scrolloff = scrolloff.min(viewport.height.saturating_sub(1) as usize / 2);
223+ scrolloff.min(viewport.height.saturating_sub(1) as usize / 2)
218 let cursor = doc.selection(self.id).primary().cursor(doc_text);
226 let cursor = doc.selection(self.id).primary().cursor(doc_text);
219 let mut offset = self.offset;
227 let mut offset = self.offset;
228+ let off = visual_offset_from_anchor(
234+ vertical_viewport_end,
221− let (visual_off, mut at_top) = if cursor >= offset.anchor {
237+ let (new_anchor, at_top) = match off {
222− let off = visual_offset_from_anchor(
228− vertical_viewport_end,
231− } else if CENTERING {
232− // cursor out of view
238− let new_anchor = match visual_off {
239− Some((visual_pos, _)) if visual_pos.row < scrolloff + offset.vertical_offset => {
238+ Ok((visual_pos, _)) if visual_pos.row < scrolloff + offset.vertical_offset => {
240− if CENTERING && visual_pos.row < offset.vertical_offset {
239+ if CENTERING {
241 // cursor out of view
240 // cursor out of view
242 return None;
241 return None;
245− true
243+ (true, true)
247− Some((visual_pos, _)) if visual_pos.row + scrolloff + 1 >= vertical_viewport_end => {
245+ Ok((visual_pos, _)) if visual_pos.row + scrolloff >= vertical_viewport_end => {
248− if CENTERING && visual_pos.row >= vertical_viewport_end {
249− // cursor out of view
252− true
246+ (true, false)
254− Some(_) => false,
248+ Ok((_, _)) => (false, false),
255− None => true,
249+ Err(_) if CENTERING => return None,
250+ Err(PosBeforeAnchorRow) => (true, true),
251+ Err(PosAfterMaxRow) => (true, false),
258 if new_anchor {
254 if new_anchor {
@@ -269,8 +265,8 @@ impl View {
269 offset.horizontal_offset = 0;
265 offset.horizontal_offset = 0;
271 // determine the current visual column of the text
267 // determine the current visual column of the text
272− let col = visual_off
268+ let col = off
273− .unwrap_or_else(|| {
269+ .unwrap_or_else(|_| {
274 visual_offset_from_block(
270 visual_offset_from_block(
275 doc_text,
271 doc_text,
276 offset.anchor,
272 offset.anchor,
@@ -360,8 +356,9 @@ impl View {
362 match pos {
358 match pos {
363− Some((Position { row, .. }, _)) => row.saturating_sub(self.offset.vertical_offset),
359+ Ok((Position { row, .. }, _)) => row.saturating_sub(self.offset.vertical_offset),
364− None => visual_height.saturating_sub(1),
360+ Err(PosAfterMaxRow) => visual_height.saturating_sub(1),
361+ Err(PosBeforeAnchorRow) => 0,
@@ -390,7 +387,8 @@ impl View {
390 &text_fmt,
387 &text_fmt,
391 &annotations,
388 &annotations,
392 viewport.height as usize,
389 viewport.height as usize,
395 if pos.row < self.offset.vertical_offset {
393 if pos.row < self.offset.vertical_offset {
396 return None;
394 return None;