nu_ansi_term/
util.rs

1use crate::display::{AnsiString, AnsiStrings};
2use std::ops::Deref;
3
4/// Return a substring of the given AnsiStrings sequence, while keeping the formatting.
5pub fn sub_string(start: usize, len: usize, strs: &AnsiStrings) -> Vec<AnsiString<'static>> {
6    let mut vec = Vec::new();
7    let mut pos = start;
8    let mut len_rem = len;
9
10    for i in strs.0.iter() {
11        let frag_len = i.string.len();
12        if pos >= frag_len {
13            pos -= frag_len;
14            continue;
15        }
16        if len_rem == 0 {
17            break;
18        }
19
20        let end = pos + len_rem;
21        let pos_end = if end >= frag_len { frag_len } else { end };
22
23        vec.push(i.style_ref().paint(String::from(&i.string[pos..pos_end])));
24
25        if end <= frag_len {
26            break;
27        }
28
29        len_rem -= pos_end - pos;
30        pos = 0;
31    }
32
33    vec
34}
35
36/// Return a concatenated copy of `strs` without the formatting, as an allocated `String`.
37pub fn unstyle(strs: &AnsiStrings) -> String {
38    let mut s = String::new();
39
40    for i in strs.0.iter() {
41        s += i.string.deref();
42    }
43
44    s
45}
46
47/// Return the unstyled length of AnsiStrings. This is equaivalent to `unstyle(strs).len()`.
48pub fn unstyled_len(strs: &AnsiStrings) -> usize {
49    let mut l = 0;
50    for i in strs.0.iter() {
51        l += i.string.len();
52    }
53    l
54}
55
56#[cfg(test)]
57mod test {
58    use super::*;
59    use crate::Color::*;
60
61    #[test]
62    fn test() {
63        let l = [
64            Black.paint("first"),
65            Red.paint("-second"),
66            White.paint("-third"),
67        ];
68        let a = AnsiStrings(&l);
69        assert_eq!(unstyle(&a), "first-second-third");
70        assert_eq!(unstyled_len(&a), 18);
71
72        let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
73        assert_eq!(sub_string(3, 11, &a), l2);
74    }
75}