1#[macro_export]
28macro_rules! define_theme {
29 (
30 bg: ($bg_r:expr, $bg_g:expr, $bg_b:expr),
31 bg_alt: ($bg_alt_r:expr, $bg_alt_g:expr, $bg_alt_b:expr),
32 fg: ($fg_r:expr, $fg_g:expr, $fg_b:expr),
33 fg_alt: ($fg_alt_r:expr, $fg_alt_g:expr, $fg_alt_b:expr),
34 base4: ($base4_r:expr, $base4_g:expr, $base4_b:expr),
35 red: ($red_r:expr, $red_g:expr, $red_b:expr),
36 orange: ($orange_r:expr, $orange_g:expr, $orange_b:expr),
37 yellow: ($yellow_r:expr, $yellow_g:expr, $yellow_b:expr),
38 green: ($green_r:expr, $green_g:expr, $green_b:expr),
39 cyan: ($cyan_r:expr, $cyan_g:expr, $cyan_b:expr),
40 blue: ($blue_r:expr, $blue_g:expr, $blue_b:expr),
41 magenta: ($magenta_r:expr, $magenta_g:expr, $magenta_b:expr),
42 violet: ($violet_r:expr, $violet_g:expr, $violet_b:expr)
43 ) => {
44 pub fn theme() -> Theme {
45 use ratatui::style::{Color, Modifier, Style};
46
47 const BG: Color = Color::Rgb($bg_r, $bg_g, $bg_b);
48 const BG_ALT: Color = Color::Rgb($bg_alt_r, $bg_alt_g, $bg_alt_b);
49 const FG: Color = Color::Rgb($fg_r, $fg_g, $fg_b);
50 const FG_ALT: Color = Color::Rgb($fg_alt_r, $fg_alt_g, $fg_alt_b);
51 const BASE4: Color = Color::Rgb($base4_r, $base4_g, $base4_b);
52 const RED: Color = Color::Rgb($red_r, $red_g, $red_b);
53 const ORANGE: Color = Color::Rgb($orange_r, $orange_g, $orange_b);
54 const YELLOW: Color = Color::Rgb($yellow_r, $yellow_g, $yellow_b);
55 const GREEN: Color = Color::Rgb($green_r, $green_g, $green_b);
56 const CYAN: Color = Color::Rgb($cyan_r, $cyan_g, $cyan_b);
57 const BLUE: Color = Color::Rgb($blue_r, $blue_g, $blue_b);
58 const MAGENTA: Color = Color::Rgb($magenta_r, $magenta_g, $magenta_b);
59 const VIOLET: Color = Color::Rgb($violet_r, $violet_g, $violet_b);
60
61 Theme {
62 background: Style::default().bg(BG),
63 text: Style::default().fg(FG),
64 border: Style::default().fg(BASE4),
65 border_focused: Style::default().fg(CYAN),
66 title_separator: Style::default().fg(BASE4),
67 title_indicator_connected: Style::default().fg(GREEN),
68 title_indicator_disconnected: Style::default().fg(RED),
69 title_text: Style::default().fg(FG),
70 user_prefix: Style::default().fg(BLUE),
71 system_prefix: Style::default().fg(YELLOW),
72 assistant_prefix: Style::default().fg(MAGENTA),
73 timestamp: Style::default().fg(FG_ALT),
74 cursor: Style::default().fg(GREEN),
75 bold: Modifier::BOLD,
76 italic: Modifier::ITALIC,
77 strikethrough: Modifier::CROSSED_OUT,
78 inline_code: Style::default().fg(YELLOW),
79 link_text: Style::default().fg(CYAN),
80 link_url: Style::default().fg(VIOLET),
81 heading_1: Style::default().fg(CYAN).add_modifier(Modifier::BOLD),
82 heading_2: Style::default().fg(GREEN).add_modifier(Modifier::BOLD),
83 heading_3: Style::default().fg(YELLOW).add_modifier(Modifier::BOLD),
84 heading_4: Style::default().fg(FG).add_modifier(Modifier::BOLD),
85 code_block: Style::default().fg(FG).bg(BG_ALT),
86 table_header: Style::default().fg(CYAN).add_modifier(Modifier::BOLD),
87 table_cell: Style::default().fg(FG),
88 table_border: Style::default().fg(BASE4),
89 tool_header: Style::default().fg(ORANGE),
90 tool_executing: Style::default().fg(FG_ALT).add_modifier(Modifier::ITALIC),
91 tool_completed: Style::default().fg(GREEN),
92 tool_failed: Style::default().fg(RED),
93 input_border: Style::default().fg(BASE4),
94 input_text: Style::default().fg(FG),
95 prompt: Style::default().fg(FG),
96 throbber_label: Style::default().fg(FG_ALT),
97 throbber_spinner: Style::default().fg(CYAN),
98 status_help: Style::default().fg(FG_ALT),
99 status_model: Style::default().fg(FG_ALT),
100 popup_border: Style::default().fg(BASE4),
101 popup_header: Style::default().fg(FG_ALT),
102 popup_item: Style::default().fg(FG),
103 popup_item_selected: Style::default().fg(CYAN).add_modifier(Modifier::BOLD),
104 popup_item_desc: Style::default().fg(FG_ALT),
105 popup_item_desc_selected: Style::default().fg(FG),
106 popup_selected_bg: Style::default().bg(BG_ALT),
107 popup_empty: Style::default().fg(FG_ALT).add_modifier(Modifier::ITALIC),
108 help_text: Style::default().fg(FG_ALT),
109 muted_text: Style::default().fg(FG_ALT),
110 focused_text: Style::default().fg(CYAN).add_modifier(Modifier::BOLD),
111 focus_indicator: Style::default().fg(YELLOW),
112 selected: Style::default().fg(GREEN),
113 unselected: Style::default().fg(FG_ALT),
114 button_confirm: Style::default().fg(GREEN),
115 button_confirm_focused: Style::default().fg(GREEN).add_modifier(Modifier::BOLD),
116 button_cancel: Style::default().fg(RED),
117 button_cancel_focused: Style::default().fg(RED).add_modifier(Modifier::BOLD),
118 warning: Style::default().fg(YELLOW),
119 category: Style::default().fg(MAGENTA),
120 resource: Style::default().fg(CYAN),
121 }
122 }
123 };
124}
125
126#[macro_export]
137macro_rules! register_themes {
138 (
139 $(
140 $module:ident => {
141 name: $name:literal,
142 display: $display:literal,
143 dark: $is_dark:expr
144 }
145 ),* $(,)?
146 ) => {
147 $(mod $module;)*
149
150 pub struct ThemeInfo {
152 pub name: &'static str,
153 pub display_name: &'static str,
154 pub is_dark: bool,
155 }
156
157 pub const THEMES: &[ThemeInfo] = &[
159 $(
160 ThemeInfo {
161 name: $name,
162 display_name: $display,
163 is_dark: $is_dark,
164 },
165 )*
166 ];
167
168 pub fn get_theme(name: &str) -> Option<Theme> {
170 match name {
171 $($name => Some($module::theme()),)*
172 _ => None,
173 }
174 }
175
176 pub fn list_themes() -> Vec<&'static str> {
178 THEMES.iter().map(|t| t.name).collect()
179 }
180
181 pub fn default_theme_name() -> &'static str {
183 "henna"
184 }
185 };
186}
187
188pub use define_theme;
190pub use register_themes;