1use std::borrow::Cow;
4
5use unicode_segmentation::UnicodeSegmentation;
6use unicode_width::UnicodeWidthStr;
7
8pub(crate) fn number_width(number: usize) -> usize {
10 let mut width = 1;
11 let mut limit = 10;
12 while limit <= number {
13 limit *= 10;
14 width += 1;
15 }
16 width
17}
18
19pub(crate) fn truncate_string<'a>(
21 text: impl Into<Cow<'a, str>>,
22 offset: usize,
23 width: usize,
24) -> String {
25 let text = text.into();
26 if offset > 0 || width < text.width() {
27 let mut column = 0;
28 let mut maybe_start_index = None;
29 let mut maybe_end_index = None;
30 let mut start_pad = 0;
31 let mut end_pad = 0;
32 for (i, g) in text.grapheme_indices(true) {
33 let w = g.width();
34 if w != 0 {
35 if column >= offset && maybe_start_index.is_none() {
36 maybe_start_index = Some(i);
37 start_pad = column - offset;
38 }
39 if column + w > offset + width && maybe_end_index.is_none() {
40 maybe_end_index = Some(i);
41 end_pad = offset + width - column;
42 break;
43 }
44 column += w;
45 }
46 }
47 let start_index = maybe_start_index.unwrap_or(text.len());
48 let end_index = maybe_end_index.unwrap_or(text.len());
49 format!(
50 "{0:1$.1$}{3}{0:2$.2$}",
51 "",
52 start_pad,
53 end_pad,
54 &text[start_index..end_index]
55 )
56 } else {
57 text.into_owned()
58 }
59}