hex_patch/app/settings/
color_settings.rs

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