unicode_ellipsis/
width.rs1use unicode_segmentation::UnicodeSegmentation;
4
5#[cfg(feature = "fish")]
6use crate::widecharwidth::char_width;
7
8#[inline]
11pub fn str_width(s: &str) -> usize {
12 UnicodeSegmentation::graphemes(s, true)
13 .map(grapheme_width)
14 .sum()
15}
16
17#[inline]
24pub fn grapheme_width(g: &str) -> usize {
25 if g.contains('\u{200d}') {
26 2
27 } else {
28 #[cfg(feature = "fish")]
29 {
30 use unicode_width::UnicodeWidthChar;
31 g.chars()
32 .map(|c| {
33 if let Some(w) = char_width(c) {
34 w
35 } else {
36 UnicodeWidthChar::width(c).unwrap_or(0)
37 }
38 })
39 .sum()
40 }
41
42 #[cfg(not(feature = "fish"))]
43 {
44 use unicode_width::UnicodeWidthStr;
45 UnicodeWidthStr::width(g)
46 }
47 }
48}
49
50#[cfg(test)]
51mod test {
52 use super::*;
53
54 #[test]
55 fn test_str_width() {
56 assert_eq!(str_width("aaa"), 3);
58 assert_eq!(str_width("a"), 1);
59 assert_eq!(str_width("💎💎"), 4);
60 assert_eq!(str_width("💎"), 2);
61 assert_eq!(str_width("大大"), 4);
62 assert_eq!(str_width("大"), 2);
63 assert_eq!(str_width("🇨🇦🇨🇦"), 4);
64 assert_eq!(str_width("🇨🇦"), 2);
65
66 #[cfg(feature = "fish")]
67 {
68 assert_eq!(str_width("हिन्दी"), 3);
69 assert_eq!(str_width("हि"), 1);
70 }
71
72 #[cfg(not(feature = "fish"))]
73 {
74 assert_eq!(str_width("हिन्दी"), 5);
75 assert_eq!(str_width("हि"), 2);
76 }
77 }
79
80 #[test]
81 fn test_grapheme_width() {
82 assert_eq!(grapheme_width("a"), 1);
84 assert_eq!(grapheme_width("💎"), 2);
85 assert_eq!(grapheme_width("大"), 2);
86 assert_eq!(grapheme_width("🇨🇦"), 2);
87 #[cfg(feature = "fish")]
88 assert_eq!(grapheme_width("हि"), 1);
89 #[cfg(not(feature = "fish"))]
90 assert_eq!(grapheme_width("हि"), 2);
91 }
93}