diff options
-rw-r--r-- | src/app/status.rs | 5 | ||||
-rw-r--r-- | src/app/tab.rs | 11 | ||||
-rw-r--r-- | src/event/event_dispatch.rs | 4 | ||||
-rw-r--r-- | src/modes/display/directory.rs | 12 | ||||
-rw-r--r-- | src/modes/display/fileinfo.rs | 8 | ||||
-rw-r--r-- | src/modes/display/tree.rs | 24 | ||||
-rw-r--r-- | src/modes/edit/flagged.rs | 7 | ||||
-rw-r--r-- | src/modes/edit/leave_mode.rs | 2 | ||||
-rw-r--r-- | src/modes/edit/menu.rs | 21 | ||||
-rw-r--r-- | src/modes/edit/mod.rs | 2 | ||||
-rw-r--r-- | src/modes/edit/search.rs | 51 | ||||
-rw-r--r-- | src/modes/edit/selectable_content.rs | 4 |
12 files changed, 79 insertions, 72 deletions
diff --git a/src/app/status.rs b/src/app/status.rs index 3b7fb70..37da0ed 100644 --- a/src/app/status.rs +++ b/src/app/status.rs @@ -1164,11 +1164,6 @@ impl Status { self.set_edit_mode(self.index, Edit::InputSimple(InputSimple::Chmod)) } - /// Add a char to input string, look for a possible completion. - pub fn input_complete(&mut self, c: char) -> Result<()> { - self.menu.input_complete(c, &self.tabs[self.index]) - } - /// Execute a custom event on the selected file pub fn run_custom_command(&mut self, string: &str) -> Result<()> { log_info!("custom {string}"); diff --git a/src/app/tab.rs b/src/app/tab.rs index 875ade8..0d2cfb8 100644 --- a/src/app/tab.rs +++ b/src/app/tab.rs @@ -205,17 +205,6 @@ impl Tab { path_to_string(&self.directory.path) } - /// Returns a vector of filenames as strings, which contains the input string. - /// Empty vector while in `Display::Preview`. - pub fn filenames_matching(&self, input_string: &str) -> Vec<String> { - match self.display_mode { - Display::Directory => self.directory.filenames_matching(input_string), - Display::Tree => self.tree.filenames_matching(input_string), - Display::Preview => vec![], - Display::Flagged => vec![], - } - } - /// Refresh everything but the view pub fn refresh_params(&mut self) -> Result<()> { self.preview = Preview::empty(); diff --git a/src/event/event_dispatch.rs b/src/event/event_dispatch.rs index 5962b2a..c1b47cb 100644 --- a/src/event/event_dispatch.rs +++ b/src/event/event_dispatch.rs @@ -79,7 +79,9 @@ impl EventDispatcher { Edit::InputSimple(InputSimple::Sort) => status.sort(c), Edit::InputSimple(InputSimple::RegexMatch) => status.input_regex(c), Edit::InputSimple(_) => status.menu.input_insert(c), - Edit::InputCompleted(_) => status.input_complete(c), + Edit::InputCompleted(_) => status + .menu + .input_complete(c, &mut status.tabs[status.index]), Edit::NeedConfirmation(confirmed_action) => status.confirm(c, confirmed_action), Edit::Navigate(navigate) => Self::navigate_char(navigate, status, c), Edit::Nothing if matches!(tab.display_mode, Display::Preview) => { diff --git a/src/modes/display/directory.rs b/src/modes/display/directory.rs index bb42976..51b16c6 100644 --- a/src/modes/display/directory.rs +++ b/src/modes/display/directory.rs @@ -244,20 +244,8 @@ impl Directory { .map(|fileinfo| fileinfo.path.borrow()) .collect() } - - pub fn filenames_matching(&self, input_string: &str) -> Vec<String> { - let Ok(re) = regex::Regex::new(input_string) else { - return vec![]; - }; - self.content - .iter() - .filter(|f| re.is_match(&f.filename)) - .map(|f| f.filename.to_string()) - .collect() - } } -// impl_selectable_content!(FileInfo, Directory); impl_selectable!(Directory); impl_content!(FileInfo, Directory); diff --git a/src/modes/display/fileinfo.rs b/src/modes/display/fileinfo.rs index b649989..194f0a7 100644 --- a/src/modes/display/fileinfo.rs +++ b/src/modes/display/fileinfo.rs @@ -11,9 +11,9 @@ use tuikit::prelude::{Attr, Color, Effect}; use crate::common::PERMISSIONS_STR; use crate::config::extension_color; use crate::config::COLORS; -use crate::modes::Users; use crate::modes::MAX_MODE; use crate::modes::{human_size, read_symlink_dest}; +use crate::modes::{ToPath, Users}; type Valid = bool; @@ -468,3 +468,9 @@ fn filekind_and_filename(filename: &str, file_kind: &FileKind<Valid>) -> std::sy fn is_valid_symlink(path: &path::Path) -> bool { matches!(std::fs::read_link(path), Ok(dest) if dest.exists()) } + +impl ToPath for FileInfo { + fn to_path(&self) -> &path::Path { + self.path.as_ref() + } +} diff --git a/src/modes/display/tree.rs b/src/modes/display/tree.rs index aafc3b2..76238b8 100644 --- a/src/modes/display/tree.rs +++ b/src/modes/display/tree.rs @@ -1,6 +1,5 @@ use std::borrow::Borrow; use std::collections::HashMap; -use std::ffi::OsStr; use std::path::Path; use std::sync::Arc; @@ -12,6 +11,7 @@ use crate::modes::files_collection; use crate::modes::FilterKind; use crate::modes::Flagged; use crate::modes::SortKind; +use crate::modes::ToPath; use crate::modes::Users; use crate::modes::{ColorEffect, FileInfo}; @@ -628,22 +628,6 @@ impl Tree { &self.displayable_lines } - #[inline] - pub fn filenames_matching(&self, input_string: &str) -> Vec<String> { - let to_filename: fn(&Arc<Path>) -> Option<&OsStr> = |path| path.file_name(); - let to_str: fn(&OsStr) -> Option<&str> = |filename| filename.to_str(); - let Ok(re) = regex::Regex::new(input_string) else { - return vec![]; - }; - self.nodes - .keys() - .filter_map(to_filename) - .filter_map(to_str) - .filter(|&p| re.is_match(p)) - .map(|p| p.replace("▸ ", "").replace("▾ ", "")) - .collect() - } - /// Vector of `Path` of nodes. pub fn paths(&self) -> Vec<&Path> { self.nodes.keys().map(|p| p.borrow()).collect() @@ -839,3 +823,9 @@ impl TreeLineBuilder { self.color_effect.effect = tuikit::attr::Effect::REVERSE; } } + +impl ToPath for TreeLineBuilder { + fn to_path(&self) -> &Path { + &self.path + } +} diff --git a/src/modes/edit/flagged.rs b/src/modes/edit/flagged.rs index 7525b52..aaa09dd 100644 --- a/src/modes/edit/flagged.rs +++ b/src/modes/edit/flagged.rs @@ -4,6 +4,7 @@ use std::path::{Path, PathBuf}; use crate::impl_content; use crate::impl_selectable; use crate::modes::ContentWindow; +use crate::modes::ToPath; #[derive(Clone, Debug)] pub struct Flagged { @@ -183,6 +184,10 @@ impl Flagged { } } -// impl_selectable_content!(PathBuf, Flagged); +impl ToPath for PathBuf { + fn to_path(&self) -> &Path { + self.as_ref() + } +} impl_selectable!(Flagged); impl_content!(PathBuf, Flagged); diff --git a/src/modes/edit/leave_mode.rs b/src/modes/edit/leave_mode.rs index d96efb9..524f776 100644 --- a/src/modes/edit/leave_mode.rs +++ b/src/modes/edit/leave_mode.rs @@ -255,7 +255,7 @@ impl LeaveMode { status.current_tab_mut().search = Search::default(); return Ok(()); } - let Ok(search) = Search::new(searched) else { + let Ok(mut search) = Search::new(searched) else { status.current_tab_mut().search = Search::default(); return Ok(()); }; diff --git a/src/modes/edit/menu.rs b/src/modes/edit/menu.rs index 85f7730..01b7795 100644 --- a/src/modes/edit/menu.rs +++ b/src/modes/edit/menu.rs @@ -112,14 +112,14 @@ impl Menu { } /// Fill the input string with the currently selected completion. - pub fn input_complete(&mut self, c: char, tab: &Tab) -> Result<()> { + pub fn input_complete(&mut self, c: char, tab: &mut Tab) -> Result<()> { self.input.insert(c); self.fill_completion(tab)?; self.window.reset(self.completion.len()); Ok(()) } - fn fill_completion(&mut self, tab: &Tab) -> Result<()> { + fn fill_completion(&mut self, tab: &mut Tab) -> Result<()> { match tab.edit_mode { Edit::InputCompleted(InputCompleted::Cd) => self.completion.cd( &self.input.string(), @@ -129,16 +129,13 @@ impl Menu { self.completion.exec(&self.input.string()) } Edit::InputCompleted(InputCompleted::Search) => { - match tab.display_mode { - Display::Tree | Display::Directory => { - self.completion - .search(tab.filenames_matching(&self.input.string())); - } - Display::Flagged => self - .completion - .search(self.flagged.filenames_matching(&self.input.string())), - _ => (), - } + let files = match tab.display_mode { + Display::Preview => vec![], + Display::Tree => tab.search.complete_tree(&tab.tree), + Display::Flagged => tab.search.complete_flagged(&self.flagged), + Display::Directory => tab.search.complete_directory(tab), + }; + self.completion.search(files); Ok(()) } Edit::InputCompleted(InputCompleted::Action) => { diff --git a/src/modes/edit/mod.rs b/src/modes/edit/mod.rs index 1ddb6a2..6906bc2 100644 --- a/src/modes/edit/mod.rs +++ b/src/modes/edit/mod.rs @@ -62,7 +62,7 @@ pub use regex::regex_matcher; pub use removable_devices::RemovableDevices; pub use search::Search; pub use second_line::SecondLine; -pub use selectable_content::{Content, Selectable}; +pub use selectable_content::{Content, Selectable, ToPath}; pub use shell_parser::ShellCommandParser; pub use shortcut::Shortcut; pub use sort::SortKind; diff --git a/src/modes/edit/search.rs b/src/modes/edit/search.rs index d0aaf49..a2c04d3 100644 --- a/src/modes/edit/search.rs +++ b/src/modes/edit/search.rs @@ -2,30 +2,22 @@ use anyhow::Result; use crate::{ app::{Status, Tab}, - modes::{Display, Flagged, Go, To, Tree}, + modes::{Content, Display, Flagged, Go, To, ToPath, Tree}, }; #[derive(Clone, Debug, Default)] pub struct Search { pub regex: Option<regex::Regex>, - index: Option<usize>, - nb_matches: Option<usize>, } impl Search { pub fn new(searched: &str) -> Result<Self> { Ok(Self { regex: regex::Regex::new(searched).ok(), - index: None, - nb_matches: None, }) } - pub fn complete(&mut self) -> Result<()> { - Ok(()) - } - - pub fn leave(&self, status: &mut Status) -> Result<()> { + pub fn leave(&mut self, status: &mut Status) -> Result<()> { match status.current_tab().display_mode { Display::Tree => { self.tree(&mut status.current_tab_mut().tree); @@ -152,4 +144,43 @@ impl Search { flagged.select_index(position); } } + + pub fn complete_flagged(&self, flagged: &Flagged) -> Vec<String> { + self.filtered_paths(flagged.content()) + .iter() + .filter_map(|p| p.file_name()) + .map(|s| s.to_string_lossy().to_string()) + .collect() + } + + pub fn complete_tree(&self, tree: &Tree) -> Vec<String> { + self.filtered_paths(tree.displayable().lines()) + .iter() + .filter_map(|p| p.file_name()) + .map(|s| s.to_string_lossy().to_string()) + .collect() + } + + pub fn complete_directory(&self, tab: &Tab) -> Vec<String> { + self.filtered_paths(tab.directory.content()) + .iter() + .filter_map(|p| p.file_name()) + .map(|s| s.to_string_lossy().to_string()) + .collect() + } + + pub fn filtered_paths(&self, content: &Vec<impl ToPath>) -> Vec<std::path::PathBuf> { + if let Some(re) = &self.regex { + content + .iter() + .map(|elt| elt.to_path()) + .filter(|p| { + re.is_match(p.file_name().unwrap_or_default().to_string_lossy().as_ref()) + }) + .map(|p| p.to_owned()) + .collect() + } else { + vec![] + } + } } diff --git a/src/modes/edit/selectable_content.rs b/src/modes/edit/selectable_content.rs index 3374104..d953cf4 100644 --- a/src/modes/edit/selectable_content.rs +++ b/src/modes/edit/selectable_content.rs @@ -24,6 +24,10 @@ pub trait Content<T>: Selectable { /// [`tuikit::attr:Attr`] used to display an element fn attr(&self, index: usize, attr: &tuikit::attr::Attr) -> tuikit::attr::Attr; } + +pub trait ToPath { + fn to_path(&self) -> &std::path::Path; +} /// Implement the `SelectableContent` for struct `$struc` with content type `$content_type`. /// This trait allows to navigate through a vector of element `content_type`. /// It implements: `is_empty`, `len`, `next`, `prev`, `selected`. |