diff options
-rw-r--r-- | src/completion.rs | 20 | ||||
-rw-r--r-- | src/event_exec.rs | 2 | ||||
-rw-r--r-- | src/status.rs | 6 | ||||
-rw-r--r-- | src/tab.rs | 2 | ||||
-rw-r--r-- | src/tree.rs | 63 |
5 files changed, 48 insertions, 45 deletions
diff --git a/src/completion.rs b/src/completion.rs index 38ed615..e2da514 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -3,7 +3,7 @@ use std::fs::{self, ReadDir}; use anyhow::Result; use strum::IntoEnumIterator; -use crate::fileinfo::PathContent; +use crate::{fileinfo::PathContent, tree::Node}; /// Different kind of completions #[derive(Clone, Default, Copy)] @@ -215,18 +215,18 @@ impl Completion { pub fn search_from_tree( &mut self, input_string: &str, - content: &[&std::ffi::OsStr], + content: std::iter::FilterMap< + std::iter::FilterMap< + std::collections::hash_map::Keys<'_, std::path::PathBuf, Node>, + fn(&std::path::PathBuf) -> Option<&std::ffi::OsStr>, + >, + fn(&std::ffi::OsStr) -> Option<&str>, + >, ) -> Result<()> { self.update( content - .iter() - .filter(|&p| p.to_string_lossy().contains(input_string)) - .map(|p| { - p.to_string_lossy() - .into_owned() - .replace("▸ ", "") - .replace("▾ ", "") - }) + .filter(|&p| p.contains(input_string)) + .map(|p| p.replace("▸ ", "").replace("▾ ", "")) .collect(), ); diff --git a/src/event_exec.rs b/src/event_exec.rs index dd467dd..c1fcbe4 100644 --- a/src/event_exec.rs +++ b/src/event_exec.rs @@ -1450,7 +1450,7 @@ impl LeaveMode { /// Execute the selected node if it's a file else enter the directory. pub fn tree(status: &mut Status) -> Result<()> { - let path = status.selected_fileinfo()?.path; + let path = status.selected_non_mut().selected()?.path; let is_dir = path.is_dir(); if is_dir { status.selected().set_pathcontent(&path)?; diff --git a/src/status.rs b/src/status.rs index f0b9f01..68e940d 100644 --- a/src/status.rs +++ b/src/status.rs @@ -20,7 +20,7 @@ use crate::config::Settings; use crate::constant_strings_paths::{NVIM, SS, TUIS_PATH}; use crate::copy_move::{copy_move, CopyMove}; use crate::cryptsetup::{BlockDeviceAction, CryptoDeviceOpener}; -use crate::fileinfo::{FileInfo, FileKind}; +use crate::fileinfo::FileKind; use crate::flagged::Flagged; use crate::iso::IsoDevice; use crate::log_line; @@ -258,10 +258,6 @@ impl Status { &self.tabs[self.index] } - pub fn selected_fileinfo(&self) -> Result<FileInfo> { - self.selected_non_mut().selected() - } - /// Reset the view of every tab. pub fn reset_tabs_view(&mut self) -> Result<()> { for tab in self.tabs.iter_mut() { @@ -131,7 +131,7 @@ impl Tab { if matches!(self.previous_mode, Mode::Tree) => { self.completion - .search_from_tree(&self.input.string(), &self.tree.filenames()) + .search_from_tree(&self.input.string(), self.tree.filenames()) } Mode::InputCompleted(InputCompleted::Command) => { self.completion.command(&self.input.string()) diff --git a/src/tree.rs b/src/tree.rs index a3d5375..a44eea1 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,5 +1,8 @@ use std::{ + collections::hash_map, collections::HashMap, + ffi::OsStr, + iter::FilterMap, path::{Path, PathBuf}, }; @@ -45,7 +48,7 @@ pub struct Node { } impl Node { - pub fn new(path: &Path, children: Option<Vec<PathBuf>>) -> Self { + fn new(path: &Path, children: Option<Vec<PathBuf>>) -> Self { Self { path: path.to_owned(), children, @@ -54,23 +57,23 @@ impl Node { } } - pub fn fold(&mut self) { + fn fold(&mut self) { self.folded = true } - pub fn unfold(&mut self) { + fn unfold(&mut self) { self.folded = false } - pub fn toggle_fold(&mut self) { + fn toggle_fold(&mut self) { self.folded = !self.folded } - pub fn select(&mut self) { + fn select(&mut self) { self.selected = true } - pub fn unselect(&mut self) { + fn unselect(&mut self) { self.selected = false } @@ -82,12 +85,13 @@ impl Node { FileInfo::new(&self.path, users) } - pub fn color_effect(&self, users: &Users) -> Result<ColorEffect> { - Ok(ColorEffect::new(&self.fileinfo(users)?)) + fn set_children(&mut self, children: Option<Vec<PathBuf>>) { + self.children = children } - pub fn set_children(&mut self, children: Option<Vec<PathBuf>>) { - self.children = children + #[inline] + fn have_children(self: &Node) -> bool { + !self.folded && self.children.is_some() } } @@ -108,7 +112,7 @@ pub enum To<'a> { impl Go for Tree { fn go(&mut self, direction: To) { match direction { - To::Next => self.select_next().unwrap_or_else(|_| ()), + To::Next => self.select_next(), To::Prev => self.select_prev(), To::Root => self.select_root(), To::Last => self.select_last(), @@ -157,7 +161,9 @@ impl Tree { { sort_kind.sort(&mut files); let children = Self::make_children_and_stack_them(&mut stack, &files); - node.set_children(Some(children)); + if !children.is_empty() { + node.set_children(Some(children)); + } }; } last_path = node.path.to_owned(); @@ -240,17 +246,16 @@ impl Tree { } /// Select next sibling or the next sibling of the parent - pub fn select_next(&mut self) -> Result<()> { + pub fn select_next(&mut self) { if self.is_on_last() { self.select_root(); - return Ok(()); + return; } if let Some(next_path) = self.find_next_path() { let Some(next_node) = self.nodes.get_mut(&next_path) else { - return Ok(()); + return; }; - log::info!("selecting {next_node:?}"); next_node.select(); let Some(selected_node) = self.nodes.get_mut(&self.selected) else { unreachable!("current_node should be in nodes"); @@ -259,7 +264,6 @@ impl Tree { self.selected = next_path; self.increment_required_height() } - Ok(()) } // FIX: Still a problem when reaching max depth of tree, @@ -497,7 +501,7 @@ impl Tree { path, )); - if Self::have_interesting_children(path, node) { + if node.have_children() { Self::stack_children(&mut stack, prefix, node); } @@ -508,11 +512,19 @@ impl Tree { (selected_index, content) } - pub fn filenames(&self) -> Vec<&std::ffi::OsStr> { - self.nodes - .keys() - .filter_map(|path| path.file_name()) - .collect() + /// An (ugly) iterator over filenames. + /// It allows us to iter explicitely over filenames + /// while avoiding another allocation by collecting into a `Vec` + #[inline] + pub fn filenames( + &self, + ) -> FilterMap< + FilterMap<hash_map::Keys<'_, PathBuf, Node>, fn(&PathBuf) -> Option<&OsStr>>, + fn(&OsStr) -> Option<&str>, + > { + let to_filename: fn(&PathBuf) -> Option<&OsStr> = |path| path.file_name(); + let to_str: fn(&OsStr) -> Option<&str> = |filename| filename.to_str(); + self.nodes.keys().filter_map(to_filename).filter_map(to_str) } #[inline] @@ -537,11 +549,6 @@ impl Tree { stack.push((other_prefix.clone(), leaf)); } } - - #[inline] - fn have_interesting_children(current_path: &Path, current_node: &Node) -> bool { - current_path.is_dir() && !current_path.is_symlink() && !current_node.folded - } } #[inline] |