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}
80