tui_markup/generator/crossterm/
span.rs1use crossterm::{
2 style::{Attributes, Color, ContentStyle, Print, PrintStyledContent, Stylize},
3 Command,
4};
5
6use crate::generator::{
7 helper::{FlattenableSpan, FlattenableStyle},
8 Tag, TagConvertor,
9};
10
11impl<'a, C> From<Tag<'a, C>> for ContentStyle
12where
13 C: TagConvertor<'a, Color = Color, Modifier = Attributes, Custom = ContentStyle>,
14{
15 fn from(t: Tag<'a, C>) -> Self {
16 match t {
17 Tag::Fg(c) => ContentStyle::new().with(c),
18 Tag::Bg(c) => ContentStyle::new().on(c),
19 Tag::Modifier(m) => {
20 let mut c = ContentStyle::new();
21 c.attributes = m;
22 c
23 }
24 Tag::Custom(style) => style,
25 }
26 }
27}
28
29impl FlattenableStyle for ContentStyle {
30 fn patch(mut self, other: Self) -> Self {
31 if let Some(c) = other.foreground_color {
32 self = self.with(c);
33 }
34
35 if let Some(c) = other.background_color {
36 self = self.on(c);
37 }
38
39 self.attributes.extend(other.attributes);
40
41 self
42 }
43}
44
45#[derive(Debug)]
47pub enum Span<'a> {
48 NoStyle(Print<&'a str>),
50 Styled(PrintStyledContent<&'a str>),
52}
53
54impl<'a> FlattenableSpan<'a, ContentStyle> for Span<'a> {
55 fn with_style(s: &'a str, style: Option<ContentStyle>) -> Self {
56 match style {
57 Some(style) => Span::Styled(PrintStyledContent(style.apply(s))),
58 None => Span::NoStyle(Print(s)),
59 }
60 }
61}
62
63impl<'a> Command for Span<'a> {
64 fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result {
65 match self {
66 Self::NoStyle(p) => p.write_ansi(f),
67 Self::Styled(p) => p.write_ansi(f),
68 }
69 }
70
71 #[cfg(windows)]
72 fn execute_winapi(&self) -> std::io::Result<()> {
73 match self {
74 Self::NoStyle(p) => p.execute_winapi(),
75 Self::Styled(p) => p.execute_winapi(),
76 }
77 }
78
79 #[cfg(windows)]
80 fn is_ansi_code_supported(&self) -> bool {
81 match self {
82 Self::NoStyle(p) => p.is_ansi_code_supported(),
83 Self::Styled(p) => p.is_ansi_code_supported(),
84 }
85 }
86}