diff --git a/Cargo.toml b/Cargo.toml index faefeeb..1d7ff3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "calcifer" -version = "0.1.0" +version = "0.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -18,3 +18,4 @@ image = "0.24.8" serde = { version = "1.0.195", features = ["derive"] } serde_json = "1.0.111" + diff --git a/calcifer_save.json b/calcifer_save.json index d88d48c..e72f6c1 100644 --- a/calcifer_save.json +++ b/calcifer_save.json @@ -1 +1 @@ -{"tabs":["/home/penwing/Documents/projects/rust/calcifer/src/main.rs","/home/penwing/Documents/notes/victory2.txt"],"theme":6} \ No newline at end of file +{"tabs":["/home/penwing/Documents/projects/rust/calcifer/src/main.rs","/home/penwing/Documents/notes/victory2.txt","/home/penwing/Documents/projects/rust/calcifer/src/tools/search.rs"],"theme":6} \ No newline at end of file diff --git a/src/tools/mod.rs b/src/tools/mod.rs index 3099b5a..5ca8958 100644 --- a/src/tools/mod.rs +++ b/src/tools/mod.rs @@ -8,7 +8,7 @@ pub mod search; pub trait View { - fn ui(&mut self, ui: &mut egui::Ui); + fn ui(&mut self, ui: &mut egui::Ui, tabs: &mut Vec, selected_tab: &mut TabNumber); } /// Something to view @@ -26,7 +26,7 @@ pub trait Demo { } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum TabNumber { None, Open, diff --git a/src/tools/search.rs b/src/tools/search.rs index bca0b40..8757b19 100644 --- a/src/tools/search.rs +++ b/src/tools/search.rs @@ -2,7 +2,17 @@ use eframe::egui; use crate::tools::{View, Demo, Tab, TabNumber}; +enum Action { + Next, + Previous, + Replace, + None, +} + + +#[derive(Clone)] pub struct Selection { + pub tab: TabNumber, pub start: usize, pub end: usize, } @@ -11,6 +21,7 @@ pub struct Selection { impl Default for Selection { fn default() -> Self { Self { + tab: TabNumber::Zero, start: 0, end: 0, } @@ -20,7 +31,9 @@ impl Default for Selection { pub struct SearchWindow { search_text: String, - result: Selection, + searched_text: String, + results: Vec, + current_result: Selection, across_documents: bool, replace_text: String, } @@ -30,7 +43,9 @@ impl Default for SearchWindow { fn default() -> Self { Self { search_text: "".into(), - result: Selection::default(), + searched_text: "".into(), + results: vec![], + current_result: Selection::default(), across_documents: false, replace_text: "".into(), } @@ -48,29 +63,35 @@ impl Demo for SearchWindow { .open(open) .vscroll(true) .hscroll(true) - .show(ctx, |ui| self.ui(ui)); + .show(ctx, |ui| self.ui(ui, tabs, selected_tab)); } } impl View for SearchWindow { - fn ui(&mut self, ui: &mut egui::Ui) { + fn ui(&mut self, ui: &mut egui::Ui, tabs: &mut Vec, selected_tab: &mut TabNumber) { ui.set_min_width(250.0); + let mut action : Action = Action::None; + ui.horizontal(|ui| { let Self { search_text, .. } = self; ui.add(egui::TextEdit::singleline(search_text).desired_width(120.0).lock_focus(true)); - if ui.add(egui::Button::new("<")).clicked() { - self.find_previous(); - } + ui.label(format!("{} ", self.results.len())); - if ui.add(egui::Button::new(">")).clicked() { - self.find_next(); + if ui.add(egui::Button::new("<")).clicked() { + action = Action::Previous; + } else if ui.add(egui::Button::new(">")).clicked() { + action = Action::Next; } }); - + + let previous_bool_state = self.across_documents.clone(); ui.checkbox(&mut self.across_documents, "Across documents"); + if previous_bool_state != self.across_documents { + self.searched_text = "".into(); + } egui::CollapsingHeader::new("Replace") .default_open(false) @@ -79,23 +100,68 @@ impl View for SearchWindow { let Self { replace_text, .. } = self; ui.add(egui::TextEdit::singleline(replace_text).desired_width(120.0).lock_focus(true)); if ui.add(egui::Button::new("Replace")).clicked() { - self.replace_text(); + action = Action::Replace; } }); }); + + match action { + Action::Next => self.find_next(tabs, selected_tab), + Action::Previous => self.find_previous(tabs, selected_tab), + Action::Replace => self.replace(tabs, selected_tab), + Action::None => (), + } } } impl SearchWindow { - fn find_previous(&self) { - println!("Searched for previous"); + fn search(&mut self, tabs: &Vec, selected_tab: &TabNumber) { + let mut search_results: Vec = vec![]; + + if self.across_documents { + for (index, tab) in tabs.iter().enumerate() { + search_results.extend(self.match_text(tab.code.clone(), TabNumber::from_index(index))); + } + } else { + search_results.extend(self.match_text(tabs[TabNumber::to_index(&selected_tab.clone())].code.clone(), selected_tab.clone())); + } + + println!("Found {} results", search_results.len()); + self.searched_text = self.search_text.clone(); + self.results = search_results.clone(); + + if self.results.len() > 0 { + self.current_result = self.results[0].clone(); + } } - fn find_next(&self) { - println!("Searched for next"); + fn match_text(&self, tab_text: String, tab_number: TabNumber) -> Vec { + let matches = tab_text.match_indices(&self.search_text.clone()).map(|(i, _)| Selection { + tab : tab_number.clone(), + start: i, + end: i + self.search_text.len(), + }).collect(); + + matches } - fn replace_text(&self) { + fn find_next(&mut self, tabs: &Vec, selected_tab: &TabNumber) { + if self.searched_text != self.search_text && self.search_text.len() > 1 { + self.search(tabs, selected_tab); + } else { + println!("just need to get next result"); + } + } + + fn find_previous(&mut self, tabs: &Vec, selected_tab: &TabNumber) { + if self.searched_text != self.search_text && self.search_text.len() > 1 { + self.search(tabs, selected_tab); + } else { + println!("just need to get next result"); + } + } + + fn replace(&mut self, tabs: &Vec, selected_tab: &TabNumber) { println!("Searched to replace {} with {}", &self.search_text, &self.replace_text); } } \ No newline at end of file