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}