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