comfy_table/utils/formatting/content_split/
normal.rs

1use unicode_segmentation::UnicodeSegmentation;
2use unicode_width::UnicodeWidthStr;
3
4/// returns printed length of string
5/// if ansi feature enabled, takes into account escape codes
6#[inline(always)]
7pub fn measure_text_width(s: &str) -> usize {
8    s.width()
9}
10
11/// Split a line into its individual parts along the given delimiter.
12pub fn split_line_by_delimiter(line: &str, delimiter: char) -> Vec<String> {
13    line.split(delimiter)
14        .map(ToString::to_string)
15        .collect::<Vec<String>>()
16}
17
18/// Splits a long word at a given character width.
19/// This needs some special logic, as we have to take multi-character UTF-8 symbols into account.
20/// When simply splitting at a certain char position, we might end up with a string that's has a
21/// wider display width than allowed.
22pub fn split_long_word(allowed_width: usize, word: &str) -> (String, String) {
23    let mut current_width = 0;
24    let mut parts = String::new();
25
26    let mut graphmes = word.graphemes(true).peekable();
27
28    // Check if the string might be too long, one Unicode grapheme at a time.
29    // Peek into the next grapheme and check the exit condition.
30    //
31    // This code uses graphemes to handle both zero-width joiner[0] UTF-8 chars, which
32    // combine multiple UTF-8 chars into a single grapheme, and variant selectors [1],
33    // which pick a certain variant of the preceding char.
34    //
35    // [0]: https://en.wikipedia.org/wiki/Zero-width_joiner
36    // [1]: https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block)
37    while let Some(c) = graphmes.peek() {
38        if (current_width + c.width()) > allowed_width {
39            break;
40        }
41
42        // We can unwrap, as we just checked that a suitable grapheme is next in line.
43        let c = graphmes.next().unwrap();
44
45        let character_width = c.width();
46        current_width += character_width;
47        parts.push_str(c);
48    }
49
50    // Collect the remaining characters.
51    let remaining = graphmes.collect();
52    (parts, remaining)
53}