use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
fn grapheme_width(g: &str) -> usize {
if g == "\t" {
0
} else {
UnicodeWidthStr::width(g)
}
}
pub fn display_width_with_tabs(s: &str, tab_width: usize) -> usize {
let mut col = 0usize;
for g in s.graphemes(true) {
if g == "\t" {
col += tab_width - (col % tab_width);
} else {
col += grapheme_width(g);
}
}
col
}
pub fn display_width(s: &str) -> usize {
display_width_with_tabs(s, 4)
}
pub fn grapheme_to_display_col(line: &str, grapheme_idx: usize, tab_width: usize) -> usize {
let mut col = 0usize;
for (i, g) in line.graphemes(true).enumerate() {
if i == grapheme_idx {
return col;
}
if g == "\t" {
col += tab_width - (col % tab_width);
} else {
col += grapheme_width(g);
}
}
col
}
pub fn display_to_grapheme_col(line: &str, display_col: usize, tab_width: usize) -> usize {
let mut col = 0usize;
for (i, g) in line.graphemes(true).enumerate() {
let w = if g == "\t" {
tab_width - (col % tab_width)
} else {
grapheme_width(g)
};
if display_col < col + w.max(1) {
return i;
}
col += w;
}
line.graphemes(true).count()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct Position {
pub line: usize,
pub col: usize,
}