on master help sign in
Fix tab rendering to use dynamic tab width

Each tab is just wide enough to round to the nearest tab stop. Refs #1243

commitfd02d1bf8966754624c733790c20bb8431e1eb54 authorBlaž Hrastnik <blaz@mxxn.io> dateFri 4 Mar 2022, 11:01 (5 years ago) parent5f386fa
3 files changed+20−8
helix-core/src/position.rs+1−1 helix-term/src/ui/editor.rs+2−1 helix-view/src/view.rs+17−6
helix-core/src/position.rs+1−1
@@ -83,7 +83,7 @@ pub fn visual_coords_at_pos(text: RopeSlice, pos: usize, tab_width: usize) -> Po
8383
8484 for grapheme in RopeGraphemes::new(text.slice(line_start..pos)) {
8585 if grapheme == "\t" {
86− col += tab_width;
86+ col += tab_width - (col % tab_width);
8787 } else {
8888 let grapheme = Cow::from(grapheme);
8989 col += grapheme_width(&grapheme);
helix-term/src/ui/editor.rs+2−1
@@ -378,7 +378,8 @@ impl EditorView {
378378
379379 let (grapheme, width) = if grapheme == "\t" {
380380 // make sure we display tab as appropriate amount of spaces
381− (tab.as_str(), tab_width)
381+ let visual_tab_width = tab_width - (visual_x as usize % tab_width);
382+ (&tab[..visual_tab_width], visual_tab_width)
382383 } else {
383384 // Cow will prevent allocations if span contained in a single slice
384385 // which should really be the majority case
helix-view/src/view.rs+17−6
@@ -243,18 +243,29 @@ impl View {
243243 let current_line = text.line(line_number);
244244
245245 let target = (column - inner.x) as usize + self.offset.col;
246− let mut selected = 0;
246+ let mut col = 0;
247247
248+ // TODO: extract this part as pos_at_visual_coords
248249 for grapheme in RopeGraphemes::new(current_line) {
249− if selected >= target {
250+ if col >= target {
250251 break;
251252 }
252− if grapheme == "\t" {
253− selected += tab_width;
253+
254+ let width = if grapheme == "\t" {
255+ tab_width - (col % tab_width)
254256 } else {
255− let width = grapheme_width(&Cow::from(grapheme));
256− selected += width;
257+ let grapheme = Cow::from(grapheme);
258+ grapheme_width(&grapheme)
259+ };
260+
261+ // If pos is in the middle of a wider grapheme (tab for example)
262+ // return the starting offset.
263+ if col + width >= target {
264+ break;
257265 }
266+
267+ col += width;
268+ // TODO: use byte pos that converts back to char pos?
258269 pos += grapheme.chars().count();
259270 }
260271