summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/app/status.rs5
-rw-r--r--src/app/tab.rs11
-rw-r--r--src/event/event_dispatch.rs4
-rw-r--r--src/modes/display/directory.rs12
-rw-r--r--src/modes/display/fileinfo.rs8
-rw-r--r--src/modes/display/tree.rs24
-rw-r--r--src/modes/edit/flagged.rs7
-rw-r--r--src/modes/edit/leave_mode.rs2
-rw-r--r--src/modes/edit/menu.rs21
-rw-r--r--src/modes/edit/mod.rs2
-rw-r--r--src/modes/edit/search.rs51
-rw-r--r--src/modes/edit/selectable_content.rs4
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`.