runefix_core/
ext.rs

1/// Extension trait for measuring the display width of runes, graphemes, and strings.
2///
3/// This trait provides unified access to terminal display width calculations
4/// for both `char` and `&str`. It supports:
5///
6/// - Single runes (`char`)
7/// - Full Unicode strings with grapheme segmentation (`&str`)
8///
9/// All widths are measured in terminal columns, respecting East Asian widths,
10/// emoji sequences, and control characters.
11///
12/// # Examples
13///
14/// ```rust
15/// use runefix_core::RuneDisplayWidth;
16///
17/// assert_eq!('語'.rune_width(), 2);
18/// assert_eq!("你👋a".display_widths(), vec![2, 2, 1]);
19/// assert_eq!("Hi👋".display_width(), 4);
20/// assert_eq!("👋".width(), 2);
21/// ```
22pub trait RuneDisplayWidth {
23    /// Returns the display width of a single rune or grapheme.
24    ///
25    /// For `char`, this is the width of the character.
26    /// For `&str`, this assumes the string is a single grapheme cluster.
27    fn rune_width(&self) -> usize;
28
29    /// Returns the display width of each grapheme cluster in the value.
30    ///
31    /// For `&str`, this segments the string using Unicode grapheme rules.
32    /// For `char`, returns a single-item vector.
33    fn display_widths(&self) -> Vec<usize>;
34
35    /// Returns the total display width in terminal columns.
36    ///
37    /// Equivalent to summing the result of `display_widths()`.
38    fn display_width(&self) -> usize;
39
40    /// Returns the total display width in terminal columns
41    /// (alias of `display_width()`).
42    fn width(&self) -> usize {
43        self.display_width()
44    }
45}
46
47impl RuneDisplayWidth for str {
48    fn rune_width(&self) -> usize {
49        crate::width::get_display_width(self)
50    }
51
52    fn display_widths(&self) -> Vec<usize> {
53        crate::grapheme::display_widths(self)
54    }
55
56    fn display_width(&self) -> usize {
57        crate::grapheme::display_width(self)
58    }
59}
60
61impl RuneDisplayWidth for char {
62    fn rune_width(&self) -> usize {
63        crate::width::get_display_width(&self.to_string())
64    }
65
66    fn display_widths(&self) -> Vec<usize> {
67        vec![self.rune_width()]
68    }
69
70    fn display_width(&self) -> usize {
71        self.rune_width()
72    }
73}