diff options
author | Blaž Hrastnik | 2022-03-04 02:01:33 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2022-03-04 02:01:33 +0000 |
commit | fd02d1bf8966754624c733790c20bb8431e1eb54 (patch) | |
tree | d0f4480f9190f8048d70acceca1711cc2e999a34 | |
parent | 5f386fa355d2f3e95a890c2d63d95b05ddca23a4 (diff) |
Fix tab rendering to use dynamic tab width
Each tab is just wide enough to round to the nearest tab stop.
Refs #1243
-rw-r--r-- | helix-core/src/position.rs | 2 | ||||
-rw-r--r-- | helix-term/src/ui/editor.rs | 3 | ||||
-rw-r--r-- | helix-view/src/view.rs | 23 |
3 files changed, 20 insertions, 8 deletions
diff --git a/helix-core/src/position.rs b/helix-core/src/position.rs index 17908d7a..ce37300a 100644 --- a/helix-core/src/position.rs +++ b/helix-core/src/position.rs @@ -83,7 +83,7 @@ pub fn visual_coords_at_pos(text: RopeSlice, pos: usize, tab_width: usize) -> Po for grapheme in RopeGraphemes::new(text.slice(line_start..pos)) { if grapheme == "\t" { - col += tab_width; + col += tab_width - (col % tab_width); } else { let grapheme = Cow::from(grapheme); col += grapheme_width(&grapheme); diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index f9c5e55e..31a9bfc8 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -378,7 +378,8 @@ impl EditorView { let (grapheme, width) = if grapheme == "\t" { // make sure we display tab as appropriate amount of spaces - (tab.as_str(), tab_width) + let visual_tab_width = tab_width - (visual_x as usize % tab_width); + (&tab[..visual_tab_width], visual_tab_width) } else { // Cow will prevent allocations if span contained in a single slice // which should really be the majority case diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 58a9b602..b427a8d4 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -243,18 +243,29 @@ impl View { let current_line = text.line(line_number); let target = (column - inner.x) as usize + self.offset.col; - let mut selected = 0; + let mut col = 0; + // TODO: extract this part as pos_at_visual_coords for grapheme in RopeGraphemes::new(current_line) { - if selected >= target { + if col >= target { break; } - if grapheme == "\t" { - selected += tab_width; + + let width = if grapheme == "\t" { + tab_width - (col % tab_width) } else { - let width = grapheme_width(&Cow::from(grapheme)); - selected += width; + let grapheme = Cow::from(grapheme); + grapheme_width(&grapheme) + }; + + // If pos is in the middle of a wider grapheme (tab for example) + // return the starting offset. + if col + width >= target { + break; } + + col += width; + // TODO: use byte pos that converts back to char pos? pos += grapheme.chars().count(); } |