diff --git a/src/app/state/config.rs b/src/app/state/config.rs index 6e6ca66..1613936 100644 --- a/src/app/state/config.rs +++ b/src/app/state/config.rs @@ -21,11 +21,11 @@ impl TextEditor { pub fn from_config_with_context(config: Config, cc: &eframe::CreationContext<'_>) -> Self { let mut editor = Self::from_config(config); - + if let Err(e) = editor.load_state_cache() { eprintln!("Failed to load state cache: {e}"); } - + theme::apply(editor.theme, &cc.egui_ctx); cc.egui_ctx.options_mut(|o| o.zoom_with_keyboard = false); diff --git a/src/app/state/state_cache.rs b/src/app/state/state_cache.rs index afc92fa..5912fa1 100644 --- a/src/app/state/state_cache.rs +++ b/src/app/state/state_cache.rs @@ -1,5 +1,5 @@ use super::editor::TextEditor; -use crate::app::tab::{Tab, compute_content_hash}; +use crate::app::tab::{compute_content_hash, Tab}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use uuid::Uuid; @@ -24,10 +24,10 @@ pub struct StateCache { fn create_diff_file(diff_content: &str) -> Result> { let diffs_dir = TextEditor::diffs_cache_dir().ok_or("Cannot determine cache directory")?; std::fs::create_dir_all(&diffs_dir)?; - + let diff_filename = format!("{}.diff", Uuid::new_v4()); let diff_path = diffs_dir.join(diff_filename); - + std::fs::write(&diff_path, diff_content)?; Ok(diff_path) } @@ -52,7 +52,7 @@ impl From<&Tab> for CachedTab { } else { None }; - + Self { diff_file, full_content: None, @@ -82,46 +82,49 @@ impl From for Tab { match load_diff_file(&diff_path) { Ok(diff_content) => { match diffy::Patch::from_str(&diff_content) { - Ok(patch) => { - match diffy::apply(&original_content, &patch) { - Ok(content) => content, - Err(_) => { - eprintln!("Warning: Failed to apply diff for {}, using original content", + Ok(patch) => match diffy::apply(&original_content, &patch) { + Ok(content) => content, + Err(_) => { + eprintln!("Warning: Failed to apply diff for {}, using original content", file_path.display()); - original_content - } + original_content } - } + }, Err(_) => { - eprintln!("Warning: Failed to parse diff for {}, using original content", - file_path.display()); + eprintln!( + "Warning: Failed to parse diff for {}, using original content", + file_path.display() + ); original_content } } } Err(e) => { - eprintln!("Warning: Failed to load diff file {:?}: {}, using original content", - diff_path, e); + eprintln!( + "Warning: Failed to load diff file {:?}: {}, using original content", + diff_path, e + ); original_content } } } else { original_content }; - - let original_hash = compute_content_hash(&std::fs::read_to_string(&file_path).unwrap_or_default()); + + let original_hash = + compute_content_hash(&std::fs::read_to_string(&file_path).unwrap_or_default()); let expected_hash = cached.original_content_hash; - + let mut tab = Tab::new_with_file(current_content, file_path); tab.title = cached.title; - + if original_hash != expected_hash { tab.is_modified = true; } else { tab.is_modified = cached.is_modified; tab.original_content_hash = cached.original_content_hash; } - + tab } else { let content = cached.full_content.unwrap_or_default(); @@ -160,7 +163,9 @@ impl TextEditor { Some(cache_dir.join("diffs")) } - fn cleanup_orphaned_diffs(active_diff_files: &[PathBuf]) -> Result<(), Box> { + fn cleanup_orphaned_diffs( + active_diff_files: &[PathBuf], + ) -> Result<(), Box> { if let Some(diffs_dir) = Self::diffs_cache_dir() { if diffs_dir.exists() { for entry in std::fs::read_dir(diffs_dir)? { @@ -183,7 +188,7 @@ impl TextEditor { } let cache_path = Self::state_cache_path().ok_or("Cannot determine cache directory")?; - + if !cache_path.exists() { return Ok(()); } @@ -193,7 +198,8 @@ impl TextEditor { if !state_cache.tabs.is_empty() { self.tabs = state_cache.tabs.into_iter().map(Tab::from).collect(); - self.active_tab_index = std::cmp::min(state_cache.active_tab_index, self.tabs.len() - 1); + self.active_tab_index = + std::cmp::min(state_cache.active_tab_index, self.tabs.len() - 1); self.tab_counter = state_cache.tab_counter; self.text_needs_processing = true; } @@ -218,7 +224,8 @@ impl TextEditor { tab_counter: self.tab_counter, }; - let active_diff_files: Vec = state_cache.tabs + let active_diff_files: Vec = state_cache + .tabs .iter() .filter_map(|tab| tab.diff_file.clone()) .collect(); @@ -236,13 +243,13 @@ impl TextEditor { std::fs::remove_file(cache_path)?; } } - + if let Some(diffs_dir) = Self::diffs_cache_dir() { if diffs_dir.exists() { let _ = std::fs::remove_dir_all(diffs_dir); } } - + Ok(()) } -} \ No newline at end of file +} diff --git a/src/app/state/tabs.rs b/src/app/state/tabs.rs index b491955..21e2e30 100644 --- a/src/app/state/tabs.rs +++ b/src/app/state/tabs.rs @@ -18,7 +18,7 @@ impl TextEditor { self.update_find_matches(); } self.text_needs_processing = true; - + if let Err(e) = self.save_state_cache() { eprintln!("Failed to save state cache: {e}"); } @@ -36,7 +36,7 @@ impl TextEditor { self.update_find_matches(); } self.text_needs_processing = true; - + if let Err(e) = self.save_state_cache() { eprintln!("Failed to save state cache: {e}"); } @@ -50,7 +50,7 @@ impl TextEditor { self.update_find_matches(); } self.text_needs_processing = true; - + if let Err(e) = self.save_state_cache() { eprintln!("Failed to save state cache: {e}"); } diff --git a/src/app/theme.rs b/src/app/theme.rs index afce1c2..7b1b271 100644 --- a/src/app/theme.rs +++ b/src/app/theme.rs @@ -1,7 +1,9 @@ use eframe::egui; use plist::{Dictionary, Value}; use std::collections::BTreeMap; -use syntect::highlighting::{Theme as SyntectTheme, ThemeSet, ThemeSettings, Color as SyntectColor, UnderlineOption}; +use syntect::highlighting::{ + Color as SyntectColor, Theme as SyntectTheme, ThemeSet, ThemeSettings, UnderlineOption, +}; #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize, Default)] pub enum Theme { @@ -233,11 +235,18 @@ pub fn create_code_theme_from_visuals(visuals: &egui::Visuals, font_size: f32) - blend_colors(egui::Color32::from_rgb(128, 0, 128), text_color, 0.8) // Purple-like }; - let plist_theme = build_custom_theme_plist("System", &format!("{:?}", bg_color), &format!("{:?}", text_color), &format!("{:?}", comment_color), &format!("{:?}", string_color), &format!("{:?}", keyword_color)); + let plist_theme = build_custom_theme_plist( + "System", + &format!("{:?}", bg_color), + &format!("{:?}", text_color), + &format!("{:?}", comment_color), + &format!("{:?}", string_color), + &format!("{:?}", keyword_color), + ); let file = std::fs::File::create("system.tmTheme").unwrap(); let writer = std::io::BufWriter::new(file); - let _ =plist::to_writer_xml(writer, &plist_theme); + let _ = plist::to_writer_xml(writer, &plist_theme); let loaded_file = std::fs::File::open("system.tmTheme").unwrap(); let mut loaded_reader = std::io::BufReader::new(loaded_file); @@ -245,7 +254,6 @@ pub fn create_code_theme_from_visuals(visuals: &egui::Visuals, font_size: f32) - let mut set = ThemeSet::new(); set.add_from_folder(".").unwrap(); return set; - } fn build_custom_theme_plist( @@ -263,16 +271,28 @@ fn build_custom_theme_plist( let mut global_settings_dict = Dictionary::new(); let mut inner_global_settings = Dictionary::new(); - inner_global_settings.insert("background".to_string(), Value::String(background_color.to_string())); - inner_global_settings.insert("foreground".to_string(), Value::String(foreground_color.to_string())); - global_settings_dict.insert("settings".to_string(), Value::Dictionary(inner_global_settings)); + inner_global_settings.insert( + "background".to_string(), + Value::String(background_color.to_string()), + ); + inner_global_settings.insert( + "foreground".to_string(), + Value::String(foreground_color.to_string()), + ); + global_settings_dict.insert( + "settings".to_string(), + Value::Dictionary(inner_global_settings), + ); settings_array.push(Value::Dictionary(global_settings_dict)); let mut comment_scope_dict = Dictionary::new(); comment_scope_dict.insert("name".to_string(), Value::String("Comment".to_string())); comment_scope_dict.insert("scope".to_string(), Value::String("comment".to_string())); let mut comment_settings = Dictionary::new(); - comment_settings.insert("foreground".to_string(), Value::String(comment_color.to_string())); + comment_settings.insert( + "foreground".to_string(), + Value::String(comment_color.to_string()), + ); comment_settings.insert("fontStyle".to_string(), Value::String("italic".to_string())); comment_scope_dict.insert("settings".to_string(), Value::Dictionary(comment_settings)); settings_array.push(Value::Dictionary(comment_scope_dict)); @@ -281,7 +301,10 @@ fn build_custom_theme_plist( string_scope_dict.insert("name".to_string(), Value::String("String".to_string())); string_scope_dict.insert("scope".to_string(), Value::String("string".to_string())); let mut string_settings = Dictionary::new(); - string_settings.insert("foreground".to_string(), Value::String(string_color.to_string())); + string_settings.insert( + "foreground".to_string(), + Value::String(string_color.to_string()), + ); string_scope_dict.insert("settings".to_string(), Value::Dictionary(string_settings)); settings_array.push(Value::Dictionary(string_scope_dict)); @@ -289,11 +312,14 @@ fn build_custom_theme_plist( keyword_scope_dict.insert("name".to_string(), Value::String("Keyword".to_string())); keyword_scope_dict.insert("scope".to_string(), Value::String("keyword".to_string())); let mut keyword_settings = Dictionary::new(); - keyword_settings.insert("foreground".to_string(), Value::String(keyword_color.to_string())); + keyword_settings.insert( + "foreground".to_string(), + Value::String(keyword_color.to_string()), + ); keyword_scope_dict.insert("settings".to_string(), Value::Dictionary(keyword_settings)); settings_array.push(Value::Dictionary(keyword_scope_dict)); root_dict.insert("settings".to_string(), Value::Array(settings_array)); Value::Dictionary(root_dict) -} \ No newline at end of file +} diff --git a/src/io.rs b/src/io.rs index d2ec674..7ee8e1c 100644 --- a/src/io.rs +++ b/src/io.rs @@ -43,7 +43,7 @@ pub(crate) fn open_file(app: &mut TextEditor) { if app.show_find && !app.find_query.is_empty() { app.update_find_matches(); } - + if let Err(e) = app.save_state_cache() { eprintln!("Failed to save state cache: {e}"); } @@ -85,7 +85,7 @@ pub(crate) fn save_to_path(app: &mut TextEditor, path: PathBuf) { active_tab.file_path = Some(path.to_path_buf()); active_tab.title = title.to_string(); active_tab.mark_as_saved(); - + if let Err(e) = app.save_state_cache() { eprintln!("Failed to save state cache: {e}"); } diff --git a/src/main.rs b/src/main.rs index 0a0716a..46402b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use std::io::IsTerminal; mod app; mod io; mod ui; -use app::{TextEditor, config::Config}; +use app::{config::Config, TextEditor}; fn main() -> eframe::Result { let _args: Vec = env::args().collect(); diff --git a/src/ui/central_panel.rs b/src/ui/central_panel.rs index 6f6e7e6..efb1e0a 100644 --- a/src/ui/central_panel.rs +++ b/src/ui/central_panel.rs @@ -1,7 +1,7 @@ mod editor; mod find_highlight; -mod line_numbers; mod languages; +mod line_numbers; use crate::app::TextEditor; use eframe::egui; diff --git a/src/ui/menu_bar.rs b/src/ui/menu_bar.rs index a7ff6cc..d37da87 100644 --- a/src/ui/menu_bar.rs +++ b/src/ui/menu_bar.rs @@ -185,7 +185,10 @@ pub(crate) fn menu_bar(app: &mut TextEditor, ctx: &egui::Context) { app.save_config(); ui.close_kind(UiKind::Menu); } - if ui.checkbox(&mut app.syntax_highlighting, "Syntax Highlighting").clicked() { + if ui + .checkbox(&mut app.syntax_highlighting, "Syntax Highlighting") + .clicked() + { app.save_config(); ui.close_kind(UiKind::Menu); } diff --git a/src/ui/preferences_window.rs b/src/ui/preferences_window.rs index b861684..54af9ce 100644 --- a/src/ui/preferences_window.rs +++ b/src/ui/preferences_window.rs @@ -26,16 +26,13 @@ pub(crate) fn preferences_window(app: &mut TextEditor, ctx: &egui::Context) { }) .show(ctx, |ui| { ui.vertical_centered(|ui| { - ui.heading("General Settings"); ui.add_space(8.0); ui.horizontal(|ui| { if ui .checkbox(&mut app.state_cache, "Cache State") - .on_hover_text( - "Unsaved changes will be cached between sessions" - ) + .on_hover_text("Unsaved changes will be cached between sessions") .changed() { app.save_config(); @@ -67,10 +64,7 @@ pub(crate) fn preferences_window(app: &mut TextEditor, ctx: &egui::Context) { ui.add_space(4.0); ui.horizontal(|ui| { - if ui - .checkbox(&mut app.word_wrap, "Word Wrap") - .changed() - { + if ui.checkbox(&mut app.word_wrap, "Word Wrap").changed() { app.save_config(); } }); @@ -92,7 +86,6 @@ pub(crate) fn preferences_window(app: &mut TextEditor, ctx: &egui::Context) { { app.save_config(); } - }); ui.add_space(12.0); diff --git a/src/ui/tab_bar.rs b/src/ui/tab_bar.rs index 86f631b..84f9583 100644 --- a/src/ui/tab_bar.rs +++ b/src/ui/tab_bar.rs @@ -39,7 +39,11 @@ pub(crate) fn tab_bar(app: &mut TextEditor, ctx: &egui::Context) { label_text = label_text.italics(); } - let tab_response = ui.add(egui::Label::new(label_text).selectable(false).sense(egui::Sense::click())); + let tab_response = ui.add( + egui::Label::new(label_text) + .selectable(false) + .sense(egui::Sense::click()), + ); if tab_response.clicked() { tab_to_switch = Some(i); } @@ -49,7 +53,10 @@ pub(crate) fn tab_bar(app: &mut TextEditor, ctx: &egui::Context) { let close_button = egui::Button::new("×") .small() .fill(visuals.panel_fill) - .stroke(egui::Stroke::new(0.0, egui::Color32::from_rgb(0, 0, 0))); + .stroke(egui::Stroke::new( + 0.0, + egui::Color32::from_rgb(0, 0, 0), + )); let close_response = ui.add(close_button); if close_response.clicked() { if *is_modified { @@ -90,5 +97,4 @@ pub(crate) fn tab_bar(app: &mut TextEditor, ctx: &egui::Context) { }); app.tab_bar_rect = Some(tab_bar.response.rect); - }