1use ratatui::style::{Color, Modifier, Style};
5
6pub struct SyntaxTheme {
25 pub keyword: Style,
27 pub string: Style,
29 pub comment: Style,
31 pub function: Style,
33 pub r#type: Style,
35 pub number: Style,
37 pub operator: Style,
39 pub variable: Style,
41 pub attribute: Style,
43 pub punctuation: Style,
45 pub constant: Style,
47 pub default: Style,
49}
50
51pub struct Theme {
67 pub user_message: Style,
68 pub assistant_message: Style,
69 pub system_message: Style,
70 pub input_text: Style,
71 pub input_cursor: Style,
72 pub status_bar: Style,
73 pub header: Style,
74 pub panel_border: Style,
75 pub panel_title: Style,
76 pub highlight: Style,
77 pub error: Style,
78 pub thinking_message: Style,
79 pub code_inline: Style,
80 pub code_block: Style,
81 pub streaming_cursor: Style,
82 pub tool_command: Style,
83 pub assistant_accent: Style,
84 pub tool_accent: Style,
85 pub diff_added_bg: Color,
86 pub diff_removed_bg: Color,
87 pub diff_word_added_bg: Color,
88 pub diff_word_removed_bg: Color,
89 pub diff_gutter_add: Style,
90 pub diff_gutter_remove: Style,
91 pub diff_header: Style,
92 pub link: Style,
93 pub table_border: Style,
94}
95
96impl Default for Theme {
97 fn default() -> Self {
98 Self {
99 user_message: Style::default().fg(Color::Cyan),
100 assistant_message: Style::default().fg(Color::Rgb(200, 200, 210)),
101 system_message: Style::default().fg(Color::DarkGray),
102 input_text: Style::default().fg(Color::Cyan),
103 input_cursor: Style::default()
104 .fg(Color::Yellow)
105 .add_modifier(Modifier::BOLD),
106 status_bar: Style::default().fg(Color::White).bg(Color::DarkGray),
107 header: Style::default()
108 .fg(Color::Rgb(200, 220, 255))
109 .bg(Color::Rgb(20, 40, 80))
110 .add_modifier(Modifier::BOLD),
111 panel_border: Style::default().fg(Color::Gray),
112 panel_title: Style::default()
113 .fg(Color::White)
114 .add_modifier(Modifier::BOLD),
115 highlight: Style::default().fg(Color::Rgb(215, 150, 60)),
116 error: Style::default().fg(Color::Red),
117 thinking_message: Style::default().fg(Color::DarkGray),
118 code_inline: Style::default()
119 .fg(Color::Rgb(100, 180, 255))
120 .bg(Color::Rgb(15, 30, 55))
121 .add_modifier(Modifier::BOLD),
122 code_block: Style::default().fg(Color::Rgb(190, 175, 145)),
123 streaming_cursor: Style::default().fg(Color::DarkGray),
124 tool_command: Style::default()
125 .fg(Color::Yellow)
126 .add_modifier(Modifier::BOLD),
127 assistant_accent: Style::default().fg(Color::Rgb(185, 85, 25)),
128 tool_accent: Style::default().fg(Color::Rgb(140, 120, 50)),
129 diff_added_bg: Color::Rgb(0, 40, 0),
130 diff_removed_bg: Color::Rgb(40, 0, 0),
131 diff_word_added_bg: Color::Rgb(0, 80, 0),
132 diff_word_removed_bg: Color::Rgb(80, 0, 0),
133 diff_gutter_add: Style::default().fg(Color::Green),
134 diff_gutter_remove: Style::default().fg(Color::Red),
135 diff_header: Style::default().fg(Color::DarkGray),
136 link: Style::default()
137 .fg(Color::Cyan)
138 .add_modifier(Modifier::UNDERLINED),
139 table_border: Style::default().fg(Color::DarkGray),
140 }
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn default_theme_has_distinct_message_styles() {
150 let theme = Theme::default();
151 assert_ne!(theme.user_message, theme.assistant_message);
152 assert_ne!(theme.assistant_message, theme.system_message);
153 }
154
155 #[test]
156 fn default_theme_status_bar_has_background() {
157 let theme = Theme::default();
158 assert_eq!(theme.status_bar.bg, Some(Color::DarkGray));
159 }
160}