Skip to content

Commit

Permalink
fix scrolling/movement for multiline virtual text
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalkuthe committed Apr 2, 2024
1 parent b14b581 commit e86b778
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 13 deletions.
10 changes: 5 additions & 5 deletions helix-core/src/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,19 @@ pub fn move_vertically_visual(
Direction::Backward => -(count as isize),
};

// TODO how to handle inline annotations that span an entire visual line (very unlikely).

// Compute visual offset relative to block start to avoid trasversing the block twice
row_off += visual_pos.row as isize;
let new_pos = char_idx_at_visual_offset(
let (mut new_pos, virtual_rows) = char_idx_at_visual_offset(
slice,
block_off,
row_off,
new_col as usize,
text_fmt,
annotations,
)
.0;
);
if dir == Direction::Forward {
new_pos += (virtual_rows != 0) as usize;
}

// Special-case to avoid moving to the end of the last non-empty line.
if behaviour == Movement::Extend && slice.line(slice.char_to_line(new_pos)).len_chars() == 0 {
Expand Down
45 changes: 37 additions & 8 deletions helix-core/src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,27 +415,31 @@ pub fn char_idx_at_visual_block_offset(
let mut formatter =
DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor);
let mut last_char_idx = formatter.next_char_pos();
let mut last_char_idx_on_line = None;
let mut found_non_virtual_on_row = false;
let mut last_row = 0;
for grapheme in &mut formatter {
match grapheme.visual_pos.row.cmp(&row) {
Ordering::Equal => {
if grapheme.visual_pos.col + grapheme.width() > column {
if !grapheme.is_virtual() {
return (grapheme.char_idx, 0);
} else if let Some(char_idx) = last_char_idx_on_line {
return (char_idx, 0);
} else if found_non_virtual_on_row {
return (last_char_idx, 0);
}
} else if !grapheme.is_virtual() {
last_char_idx_on_line = Some(grapheme.char_idx)
found_non_virtual_on_row = true;
last_char_idx = grapheme.char_idx;
}
}
Ordering::Greater if found_non_virtual_on_row => return (last_char_idx, 0),
Ordering::Greater => return (last_char_idx, row - last_row),
_ => (),
Ordering::Less => {
if !grapheme.is_virtual() {
last_row = grapheme.visual_pos.row;
last_char_idx = grapheme.char_idx;
}
}
}

last_char_idx = grapheme.char_idx;
last_row = grapheme.visual_pos.row;
}

(formatter.next_char_pos(), 0)
Expand All @@ -444,6 +448,7 @@ pub fn char_idx_at_visual_block_offset(
#[cfg(test)]
mod test {
use super::*;
use crate::text_annotations::InlineAnnotation;
use crate::Rope;

#[test]
Expand Down Expand Up @@ -804,6 +809,30 @@ mod test {
assert_eq!(pos_at_visual_coords(slice, (10, 10).into(), 4), 0);
}

#[test]
fn test_char_idx_at_visual_row_offset_inline_annotation() {
let text = Rope::from("foo\nbar");
let slice = text.slice(..);
let mut text_fmt = TextFormat::default();
let annotations = [InlineAnnotation {
text: "x".repeat(100).into(),
char_idx: 3,
}];
text_fmt.soft_wrap = true;

assert_eq!(
char_idx_at_visual_offset(
slice,
0,
1,
0,
&text_fmt,
TextAnnotations::default().add_inline_annotations(&annotations, None)
),
(2, 1)
);
}

#[test]
fn test_char_idx_at_visual_row_offset() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ\nfoo");
Expand Down

0 comments on commit e86b778

Please sign in to comment.