Skip to main content

gitkraft_core/utils/
text.rs

1//! Text manipulation utilities shared across the crate.
2
3/// Truncate `s` to at most `max_chars` Unicode characters, appending "…" if shortened.
4///
5/// This is a framework-agnostic utility shared by both the GUI and TUI.
6pub fn truncate_str(s: &str, max_chars: usize) -> String {
7    let char_count = s.chars().count();
8    if char_count <= max_chars {
9        s.to_string()
10    } else if max_chars <= 1 {
11        "…".to_string()
12    } else {
13        let mut out: String = s.chars().take(max_chars - 1).collect();
14        out.push('…');
15        out
16    }
17}
18
19#[cfg(test)]
20mod tests {
21    use super::*;
22
23    #[test]
24    fn no_truncation_when_short() {
25        assert_eq!(truncate_str("hello", 10), "hello");
26    }
27
28    #[test]
29    fn exact_length_no_truncation() {
30        assert_eq!(truncate_str("hello", 5), "hello");
31    }
32
33    #[test]
34    fn truncation_adds_ellipsis() {
35        assert_eq!(truncate_str("hello world", 5), "hell…");
36    }
37
38    #[test]
39    fn max_one_gives_ellipsis() {
40        assert_eq!(truncate_str("hello", 1), "…");
41    }
42
43    #[test]
44    fn max_zero_gives_ellipsis() {
45        assert_eq!(truncate_str("hello", 0), "…");
46    }
47
48    #[test]
49    fn unicode_chars_counted_correctly() {
50        // 4 chars: each emoji is 1 char
51        assert_eq!(truncate_str("😀😁😂😃", 3), "😀😁…");
52    }
53
54    #[test]
55    fn empty_string() {
56        assert_eq!(truncate_str("", 5), "");
57    }
58}