diff options
author | Benjamin Nguyen <benjamin.van.nguyen@gmail.com> | 2023-11-29 15:49:41 -0800 |
---|---|---|
committer | Benjamin Nguyen <benjamin.van.nguyen@gmail.com> | 2023-11-29 15:49:41 -0800 |
commit | 867859b3ae2e3b6a7f68563477025bfd7bf2f1cf (patch) | |
tree | e5ed51cad794c3489baa47ba1e7ca11fe1aea83c | |
parent | 93d79b8a64d4fee8f8f404fb7b4f18cd27c25f44 (diff) |
suppress size algorithm
-rw-r--r-- | src/file/mod.rs | 10 | ||||
-rw-r--r-- | src/file/order.rs | 23 | ||||
-rw-r--r-- | src/file/tree/mod.rs | 115 | ||||
-rw-r--r-- | src/render/row/mod.rs | 4 | ||||
-rw-r--r-- | src/user/args.rs | 2 |
5 files changed, 86 insertions, 68 deletions
diff --git a/src/file/mod.rs b/src/file/mod.rs index 279b1f4..db1ba20 100644 --- a/src/file/mod.rs +++ b/src/file/mod.rs @@ -147,7 +147,10 @@ impl File { } pub fn display_path<'a>(&'a self, path_prefix: Option<&'a Path>) -> DisplayPath<'a> { - DisplayPath { file: self, path_prefix } + DisplayPath { + file: self, + path_prefix, + } } #[cfg(unix)] @@ -207,9 +210,10 @@ impl Display for DisplayPath<'_> { let display = match self.path_prefix { Some(prefix) => { let path = self.file.path(); - path.strip_prefix(prefix).map_or_else(|_| path.display(), |p| p.display()) + path.strip_prefix(prefix) + .map_or_else(|_| path.display(), |p| p.display()) }, - None => self.file.path().display() + None => self.file.path().display(), }; let link_target = self.file.symlink_target().map(|p| p.canonicalize()); diff --git a/src/file/order.rs b/src/file/order.rs index de22546..b3cd8a1 100644 --- a/src/file/order.rs +++ b/src/file/order.rs @@ -8,15 +8,11 @@ pub type FileComparator = dyn Fn(&File, &File) -> Ordering; /// Yields function pointer to the appropriate `File` comparator. pub fn comparator(sort: Sort, dir_order: DirOrder) -> Option<Box<FileComparator>> { match dir_order { - DirOrder::First if matches!(sort, Sort::None) => Some(Box::new(move |a, b| { - dir_first_comparator(a, b) - })), + DirOrder::First if matches!(sort, Sort::None) => Some(Box::new(dir_first_comparator)), DirOrder::First => Some(Box::new(move |a, b| { dir_first_comparator_with_fallback(a, b, base_comparator(sort)) })), - DirOrder::Last if matches!(sort, Sort::None) => Some(Box::new(move |a, b| { - dir_last_comparator(a, b) - })), + DirOrder::Last if matches!(sort, Sort::None) => Some(Box::new(dir_last_comparator)), DirOrder::Last => Some(Box::new(move |a, b| { dir_last_comparator_with_fallback(a, b, base_comparator(sort)) })), @@ -43,7 +39,7 @@ fn dir_first_comparator(a: &File, b: &File) -> Ordering { match (a.is_dir(), b.is_dir()) { (true, false) => Ordering::Greater, (false, true) => Ordering::Less, - _ => Ordering::Equal + _ => Ordering::Equal, } } @@ -61,14 +57,11 @@ fn dir_last_comparator_with_fallback( } /// Orders directories last relative to all other file-types. -fn dir_last_comparator( - a: &File, - b: &File, -) -> Ordering { +fn dir_last_comparator(a: &File, b: &File) -> Ordering { match (a.is_dir(), b.is_dir()) { (true, false) => Ordering::Less, (false, true) => Ordering::Greater, - _ => Ordering::Equal + _ => Ordering::Equal, } } @@ -90,9 +83,9 @@ fn base_comparator(sort_type: Sort) -> Box<FileComparator> { } mod time_stamping { - pub(self) use super::File; - pub(self) use core::cmp::Ordering; - pub(self) use std::time::SystemTime; + use super::File; + use core::cmp::Ordering; + use std::time::SystemTime; pub mod accessed { use super::*; diff --git a/src/file/tree/mod.rs b/src/file/tree/mod.rs index aaf2912..c805a27 100644 --- a/src/file/tree/mod.rs +++ b/src/file/tree/mod.rs @@ -1,8 +1,11 @@ -use super::order::{self, FileComparator}; +use super::order; use crate::{ error::prelude::*, file::File, - user::{args::{Layout, SortType, Sort}, column, Context}, + user::{ + args::{Layout, Sort, SortType}, + column, Context, + }, }; use ahash::{HashMap, HashSet}; use indextree::{Arena, NodeId}; @@ -128,9 +131,11 @@ impl Tree { comparator(node_a, node_b) }); - all_dirents.into_iter().for_each(|n| root_id.append(n, &mut arena)); - } - _ => { + all_dirents + .into_iter() + .for_each(|n| root_id.append(n, &mut arena)); + }, + _ => { for (dir_id, dirsize) in dirsize_map.into_iter() { let dir = arena[dir_id].get_mut(); *dir.size_mut() += dirsize; @@ -178,51 +183,72 @@ impl Tree { root_id, } = Self::load(ctx)?; - let mut dir_stack = vec![root_id]; - - 'outer: while let Some(node_id) = dir_stack.last() { - let current_dir = *node_id; - - let current_node_path = arena[current_dir].get().path(); - - let Some(dirents) = branches.get_mut(current_node_path) else { - dir_stack.pop(); - continue; + #[cfg(unix)] + macro_rules! update_metadata { + ($dirent_id:expr) => { + let dirent = arena[$dirent_id].get(); + if let Ok(inode) = dirent.inode() { + column_metadata.update_inode_attr_widths(&inode); + } }; + } - while let Some(dirent_node_id) = dirents.pop() { - current_dir.append(dirent_node_id, &mut arena); + match ctx.sort_type { + SortType::Flat if matches!(ctx.layout, Layout::Flat) => { + let mut all_dirents = branches + .values() + .flatten() + .filter_map(|n| (*n != root_id).then_some(*n)) + .collect::<Vec<_>>(); - let dirent_node = arena[dirent_node_id].get(); + if let Some(comparator) = order::comparator(Sort::None, ctx.dir_order) { + all_dirents.sort_by(|id_a, id_b| { + let node_a = arena[*id_a].get(); + let node_b = arena[*id_b].get(); + comparator(node_a, node_b) + }); + } - #[cfg(unix)] - match dirent_node.inode() { - Ok(value) => { - column_metadata.update_inode_attr_widths(&value); - value - }, - Err(err) => { - log::warn!( - "Failed to query inode of {}: {err}", - dirent_node.path().display(), - ); - continue; - }, - }; + for dirent_id in all_dirents { + root_id.append(dirent_id, &mut arena); - if dirent_node.file_type().is_some_and(|f| f.is_dir()) { - dir_stack.push(dirent_node_id); - continue 'outer; + #[cfg(unix)] + update_metadata!(dirent_id); } - } + }, + _ => { + let dirs = arena + .iter() + .filter_map(|node| { + if node.get().is_dir() { + arena + .get_node_id(node) + .map(|n| (node.get().path().to_path_buf(), n)) + } else { + None + } + }) + .collect::<Vec<_>>(); - dir_stack.pop(); - } + dirs.into_iter().for_each(|(path, dir)| { + if let Some(mut dirents) = branches.remove(&path) { + if let Some(comparator) = order::comparator(Sort::None, ctx.dir_order) { + dirents.sort_by(|id_a, id_b| { + let node_a = arena[*id_a].get(); + let node_b = arena[*id_b].get(); + comparator(node_a, node_b) + }); + } - if !matches!(ctx.sort, Sort::Size | Sort::Rsize) { - if let Some(comparator) = order::comparator(ctx.sort, ctx.dir_order) { - Self::tree_sort(root_id, &mut arena, comparator); - } + for dirent_id in dirents { + dir.append(dirent_id, &mut arena); + + #[cfg(unix)] + update_metadata!(dirent_id); + } + } + }); + }, } let tree = Self { root_id, arena }; @@ -291,11 +317,6 @@ impl Tree { pub fn arena(&self) -> &Arena<File> { &self.arena } - - /// Sort [`File`]s in the `arena` with the provided `comparator`. - pub fn tree_sort(root_id: NodeId, arena: &mut Arena<File>, comparator: Box<FileComparator>) { - todo!() - } } impl Deref for Tree { diff --git a/src/render/row/mod.rs b/src/render/row/mod.rs index f392340..f59fa91 100644 --- a/src/render/row/mod.rs +++ b/src/render/row/mod.rs @@ -77,7 +77,7 @@ pub fn formatter<'a>(buf: &'a mut String, ctx: &'a Context) -> Result<RowFormatt let long_format = long::Format::new(file, ctx); writeln!(buf, "{long_format} {prefix}{name}") })), - } + }, } } @@ -117,6 +117,6 @@ pub fn formatter<'a>(buf: &'a mut String, ctx: &'a Context) -> Result<RowFormatt writeln!(buf, "{size:>max_size_width$} {prefix}{name}") })) } - } + }, } } diff --git a/src/user/args.rs b/src/user/args.rs index 4484be4..06990c0 100644 --- a/src/user/args.rs +++ b/src/user/args.rs @@ -135,7 +135,7 @@ pub enum SortType { #[default] Tree, /// Sort directory entries relative to all directory entries - Flat + Flat, } /// How directories should be ordered relative to regular files. |