vtcode_commons/
styling.rs1use anstyle::{AnsiColor, Color, Style};
4
5#[derive(Debug, Clone, Copy)]
7pub struct ColorPalette {
8 pub success: Color, pub error: Color, pub warning: Color, pub info: Color, pub accent: Color, pub primary: Color, pub muted: Color, }
16
17impl Default for ColorPalette {
18 fn default() -> Self {
19 Self {
20 success: Color::Ansi(AnsiColor::Green),
21 error: Color::Ansi(AnsiColor::Red),
22 warning: Color::Ansi(AnsiColor::Red),
23 info: Color::Ansi(AnsiColor::Cyan),
24 accent: Color::Ansi(AnsiColor::Magenta),
25 primary: Color::Ansi(AnsiColor::Cyan),
26 muted: Color::Ansi(AnsiColor::BrightBlack),
27 }
28 }
29}
30
31pub fn render_styled(text: &str, color: Color, effects: Option<String>) -> String {
33 let mut style = Style::new().fg_color(Some(color));
34
35 if let Some(effects_str) = effects {
36 let mut ansi_effects = anstyle::Effects::new();
37
38 for effect in effects_str.split(',') {
39 let effect = effect.trim().to_lowercase();
40 match effect.as_str() {
41 "bold" => ansi_effects |= anstyle::Effects::BOLD,
42 "dim" | "dimmed" => ansi_effects |= anstyle::Effects::DIMMED,
43 "italic" => ansi_effects |= anstyle::Effects::ITALIC,
44 "underline" => ansi_effects |= anstyle::Effects::UNDERLINE,
45 "blink" => ansi_effects |= anstyle::Effects::BLINK,
46 "invert" | "reversed" => ansi_effects |= anstyle::Effects::INVERT,
47 "hidden" => ansi_effects |= anstyle::Effects::HIDDEN,
48 "strikethrough" => ansi_effects |= anstyle::Effects::STRIKETHROUGH,
49 _ => {}
50 }
51 }
52
53 style = style.effects(ansi_effects);
54 }
55
56 format!("{}{}{}", style, text, "\x1b[0m")
58}
59
60pub fn style_from_color_name(name: &str) -> Style {
62 let (color_name, dimmed) = if let Some(idx) = name.find(':') {
63 let (color, modifier) = name.split_at(idx);
64 (color, modifier.strip_prefix(':').unwrap_or(""))
65 } else {
66 (name, "")
67 };
68
69 let color = match color_name.to_lowercase().as_str() {
70 "red" => Color::Ansi(AnsiColor::Red),
71 "green" => Color::Ansi(AnsiColor::Green),
72 "blue" => Color::Ansi(AnsiColor::Blue),
73 "yellow" => Color::Ansi(AnsiColor::Yellow),
74 "cyan" => Color::Ansi(AnsiColor::Cyan),
75 "magenta" | "purple" => Color::Ansi(AnsiColor::Magenta),
76 "white" => Color::Ansi(AnsiColor::White),
77 "black" => Color::Ansi(AnsiColor::Black),
78 _ => return Style::new(),
79 };
80
81 let mut style = Style::new().fg_color(Some(color));
82 if dimmed.eq_ignore_ascii_case("dimmed") {
83 style = style.dimmed();
84 }
85 style
86}
87
88pub fn bold_color(color: AnsiColor) -> Style {
90 Style::new().bold().fg_color(Some(Color::Ansi(color)))
91}
92
93pub fn dimmed_color(color: AnsiColor) -> Style {
95 Style::new().dimmed().fg_color(Some(Color::Ansi(color)))
96}
97
98#[derive(Debug, Clone, Copy)]
100pub struct DiffColorPalette {
101 pub added_fg: anstyle::RgbColor,
102 pub added_bg: anstyle::RgbColor,
103 pub removed_fg: anstyle::RgbColor,
104 pub removed_bg: anstyle::RgbColor,
105 pub header_fg: anstyle::RgbColor,
106 pub header_bg: anstyle::RgbColor,
107}
108
109impl Default for DiffColorPalette {
110 fn default() -> Self {
111 Self {
112 added_fg: anstyle::RgbColor(180, 240, 180),
113 added_bg: anstyle::RgbColor(10, 24, 10),
114 removed_fg: anstyle::RgbColor(240, 180, 180),
115 removed_bg: anstyle::RgbColor(24, 10, 10),
116 header_fg: anstyle::RgbColor(150, 200, 220),
117 header_bg: anstyle::RgbColor(10, 16, 20),
118 }
119 }
120}
121
122impl DiffColorPalette {
123 pub fn added_style(&self) -> Style {
124 Style::new()
125 .fg_color(Some(Color::Rgb(self.added_fg)))
126 .bg_color(Some(Color::Rgb(self.added_bg)))
127 }
128
129 pub fn removed_style(&self) -> Style {
130 Style::new()
131 .fg_color(Some(Color::Rgb(self.removed_fg)))
132 .bg_color(Some(Color::Rgb(self.removed_bg)))
133 }
134
135 pub fn header_style(&self) -> Style {
136 Style::new()
137 .fg_color(Some(Color::Rgb(self.header_fg)))
138 .bg_color(Some(Color::Rgb(self.header_bg)))
139 }
140}