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 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            // null
282            0x00 => color_settings.hex_null,
283            // newline
284            0x0A | 0x0C | 0x0D => color_settings.hex_end_of_line,
285            // whitespace
286            0x20 | 0x09 | 0x0B => color_settings.hex_whitespace,
287            // numbers
288            0x30..=0x39 |
289            // uppercase
290            0x41..=0x5A |
291            // lowercase
292            0x61..=0x7A => color_settings.hex_alphanumeric,
293            // special characters
294            0x20..=0x7E => color_settings.hex_symbol,
295            _ => color_settings.hex_default
296        }
297    }
298}