supercode_frontend_tui/foundation/
line_truncation.rs1use ratatui::text::Line;
8use ratatui::text::Span;
9use unicode_width::UnicodeWidthChar;
10use unicode_width::UnicodeWidthStr;
11
12pub fn line_width(line: &Line<'_>) -> usize {
13 line.iter()
14 .map(|span| UnicodeWidthStr::width(span.content.as_ref()))
15 .sum()
16}
17
18pub fn truncate_line_to_width(line: Line<'static>, max_width: usize) -> Line<'static> {
19 if max_width == 0 {
20 return Line::from(Vec::<Span<'static>>::new());
21 }
22
23 let Line {
24 style,
25 alignment,
26 spans,
27 } = line;
28 let mut used = 0usize;
29 let mut spans_out: Vec<Span<'static>> = Vec::with_capacity(spans.len());
30
31 for span in spans {
32 let span_width = UnicodeWidthStr::width(span.content.as_ref());
33
34 if span_width == 0 {
35 spans_out.push(span);
36 continue;
37 }
38
39 if used >= max_width {
40 break;
41 }
42
43 if used + span_width <= max_width {
44 used += span_width;
45 spans_out.push(span);
46 continue;
47 }
48
49 let style = span.style;
50 let text = span.content.as_ref();
51 let mut end_idx = 0usize;
52 for (idx, ch) in text.char_indices() {
53 let ch_width = UnicodeWidthChar::width(ch).unwrap_or(0);
54 if used + ch_width > max_width {
55 break;
56 }
57 end_idx = idx + ch.len_utf8();
58 used += ch_width;
59 }
60
61 if end_idx > 0 {
62 spans_out.push(Span::styled(text[..end_idx].to_string(), style));
63 }
64
65 break;
66 }
67
68 Line {
69 style,
70 alignment,
71 spans: spans_out,
72 }
73}
74
75pub fn truncate_line_with_ellipsis_if_overflow(
82 line: Line<'static>,
83 max_width: usize,
84) -> Line<'static> {
85 if max_width == 0 {
86 return Line::from(Vec::<Span<'static>>::new());
87 }
88
89 if line_width(&line) <= max_width {
90 return line;
91 }
92
93 let truncated = truncate_line_to_width(line, max_width.saturating_sub(1));
94 let Line {
95 style,
96 alignment,
97 mut spans,
98 } = truncated;
99 let ellipsis_style = spans.last().map(|span| span.style).unwrap_or_default();
100 spans.push(Span::styled("…", ellipsis_style));
101 Line {
102 style,
103 alignment,
104 spans,
105 }
106}