vtcode_commons/
anstyle_utils.rs1use anstyle::{AnsiColor, Color as AnsiColorType, Effects, Style as AnsiStyle};
4use ratatui::crossterm::style::Attribute;
5use ratatui::style::{Color, Modifier, Style};
6
7pub fn ansi_color_to_ratatui_color(color: &AnsiColorType) -> Color {
9 match color {
10 AnsiColorType::Ansi(ansi_color) => match ansi_color {
11 AnsiColor::Black => Color::Black,
12 AnsiColor::Red => Color::Red,
13 AnsiColor::Green => Color::Green,
14 AnsiColor::Yellow => Color::Yellow,
15 AnsiColor::Blue => Color::Blue,
16 AnsiColor::Magenta => Color::DarkGray,
17 AnsiColor::Cyan => Color::Cyan,
18 AnsiColor::White => Color::White,
19 AnsiColor::BrightBlack => Color::DarkGray,
20 AnsiColor::BrightRed => Color::Red,
21 AnsiColor::BrightGreen => Color::Green,
22 AnsiColor::BrightYellow => Color::Yellow,
23 AnsiColor::BrightBlue => Color::Blue,
24 AnsiColor::BrightMagenta => Color::DarkGray,
25 AnsiColor::BrightCyan => Color::Cyan,
26 AnsiColor::BrightWhite => Color::Gray,
27 },
28 AnsiColorType::Rgb(rgb_color) => Color::Rgb(rgb_color.r(), rgb_color.g(), rgb_color.b()),
29 _ => Color::Reset,
30 }
31}
32
33pub fn anstyle_to_ratatui(anstyle: AnsiStyle) -> Style {
35 let crossterm_style = anstyle_crossterm::to_crossterm(anstyle);
36 let mut style = Style::default();
37
38 if let Some(fg) = crossterm_style.foreground_color {
39 style = style.fg(crossterm_color_to_ratatui(&fg));
40 }
41
42 if let Some(bg) = crossterm_style.background_color {
43 style = style.bg(crossterm_color_to_ratatui(&bg));
44 }
45
46 let attrs = crossterm_style.attributes;
47 apply_attributes(&mut style, attrs);
48
49 style
50}
51
52fn apply_attributes(style: &mut Style, attrs: ratatui::crossterm::style::Attributes) {
53 if attrs.has(Attribute::Bold) {
54 *style = style.add_modifier(Modifier::BOLD);
55 }
56 if attrs.has(Attribute::Italic) {
57 *style = style.add_modifier(Modifier::ITALIC);
58 }
59 if attrs.has(Attribute::Underlined) {
60 *style = style.add_modifier(Modifier::UNDERLINED);
61 }
62 if attrs.has(Attribute::Dim) {
63 *style = style.add_modifier(Modifier::DIM);
64 }
65 if attrs.has(Attribute::Reverse) {
66 *style = style.add_modifier(Modifier::REVERSED);
67 }
68 if attrs.has(Attribute::SlowBlink) || attrs.has(Attribute::RapidBlink) {
69 *style = style.add_modifier(Modifier::SLOW_BLINK);
70 }
71 if attrs.has(Attribute::CrossedOut) {
72 *style = style.add_modifier(Modifier::CROSSED_OUT);
73 }
74}
75
76fn crossterm_color_to_ratatui(color: &ratatui::crossterm::style::Color) -> Color {
77 use ratatui::crossterm::style::Color as CColor;
78 match color {
79 CColor::Reset => Color::Reset,
80 CColor::Black => Color::Black,
81 CColor::DarkGrey => Color::DarkGray,
82 CColor::Red => Color::Red,
83 CColor::DarkRed => Color::Indexed(52),
84 CColor::Green => Color::Green,
85 CColor::DarkGreen => Color::Indexed(22),
86 CColor::Yellow => Color::Yellow,
87 CColor::DarkYellow => Color::Indexed(58),
88 CColor::Blue => Color::Blue,
89 CColor::DarkBlue => Color::Indexed(17),
90 CColor::Magenta => Color::DarkGray,
91 CColor::DarkMagenta => Color::DarkGray,
92 CColor::Cyan => Color::Cyan,
93 CColor::DarkCyan => Color::Indexed(23),
94 CColor::White => Color::White,
95 CColor::Grey => Color::Gray,
96 CColor::Rgb { r, g, b } => Color::Rgb(*r, *g, *b),
97 CColor::AnsiValue(code) => Color::Indexed(*code),
98 }
99}
100
101pub fn ansi_effects_to_ratatui_modifiers(effects: Effects) -> Modifier {
103 let mut modifier = Modifier::empty();
104
105 if effects.contains(Effects::BOLD) {
106 modifier.insert(Modifier::BOLD);
107 }
108 if effects.contains(Effects::DIMMED) {
109 modifier.insert(Modifier::DIM);
110 }
111 if effects.contains(Effects::ITALIC) {
112 modifier.insert(Modifier::ITALIC);
113 }
114 if effects.contains(Effects::UNDERLINE) {
115 modifier.insert(Modifier::UNDERLINED);
116 }
117 if effects.contains(Effects::BLINK) {
118 modifier.insert(Modifier::SLOW_BLINK);
119 }
120 if effects.contains(Effects::INVERT) {
121 modifier.insert(Modifier::REVERSED);
122 }
123 if effects.contains(Effects::STRIKETHROUGH) {
124 modifier.insert(Modifier::CROSSED_OUT);
125 }
126
127 modifier
128}
129
130pub fn ansi_style_to_ratatui_style(style: AnsiStyle) -> Style {
132 let mut ratatui_style = Style::default();
133
134 if let Some(fg_color) = style.get_fg_color() {
135 ratatui_style = ratatui_style.fg(ansi_color_to_ratatui_color(&fg_color));
136 }
137
138 if let Some(bg_color) = style.get_bg_color() {
139 ratatui_style = ratatui_style.bg(ansi_color_to_ratatui_color(&bg_color));
140 }
141
142 let modifiers = ansi_effects_to_ratatui_modifiers(style.get_effects());
143 ratatui_style = ratatui_style.add_modifier(modifiers);
144
145 ratatui_style
146}
147
148pub fn build_ratatui_style(
150 fg_color: Option<AnsiColorType>,
151 bg_color: Option<AnsiColorType>,
152 effects: Effects,
153) -> Style {
154 let mut style = Style::default();
155
156 if let Some(fg) = fg_color {
157 style = style.fg(ansi_color_to_ratatui_color(&fg));
158 }
159
160 if let Some(bg) = bg_color {
161 style = style.bg(ansi_color_to_ratatui_color(&bg));
162 }
163
164 let modifiers = ansi_effects_to_ratatui_modifiers(effects);
165 style = style.add_modifier(modifiers);
166
167 style
168}
169
170pub fn fg_color(color: anstyle::Color) -> Style {
172 anstyle_to_ratatui(AnsiStyle::new().fg_color(Some(color)))
173}
174
175pub fn bg_color(color: anstyle::Color) -> Style {
177 anstyle_to_ratatui(AnsiStyle::new().bg_color(Some(color)))
178}
179
180pub fn fg_bg_colors(fg: anstyle::Color, bg: anstyle::Color) -> Style {
182 anstyle_to_ratatui(AnsiStyle::new().fg_color(Some(fg)).bg_color(Some(bg)))
183}
184
185pub fn with_effects(effects: anstyle::Effects) -> Style {
187 anstyle_to_ratatui(AnsiStyle::new().effects(effects))
188}
189
190pub fn colored_with_effects(color: anstyle::Color, effects: anstyle::Effects) -> Style {
192 anstyle_to_ratatui(AnsiStyle::new().fg_color(Some(color)).effects(effects))
193}
194
195pub fn bg_colored_with_effects(color: anstyle::Color, effects: anstyle::Effects) -> Style {
197 anstyle_to_ratatui(AnsiStyle::new().bg_color(Some(color)).effects(effects))
198}
199
200pub fn full_style(
202 fg: Option<anstyle::Color>,
203 bg: Option<anstyle::Color>,
204 effects: anstyle::Effects,
205) -> Style {
206 let mut astyle = AnsiStyle::new();
207 if let Some(c) = fg {
208 astyle = astyle.fg_color(Some(c));
209 }
210 if let Some(c) = bg {
211 astyle = astyle.bg_color(Some(c));
212 }
213 astyle = astyle.effects(effects);
214 anstyle_to_ratatui(astyle)
215}