diff --git a/helix-core/src/position.rs b/helix-core/src/position.rs index 93362c77..17908d7a 100644 --- a/helix-core/src/position.rs +++ b/helix-core/src/position.rs @@ -1,8 +1,9 @@ +use std::borrow::Cow; + use crate::{ chars::char_is_line_ending, - graphemes::{ensure_grapheme_boundary_prev, RopeGraphemes}, + graphemes::{ensure_grapheme_boundary_prev, grapheme_width, RopeGraphemes}, line_ending::line_end_char_index, - unicode::width::UnicodeWidthChar, RopeSlice, }; @@ -77,14 +78,17 @@ pub fn visual_coords_at_pos(text: RopeSlice, pos: usize, tab_width: usize) -> Po let line_start = text.line_to_char(line); let pos = ensure_grapheme_boundary_prev(text, pos); - let col = text - .slice(line_start..pos) - .chars() - .flat_map(|c| match c { - '\t' => Some(tab_width), - c => UnicodeWidthChar::width(c), - }) - .sum(); + + let mut col = 0; + + for grapheme in RopeGraphemes::new(text.slice(line_start..pos)) { + if grapheme == "\t" { + col += tab_width; + } else { + let grapheme = Cow::from(grapheme); + col += grapheme_width(&grapheme); + } + } Position::new(line, col) } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 39a8df53..8ee05ece 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1551,6 +1551,7 @@ fn search_impl( }; doc.set_selection(view.id, selection); + // TODO: is_cursor_in_view does the same calculation as ensure_cursor_in_view if view.is_cursor_in_view(doc, 0) { view.ensure_cursor_in_view(doc, scrolloff); } else { diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 6bc9435c..58a9b602 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -204,19 +204,9 @@ impl View { return None; } - let line_start = text.line_to_char(line); - let line_slice = text.slice(line_start..pos); - let mut col = 0; let tab_width = doc.tab_width(); - - for grapheme in RopeGraphemes::new(line_slice) { - if grapheme == "\t" { - col += tab_width; - } else { - let grapheme = Cow::from(grapheme); - col += grapheme_width(&grapheme); - } - } + // TODO: visual_coords_at_pos also does char_to_line which we ignore, can we reuse the call? + let Position { col, .. } = visual_coords_at_pos(text, pos, tab_width); // It is possible for underflow to occur if the buffer length is larger than the terminal width. let row = line.saturating_sub(self.offset.row);