nu_ansi_term/
util.rs

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