Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-core/src/position.rs')
| -rw-r--r-- | helix-core/src/position.rs | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/helix-core/src/position.rs b/helix-core/src/position.rs index 3719abb0..1b378911 100644 --- a/helix-core/src/position.rs +++ b/helix-core/src/position.rs @@ -415,7 +415,7 @@ 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) { @@ -423,19 +423,23 @@ pub fn char_idx_at_visual_block_offset( 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) @@ -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] @@ -805,6 +810,30 @@ mod test { } #[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"); let slice = text.slice(..); |