1use unicode_width::UnicodeWidthStr;
4
5pub fn truncate(s: &str, max_width: usize) -> String {
7 if s.width() <= max_width {
8 return s.to_string();
9 }
10
11 let mut width = 0;
12 let mut result = String::new();
13
14 for c in s.chars() {
15 let char_width = unicode_width::UnicodeWidthChar::width(c).unwrap_or(0);
16 if width + char_width + 1 > max_width {
17 result.push('…');
18 break;
19 }
20 result.push(c);
21 width += char_width;
22 }
23
24 result
25}
26
27pub fn format_number(n: u64) -> String {
29 if n >= 1_000_000 {
30 format!("{:.1}M", n as f64 / 1_000_000.0)
31 } else if n >= 1_000 {
32 format!("{:.1}K", n as f64 / 1_000.0)
33 } else {
34 n.to_string()
35 }
36}
37
38pub fn pad_right(s: &str, width: usize) -> String {
40 let current_width = s.width();
41 if current_width >= width {
42 s.to_string()
43 } else {
44 format!("{}{}", s, " ".repeat(width - current_width))
45 }
46}
47
48pub fn normalize_whitespace(s: &str) -> String {
50 s.split_whitespace().collect::<Vec<_>>().join(" ")
51}