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
33pub fn truncate_to_fit(s: &str, available_px: f32, px_per_char: f32) -> String {
40 if available_px <= 0.0 || px_per_char <= 0.0 {
41 return String::new();
42 }
43 let max_chars = (available_px / px_per_char).floor() as usize;
44 truncate_str(s, max_chars)
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn no_truncation_when_short() {
53 assert_eq!(truncate_str("hello", 10), "hello");
54 }
55
56 #[test]
57 fn exact_length_no_truncation() {
58 assert_eq!(truncate_str("hello", 5), "hello");
59 }
60
61 #[test]
62 fn truncation_adds_ellipsis() {
63 assert_eq!(truncate_str("hello world", 5), "hell…");
64 }
65
66 #[test]
67 fn max_one_gives_ellipsis() {
68 assert_eq!(truncate_str("hello", 1), "…");
69 }
70
71 #[test]
72 fn max_zero_gives_ellipsis() {
73 assert_eq!(truncate_str("hello", 0), "…");
74 }
75
76 #[test]
77 fn unicode_chars_counted_correctly() {
78 assert_eq!(truncate_str("😀😁😂😃", 3), "😀😁…");
80 }
81
82 #[test]
83 fn empty_string() {
84 assert_eq!(truncate_str("", 5), "");
85 }
86
87 #[test]
88 fn path_basename_with_slashes() {
89 assert_eq!(path_basename("src/main.rs"), "main.rs");
90 }
91
92 #[test]
93 fn path_basename_no_slash() {
94 assert_eq!(path_basename("hello.txt"), "hello.txt");
95 }
96
97 #[test]
98 fn path_basename_trailing_slash() {
99 assert_eq!(path_basename("dir/"), "");
100 }
101
102 #[test]
103 fn path_basename_empty() {
104 assert_eq!(path_basename(""), "");
105 }
106
107 #[test]
108 fn path_basename_deep_path() {
109 assert_eq!(path_basename("a/b/c/d/file.rs"), "file.rs");
110 }
111
112 #[test]
113 fn truncate_to_fit_short_string() {
114 assert_eq!(truncate_to_fit("hi", 100.0, 7.0), "hi");
115 }
116
117 #[test]
118 fn truncate_to_fit_long_string() {
119 let result = truncate_to_fit("hello world", 30.0, 7.0);
120 assert!(result.ends_with('…'));
121 assert!(result.chars().count() <= 5);
122 }
123
124 #[test]
125 fn truncate_to_fit_zero_px() {
126 assert_eq!(truncate_to_fit("hello", 0.0, 7.0), "");
127 }
128
129 #[test]
130 fn truncate_to_fit_negative_px() {
131 assert_eq!(truncate_to_fit("hello", -10.0, 7.0), "");
132 }
133
134 #[test]
135 fn truncate_to_fit_zero_px_per_char() {
136 assert_eq!(truncate_to_fit("hello", 100.0, 0.0), "");
137 }
138}