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.rs45
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(..);