gitkraft_core/utils/
text.rs1pub 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
19pub fn path_basename(path: &str) -> &str {
30 path.rsplit('/').next().unwrap_or(path)
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn no_truncation_when_short() {
39 assert_eq!(truncate_str("hello", 10), "hello");
40 }
41
42 #[test]
43 fn exact_length_no_truncation() {
44 assert_eq!(truncate_str("hello", 5), "hello");
45 }
46
47 #[test]
48 fn truncation_adds_ellipsis() {
49 assert_eq!(truncate_str("hello world", 5), "hell…");
50 }
51
52 #[test]
53 fn max_one_gives_ellipsis() {
54 assert_eq!(truncate_str("hello", 1), "…");
55 }
56
57 #[test]
58 fn max_zero_gives_ellipsis() {
59 assert_eq!(truncate_str("hello", 0), "…");
60 }
61
62 #[test]
63 fn unicode_chars_counted_correctly() {
64 assert_eq!(truncate_str("😀😁😂😃", 3), "😀😁…");
66 }
67
68 #[test]
69 fn empty_string() {
70 assert_eq!(truncate_str("", 5), "");
71 }
72
73 #[test]
74 fn path_basename_with_slashes() {
75 assert_eq!(path_basename("src/main.rs"), "main.rs");
76 }
77
78 #[test]
79 fn path_basename_no_slash() {
80 assert_eq!(path_basename("hello.txt"), "hello.txt");
81 }
82
83 #[test]
84 fn path_basename_trailing_slash() {
85 assert_eq!(path_basename("dir/"), "");
86 }
87
88 #[test]
89 fn path_basename_empty() {
90 assert_eq!(path_basename(""), "");
91 }
92
93 #[test]
94 fn path_basename_deep_path() {
95 assert_eq!(path_basename("a/b/c/d/file.rs"), "file.rs");
96 }
97}