1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use tui::{
style::Style,
text::{Span, Spans, StyledGrapheme},
};
pub trait IntoSpan<'a> {
fn into_span(self) -> Span<'a>;
}
impl<'a> IntoSpan<'a> for StyledGrapheme<'a> {
fn into_span(self) -> Span<'a> {
Span::styled(self.symbol, self.style)
}
}
pub trait IntoSpans<'a> {
fn into_spans(self) -> Spans<'a>;
}
impl<'a> IntoSpans<'a> for Vec<StyledGrapheme<'a>> {
fn into_spans(self) -> Spans<'a> {
self.into_iter()
.fold(None, |mut acc: Option<(Vec<Span<'a>>, Style)>, x| {
let x_style = x.style;
match acc {
Some((ref mut vec, ref mut style)) => {
if style == &x_style {
vec.last_mut().expect("vec.len() >= 1").content += x.symbol;
} else {
vec.push(x.into_span());
*style = x_style
}
}
None => return Some((vec![x.into_span()], x_style)),
};
acc
})
.map(|(vec, _)| vec)
.unwrap_or_default()
.into()
}
}
impl<'a> IntoSpans<'a> for Vec<(Style, char)> {
fn into_spans(self) -> Spans<'a> {
self.into_iter()
.fold(
None,
|mut acc: Option<(Vec<(Style, String)>, Style)>, (x_style, c)| {
match acc {
Some((ref mut vec, ref mut style)) => {
if style == &x_style {
let last = &mut vec.last_mut().expect("vec.len() >= 1").1;
last.push(c);
} else {
vec.push((x_style, c.to_string()));
*style = x_style
}
}
None => return Some((vec![(x_style, c.to_string())], x_style)),
};
acc
},
)
.map(|(vec, _)| {
vec.into_iter()
.map(|(style, string)| Span::styled(string, style))
.collect::<Vec<_>>()
})
.unwrap_or_default()
.into()
}
}
#[test]
fn test_into_span() {
use tui::style::Color;
let style_blue = Style::default().fg(Color::Blue);
let style_plain = Style::default();
let style_red = Style::default().fg(Color::Red);
let (a, b, c) = (
Span::raw("Hello"),
Span::raw(" "),
Span::raw("World 中文测试"),
);
let chars_blue = a.styled_graphemes(style_blue);
let chars_plain = b.styled_graphemes(style_plain);
let chars_red = c.styled_graphemes(style_red);
let spans = chars_blue
.chain(chars_plain)
.chain(chars_red)
.collect::<Vec<_>>()
.into_spans();
assert_eq!(
spans,
Spans::from(vec![
Span {
content: "Hello".into(),
style: style_blue
},
Span {
content: " ".into(),
style: style_plain
},
Span {
content: "World 中文测试".into(),
style: style_red
},
])
)
}