1use std::collections::HashMap;
2
3use ratatui::style::{Color, Modifier, Style};
4use serde::Serialize;
5use termbg::Theme;
6
7use crate::app::App;
8use crate::{EditColorSettings, RegisterColorSettings};
9
10use super::app_settings::AppSettings;
11use super::theme_preference::ThemePreference;
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
14#[derive(EditColorSettings!)]
15#[derive(RegisterColorSettings!)]
16pub struct ColorSettings {
17 pub address_selected: Style,
18 pub address_default: Style,
19
20 pub hex_selected: Style,
21 pub hex_null: Style,
22 pub hex_alphanumeric: Style,
23 pub hex_symbol: Style,
24 pub hex_end_of_line: Style,
25 pub hex_whitespace: Style,
26 pub hex_current_instruction: Style,
27 pub hex_current_section: Style,
28 pub hex_default: Style,
29
30 pub oneline_comment: Style,
31 pub pane_selected: Style,
32 pub pane: Style,
33
34 pub text_selected: Style,
35
36 pub assembly_symbol: Style,
37 pub assembly_selected: Style,
38 pub assembly_address: Style,
39 pub assembly_virtual_address: Style,
40 pub assembly_nop: Style,
41 pub assembly_bad: Style,
42 pub assembly_section: Style,
43 pub assembly_entry_point: Style,
44 pub assembly_comment: Style,
45 pub assembly_default: Style,
46
47 pub patch_patched_less_or_equal: Style,
48 pub patch_patched_greater: Style,
49 pub patch_old_instruction: Style,
50 pub patch_old_rest: Style,
51 pub patch_line_number: Style,
52
53 pub help_command: Style,
54 pub help_description: Style,
55
56 pub yes: Style,
57 pub yes_selected: Style,
58 pub no: Style,
59 pub no_selected: Style,
60 pub menu_text: Style,
61 pub menu_text_selected: Style,
62
63 pub insert_text_status: Style,
64
65 pub command_name: Style,
66 pub command_description: Style,
67 pub command_selected: Style,
68
69 pub path_dir: Style,
70 pub path_file: Style,
71 pub path_selected: Style,
72
73 pub log_info: Style,
74 pub log_debug: Style,
75 pub log_warning: Style,
76 pub log_error: Style,
77 pub log_message: Style,
78
79 pub status_bar: Style,
80 pub status_info: Style,
81 pub status_debug: Style,
82 pub status_warning: Style,
83 pub status_error: Style,
84
85 pub scrollbar: Style,
86 pub placeholder: Style,
87}
88
89impl ColorSettings {
90 pub fn get_default_theme(theme: Theme) -> Self {
91 match theme {
92 Theme::Light => Self::get_default_light_theme(),
93 Theme::Dark => Self::get_default_dark_theme(),
94 }
95 }
96
97 pub fn get_default_light_theme() -> Self {
98 let status_bar_bg = Color::Rgb(246, 184, 76);
99 let dark_yellow = Color::Rgb(243, 164, 27);
100 let light_brown = Color::Rgb(202, 123, 63);
101 let dark_orange = Color::Rgb(218, 152, 37);
102 let desaturated_dark_brown = Color::Rgb(98, 83, 75);
103 Self {
104 address_selected: Style::default().fg(Color::White).bg(Color::Black),
105 address_default: Style::default().fg(Color::Gray),
106
107 hex_selected: Style::default().fg(Color::White).bg(Color::Black),
108 hex_null: Style::default().fg(Color::Gray),
109 hex_alphanumeric: Style::default().fg(light_brown),
110 hex_symbol: Style::default().fg(light_brown).add_modifier(Modifier::DIM),
111 hex_end_of_line: Style::default().fg(Color::Red),
112 hex_whitespace: Style::default().fg(desaturated_dark_brown),
113 hex_current_instruction: Style::default().fg(Color::White).bg(dark_orange),
114 hex_current_section: Style::default().fg(Color::White).bg(dark_orange),
115 hex_default: Style::default(),
116
117 text_selected: Style::default().fg(Color::White).bg(Color::Black),
118 pane_selected: Style::default().fg(Color::LightGreen),
119 pane: Style::default().fg(Color::White),
120 oneline_comment: Style::default().fg(Color::Green),
121
122 assembly_symbol: Style::default().fg(Color::Green),
123 assembly_selected: Style::default().fg(Color::White).bg(Color::Black),
124 assembly_address: Style::default().fg(Color::Gray),
125 assembly_virtual_address: Style::default().fg(Color::Gray).add_modifier(Modifier::DIM),
126 assembly_nop: Style::default().fg(Color::Gray),
127 assembly_bad: Style::default().fg(Color::Red),
128 assembly_section: Style::default().fg(Color::Blue),
129 assembly_entry_point: Style::default().fg(dark_yellow),
130 assembly_comment: Style::default().fg(Color::LightGreen),
131 assembly_default: Style::default().fg(light_brown),
132
133 patch_patched_less_or_equal: Style::default().fg(Color::Green),
134 patch_patched_greater: Style::default().fg(dark_yellow),
135 patch_old_instruction: Style::default().fg(Color::Red),
136 patch_old_rest: Style::default().fg(Color::Gray),
137 patch_line_number: Style::default().fg(Color::Gray),
138
139 help_command: Style::default().fg(Color::Green),
140 help_description: Style::default().fg(Color::DarkGray),
141
142 yes: Style::default().fg(Color::Green),
143 yes_selected: Style::default().fg(Color::White).bg(Color::Green),
144 no: Style::default().fg(Color::Red),
145 no_selected: Style::default().fg(Color::White).bg(Color::Red),
146 menu_text: Style::default().fg(Color::Black),
147 menu_text_selected: Style::default().fg(Color::White).bg(Color::Black),
148
149 insert_text_status: Style::default().fg(Color::Black).bg(status_bar_bg),
150
151 command_name: Style::default().fg(Color::Green),
152 command_description: Style::default().fg(Color::DarkGray),
153 command_selected: Style::default().fg(Color::White).bg(Color::Black),
154
155 path_dir: Style::default().fg(Color::Blue),
156 path_file: Style::default().fg(dark_yellow),
157 path_selected: Style::default().fg(Color::White).bg(Color::Black),
158
159 log_info: Style::default().fg(Color::Blue),
160 log_debug: Style::default().fg(Color::Green),
161 log_warning: Style::default().fg(dark_yellow),
162 log_error: Style::default().fg(Color::Red),
163 log_message: Style::default().fg(Color::Black),
164
165 status_bar: Style::default().fg(Color::Black).bg(status_bar_bg),
166 status_info: Style::default().fg(Color::Blue).bg(status_bar_bg),
167 status_debug: Style::default().fg(Color::Green).bg(status_bar_bg),
168 status_warning: Style::default().fg(Color::Yellow).bg(status_bar_bg),
169 status_error: Style::default().fg(Color::Red).bg(status_bar_bg),
170
171 scrollbar: Style::default().fg(status_bar_bg).bg(Color::Gray),
172 placeholder: Style::default().fg(Color::Gray),
173 }
174 }
175
176 pub fn get_default_dark_theme() -> Self {
177 let status_bar_bg = Color::Rgb(255, 223, 168);
178 Self {
179 address_selected: Style::default().fg(Color::Black).bg(Color::White),
180 address_default: Style::default().fg(Color::DarkGray),
181
182 hex_selected: Style::default().fg(Color::Black).bg(Color::White),
183 hex_null: Style::default().fg(Color::DarkGray),
184 hex_alphanumeric: Style::default().fg(Color::Rgb(204, 152, 113)),
185 hex_symbol: Style::default()
186 .fg(Color::Rgb(204, 152, 113))
187 .add_modifier(Modifier::DIM),
188 hex_end_of_line: Style::default().fg(Color::LightRed),
189 hex_whitespace: Style::default().fg(Color::Rgb(244, 202, 183)),
190 hex_current_instruction: Style::default()
191 .fg(Color::Black)
192 .bg(Color::Rgb(215, 170, 92)),
193 hex_current_section: Style::default()
194 .fg(Color::Black)
195 .bg(Color::Rgb(215, 170, 92)),
196 hex_default: Style::default(),
197
198 text_selected: Style::default().fg(Color::Black).bg(Color::White),
199 pane_selected: Style::default().fg(Color::LightGreen),
200 pane: Style::default().fg(Color::White),
201 oneline_comment: Style::default().fg(Color::LightGreen),
202
203 assembly_symbol: Style::default().fg(Color::LightGreen),
204 assembly_selected: Style::default().fg(Color::Black).bg(Color::White),
205 assembly_address: Style::default().fg(Color::DarkGray),
206 assembly_virtual_address: Style::default()
207 .fg(Color::DarkGray)
208 .add_modifier(Modifier::DIM),
209 assembly_nop: Style::default().fg(Color::DarkGray),
210 assembly_bad: Style::default().fg(Color::LightRed),
211 assembly_section: Style::default().fg(Color::LightBlue),
212 assembly_entry_point: Style::default().fg(Color::Yellow),
213 assembly_comment: Style::default().fg(Color::Green),
214 assembly_default: Style::default().fg(Color::Rgb(204, 152, 113)),
215
216 patch_patched_less_or_equal: Style::default().fg(Color::Green),
217 patch_patched_greater: Style::default().fg(Color::Yellow),
218 patch_old_instruction: Style::default().fg(Color::Red),
219 patch_old_rest: Style::default().fg(Color::DarkGray),
220 patch_line_number: Style::default().fg(Color::DarkGray),
221
222 help_command: Style::default().fg(Color::LightGreen),
223 help_description: Style::default().fg(Color::Gray),
224
225 yes: Style::default().fg(Color::Green),
226 yes_selected: Style::default().fg(Color::Black).bg(Color::Green),
227 no: Style::default().fg(Color::Red),
228 no_selected: Style::default().fg(Color::Black).bg(Color::Red),
229 menu_text: Style::default().fg(Color::White),
230 menu_text_selected: Style::default().fg(Color::Black).bg(Color::White),
231
232 insert_text_status: Style::default().fg(Color::Black).bg(status_bar_bg),
233
234 command_name: Style::default().fg(Color::LightGreen),
235 command_description: Style::default().fg(Color::Gray),
236 command_selected: Style::default().fg(Color::Black).bg(Color::White),
237
238 path_dir: Style::default().fg(Color::Blue),
239 path_file: Style::default().fg(Color::Yellow),
240 path_selected: Style::default().fg(Color::Black).bg(Color::White),
241
242 log_info: Style::default().fg(Color::LightBlue),
243 log_debug: Style::default().fg(Color::LightGreen),
244 log_warning: Style::default().fg(Color::Yellow),
245 log_error: Style::default().fg(Color::Red),
246 log_message: Style::default().fg(Color::White),
247
248 status_bar: Style::default().fg(Color::Black).bg(status_bar_bg),
249 status_info: Style::default().fg(Color::Blue).bg(status_bar_bg),
250 status_debug: Style::default().fg(Color::Green).bg(status_bar_bg),
251 status_warning: Style::default().fg(Color::Yellow).bg(status_bar_bg),
252 status_error: Style::default().fg(Color::Red).bg(status_bar_bg),
253
254 scrollbar: Style::default().fg(status_bar_bg).bg(Color::DarkGray),
255 placeholder: Style::default().fg(Color::DarkGray),
256 }
257 }
258
259 pub fn from_map(
260 map: &HashMap<String, Style>,
261 app_settings: &AppSettings,
262 terminal_theme: Theme,
263 ) -> Result<Self, String> {
264 let theme = match &app_settings.theme {
265 ThemePreference::Light => Theme::Light,
266 ThemePreference::Dark => Theme::Dark,
267 ThemePreference::Auto => terminal_theme,
268 };
269 let mut color_settings = Self::get_default_theme(theme);
270 color_settings
271 .edit_color_settings(map)
272 .map_err(|e| format!("Failed to load color settings: {}", e))?;
273 Ok(color_settings)
274 }
275}
276
277impl App {
278 pub(in crate::app) fn get_style_for_byte(color_settings: &ColorSettings, byte: u8) -> Style {
279 match byte
280 {
281 0x00 => color_settings.hex_null,
283 0x0A | 0x0C | 0x0D => color_settings.hex_end_of_line,
285 0x20 | 0x09 | 0x0B => color_settings.hex_whitespace,
287 0x30..=0x39 |
289 0x41..=0x5A |
291 0x61..=0x7A => color_settings.hex_alphanumeric,
293 0x20..=0x7E => color_settings.hex_symbol,
295 _ => color_settings.hex_default
296 }
297 }
298}