Skip to main content

vtcode_commons/
anstyle_utils.rs

1//! Utilities for working with anstyle types and bridging to ratatui.
2//!
3//! **Deprecated**: Use `vtcode_design::color` and `vtcode_design::style` instead.
4//! This module is retained for backward compatibility but will be removed in a
5//! future version.
6
7// Suppress deprecation warnings for internal self-references between deprecated
8// functions within this module. External callers still receive deprecation warnings.
9#![allow(deprecated)]
10
11use anstyle::{AnsiColor, Color as AnsiColorType, Effects, Style as AnsiStyle};
12use ratatui::crossterm::style::Attribute;
13use ratatui::style::{Color, Modifier, Style};
14
15/// Convert anstyle Color to ratatui Color directly.
16///
17/// **Deprecated**: Use `vtcode_design::color::anstyle_to_ratatui_color` instead.
18#[deprecated(
19    since = "0.123.2",
20    note = "Use vtcode_design::color::anstyle_to_ratatui_color instead"
21)]
22pub fn ansi_color_to_ratatui_color(color: &AnsiColorType) -> Color {
23    match color {
24        AnsiColorType::Ansi(ansi_color) => match ansi_color {
25            AnsiColor::Black => Color::Black,
26            AnsiColor::Red => Color::Red,
27            AnsiColor::Green => Color::Green,
28            AnsiColor::Yellow => Color::Yellow,
29            AnsiColor::Blue => Color::Blue,
30            AnsiColor::Magenta => Color::Magenta,
31            AnsiColor::Cyan => Color::Cyan,
32            AnsiColor::White => Color::White,
33            AnsiColor::BrightBlack => Color::DarkGray,
34            AnsiColor::BrightRed => Color::LightRed,
35            AnsiColor::BrightGreen => Color::LightGreen,
36            AnsiColor::BrightYellow => Color::LightYellow,
37            AnsiColor::BrightBlue => Color::LightBlue,
38            AnsiColor::BrightMagenta => Color::LightMagenta,
39            AnsiColor::BrightCyan => Color::LightCyan,
40            AnsiColor::BrightWhite => Color::White,
41        },
42        AnsiColorType::Rgb(rgb_color) => Color::Rgb(rgb_color.r(), rgb_color.g(), rgb_color.b()),
43        AnsiColorType::Ansi256(c) => Color::Indexed(c.0),
44    }
45}
46
47/// Convert an anstyle Style to a ratatui Style using anstyle-crossterm as a bridge.
48///
49/// **Deprecated**: Use `vtcode_design::style::anstyle_to_ratatui_style` instead.
50#[deprecated(
51    since = "0.123.2",
52    note = "Use vtcode_design::style::anstyle_to_ratatui_style instead"
53)]
54pub fn anstyle_to_ratatui(anstyle: AnsiStyle) -> Style {
55    let crossterm_style = anstyle_crossterm::to_crossterm(anstyle);
56    let mut style = Style::default();
57
58    if let Some(fg) = crossterm_style.foreground_color {
59        style = style.fg(crossterm_color_to_ratatui(&fg));
60    }
61
62    if let Some(bg) = crossterm_style.background_color {
63        style = style.bg(crossterm_color_to_ratatui(&bg));
64    }
65
66    let attrs = crossterm_style.attributes;
67    apply_attributes(&mut style, attrs);
68
69    style
70}
71
72fn apply_attributes(style: &mut Style, attrs: ratatui::crossterm::style::Attributes) {
73    if attrs.has(Attribute::Bold) {
74        *style = style.add_modifier(Modifier::BOLD);
75    }
76    if attrs.has(Attribute::Italic) {
77        *style = style.add_modifier(Modifier::ITALIC);
78    }
79    if attrs.has(Attribute::Underlined) {
80        *style = style.add_modifier(Modifier::UNDERLINED);
81    }
82    if attrs.has(Attribute::Dim) {
83        *style = style.add_modifier(Modifier::DIM);
84    }
85    if attrs.has(Attribute::Reverse) {
86        *style = style.add_modifier(Modifier::REVERSED);
87    }
88    if attrs.has(Attribute::SlowBlink) || attrs.has(Attribute::RapidBlink) {
89        *style = style.add_modifier(Modifier::SLOW_BLINK);
90    }
91    if attrs.has(Attribute::CrossedOut) {
92        *style = style.add_modifier(Modifier::CROSSED_OUT);
93    }
94}
95
96fn crossterm_color_to_ratatui(color: &ratatui::crossterm::style::Color) -> Color {
97    use ratatui::crossterm::style::Color as CColor;
98    match color {
99        CColor::Reset => Color::Reset,
100        CColor::Black => Color::Black,
101        CColor::DarkGrey => Color::DarkGray,
102        CColor::Red => Color::Red,
103        CColor::DarkRed => Color::Indexed(52),
104        CColor::Green => Color::Green,
105        CColor::DarkGreen => Color::Indexed(22),
106        CColor::Yellow => Color::Yellow,
107        CColor::DarkYellow => Color::Indexed(58),
108        CColor::Blue => Color::Blue,
109        CColor::DarkBlue => Color::Indexed(17),
110        CColor::Magenta => Color::Magenta,
111        CColor::DarkMagenta => Color::Indexed(53),
112        CColor::Cyan => Color::Cyan,
113        CColor::DarkCyan => Color::Indexed(23),
114        CColor::White => Color::White,
115        CColor::Grey => Color::Gray,
116        CColor::Rgb { r, g, b } => Color::Rgb(*r, *g, *b),
117        CColor::AnsiValue(code) => Color::Indexed(*code),
118    }
119}
120
121/// Convert anstyle Effects to ratatui Modifiers.
122#[deprecated(
123    since = "0.123.2",
124    note = "Use vtcode_design::style::effects_to_modifiers instead"
125)]
126pub fn ansi_effects_to_ratatui_modifiers(effects: Effects) -> Modifier {
127    let mut modifier = Modifier::empty();
128
129    if effects.contains(Effects::BOLD) {
130        modifier.insert(Modifier::BOLD);
131    }
132    if effects.contains(Effects::DIMMED) {
133        modifier.insert(Modifier::DIM);
134    }
135    if effects.contains(Effects::ITALIC) {
136        modifier.insert(Modifier::ITALIC);
137    }
138    if effects.contains(Effects::UNDERLINE) {
139        modifier.insert(Modifier::UNDERLINED);
140    }
141    if effects.contains(Effects::BLINK) {
142        modifier.insert(Modifier::SLOW_BLINK);
143    }
144    if effects.contains(Effects::INVERT) {
145        modifier.insert(Modifier::REVERSED);
146    }
147    if effects.contains(Effects::STRIKETHROUGH) {
148        modifier.insert(Modifier::CROSSED_OUT);
149    }
150
151    modifier
152}
153
154/// Convert an style directly to a ratatui Style using manual mapping.
155///
156/// **Deprecated**: Use `vtcode_design::style::anstyle_to_ratatui_style` instead.
157#[deprecated(
158    since = "0.123.2",
159    note = "Use vtcode_design::style::anstyle_to_ratatui_style instead"
160)]
161pub fn ansi_style_to_ratatui_style(style: AnsiStyle) -> Style {
162    let mut ratatui_style = Style::default();
163
164    if let Some(fg_color) = style.get_fg_color() {
165        ratatui_style = ratatui_style.fg(ansi_color_to_ratatui_color(&fg_color));
166    }
167
168    if let Some(bg_color) = style.get_bg_color() {
169        ratatui_style = ratatui_style.bg(ansi_color_to_ratatui_color(&bg_color));
170    }
171
172    let modifiers = ansi_effects_to_ratatui_modifiers(style.get_effects());
173    ratatui_style = ratatui_style.add_modifier(modifiers);
174
175    ratatui_style
176}
177
178/// A convenience function that combines color, background, and effects into a single ratatui Style.
179#[deprecated(since = "0.123.2", note = "Use vtcode_design::style builders instead")]
180pub fn build_ratatui_style(
181    fg_color: Option<AnsiColorType>,
182    bg_color: Option<AnsiColorType>,
183    effects: Effects,
184) -> Style {
185    let mut style = Style::default();
186
187    if let Some(fg) = fg_color {
188        style = style.fg(ansi_color_to_ratatui_color(&fg));
189    }
190
191    if let Some(bg) = bg_color {
192        style = style.bg(ansi_color_to_ratatui_color(&bg));
193    }
194
195    let modifiers = ansi_effects_to_ratatui_modifiers(effects);
196    style = style.add_modifier(modifiers);
197
198    style
199}
200
201/// Create a ratatui Style with a foreground color from anstyle.
202#[deprecated(since = "0.123.2", note = "Use vtcode_design::style::fg_style instead")]
203pub fn fg_color(color: anstyle::Color) -> Style {
204    anstyle_to_ratatui(AnsiStyle::new().fg_color(Some(color)))
205}
206
207/// Create a ratatui Style with a background color from anstyle.
208#[deprecated(since = "0.123.2", note = "Use vtcode_design::style::bg_style instead")]
209pub fn bg_color(color: anstyle::Color) -> Style {
210    anstyle_to_ratatui(AnsiStyle::new().bg_color(Some(color)))
211}
212
213/// Create a ratatui Style with foreground and background colors.
214#[deprecated(
215    since = "0.123.2",
216    note = "Use vtcode_design::style::fg_bg_style instead"
217)]
218pub fn fg_bg_colors(fg: anstyle::Color, bg: anstyle::Color) -> Style {
219    anstyle_to_ratatui(AnsiStyle::new().fg_color(Some(fg)).bg_color(Some(bg)))
220}
221
222/// Create a ratatui Style with effects/modifiers.
223#[deprecated(
224    since = "0.123.2",
225    note = "Use vtcode_design::style::with_effects instead"
226)]
227pub fn with_effects(effects: Effects) -> Style {
228    anstyle_to_ratatui(AnsiStyle::new().effects(effects))
229}
230
231/// Create a ratatui Style with foreground color and effects.
232#[deprecated(
233    since = "0.123.2",
234    note = "Use vtcode_design::style::colored_with_effects instead"
235)]
236pub fn colored_with_effects(color: anstyle::Color, effects: Effects) -> Style {
237    anstyle_to_ratatui(AnsiStyle::new().fg_color(Some(color)).effects(effects))
238}
239
240/// Create a ratatui Style with background color and effects.
241#[deprecated(since = "0.123.2", note = "Use vtcode_design::style builders instead")]
242pub fn bg_colored_with_effects(color: anstyle::Color, effects: Effects) -> Style {
243    anstyle_to_ratatui(AnsiStyle::new().bg_color(Some(color)).effects(effects))
244}
245
246/// Create a complete ratatui Style from anstyle colors and effects.
247#[deprecated(since = "0.123.2", note = "Use vtcode_design::style builders instead")]
248pub fn full_style(
249    fg: Option<anstyle::Color>,
250    bg: Option<anstyle::Color>,
251    effects: Effects,
252) -> Style {
253    let mut astyle = AnsiStyle::new();
254    if let Some(c) = fg {
255        astyle = astyle.fg_color(Some(c));
256    }
257    if let Some(c) = bg {
258        astyle = astyle.bg_color(Some(c));
259    }
260    astyle = astyle.effects(effects);
261    anstyle_to_ratatui(astyle)
262}