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
use crossterm::{
style::{Attributes, Color, ContentStyle, Print, PrintStyledContent, Stylize},
Command,
};
use crate::generator::{
helper::{FlattenableSpan, FlattenableStyle},
Tag, TagConvertor,
};
impl<'a, C> From<Tag<'a, C>> for ContentStyle
where
C: TagConvertor<'a, Color = Color, Modifier = Attributes, Custom = ContentStyle>,
{
fn from(t: Tag<'a, C>) -> Self {
match t {
Tag::Fg(c) => ContentStyle::new().with(c),
Tag::Bg(c) => ContentStyle::new().on(c),
Tag::Modifier(m) => {
let mut c = ContentStyle::new();
c.attributes = m;
c
}
Tag::Custom(style) => style,
}
}
}
impl FlattenableStyle for ContentStyle {
fn patch(mut self, other: Self) -> Self {
if let Some(c) = other.foreground_color {
self = self.with(c);
}
if let Some(c) = other.background_color {
self = self.on(c);
}
self.attributes.extend(other.attributes);
self
}
}
#[derive(Debug)]
pub enum Span<'a> {
NoStyle(Print<&'a str>),
Styled(PrintStyledContent<&'a str>),
}
impl<'a> FlattenableSpan<'a, ContentStyle> for Span<'a> {
fn with_style(s: &'a str, style: Option<ContentStyle>) -> Self {
match style {
Some(style) => Span::Styled(PrintStyledContent(style.apply(s))),
None => Span::NoStyle(Print(s)),
}
}
}
impl<'a> Command for Span<'a> {
fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result {
match self {
Self::NoStyle(p) => p.write_ansi(f),
Self::Styled(p) => p.write_ansi(f),
}
}
}