From 891360678143c034ef75c3f3ebd62100987b3c11 Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Tue, 21 Mar 2023 09:07:37 +0100 Subject: [PATCH 1/7] Implement dirs-only option When dirs-only is enabled every node other than a directory will be skipped, and is not shown in the output. Closes #84. --- src/render/context/mod.rs | 4 ++++ src/render/tree/mod.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/render/context/mod.rs b/src/render/context/mod.rs index 50cb365a..6874e6c3 100644 --- a/src/render/context/mod.rs +++ b/src/render/context/mod.rs @@ -113,6 +113,10 @@ pub struct Context { #[arg(long)] /// Print completions for a given shell to stdout pub completions: Option, + + #[arg(short = 'D', long)] + /// Only show directories + pub dirs_only: bool, } impl Context { diff --git a/src/render/tree/mod.rs b/src/render/tree/mod.rs index 23998db1..f18fce98 100644 --- a/src/render/tree/mod.rs +++ b/src/render/tree/mod.rs @@ -89,6 +89,9 @@ impl Tree { let mut root_id = None; while let Ok(TraversalState::Ongoing(node)) = rx.recv() { + if ctx.dirs_only && !node.is_dir() { + continue + } if node.is_dir() { let node_path = node.path(); From 3448b39cae96155d67454e9c12e8303fe4576a07 Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Tue, 21 Mar 2023 20:34:26 +0100 Subject: [PATCH 2/7] Add unit test --- tests/dirs_only.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/dirs_only.rs diff --git a/tests/dirs_only.rs b/tests/dirs_only.rs new file mode 100644 index 00000000..92443ea3 --- /dev/null +++ b/tests/dirs_only.rs @@ -0,0 +1,24 @@ +use indoc::indoc; + +mod utils; + +#[test] +fn level() { + assert_eq!( + utils::run_cmd(&[ + "--sort", + "name", + "--no-config", + "--dirs-only", + "tests/data" + ]), + indoc!( + " + data + ├─ dream_cycle + ├─ lipsum + └─ the_yellow_king" + ), + "Failed to print dirs-only." + ) +} From 18e78771f9d1294b225edfa535a23955dc641344 Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Wed, 22 Mar 2023 17:03:06 +0100 Subject: [PATCH 3/7] fixup! Implement dirs-only option --- src/render/tree/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render/tree/mod.rs b/src/render/tree/mod.rs index f18fce98..16b5d252 100644 --- a/src/render/tree/mod.rs +++ b/src/render/tree/mod.rs @@ -89,9 +89,6 @@ impl Tree { let mut root_id = None; while let Ok(TraversalState::Ongoing(node)) = rx.recv() { - if ctx.dirs_only && !node.is_dir() { - continue - } if node.is_dir() { let node_path = node.path(); @@ -252,6 +249,9 @@ impl Display for Tree { ctx: &Context, f: &mut Formatter<'_>, ) -> fmt::Result { + if ctx.dirs_only && !node.is_dir() { + return Ok(()); + } if ctx.size_left && !ctx.suppress_size { node.display_size_left(f, base_prefix, ctx)?; } else { From aeaf10a126425a1defb244fbf86eb70527e58965 Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Wed, 22 Mar 2023 17:03:22 +0100 Subject: [PATCH 4/7] fixup! Add unit test --- tests/dirs_only.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/dirs_only.rs b/tests/dirs_only.rs index 92443ea3..96f89cdf 100644 --- a/tests/dirs_only.rs +++ b/tests/dirs_only.rs @@ -5,19 +5,13 @@ mod utils; #[test] fn level() { assert_eq!( - utils::run_cmd(&[ - "--sort", - "name", - "--no-config", - "--dirs-only", - "tests/data" - ]), + utils::run_cmd(&["--sort", "name", "--no-config", "--dirs-only", "tests/data"]), indoc!( " - data - ├─ dream_cycle - ├─ lipsum - └─ the_yellow_king" + data (1.21 KiB) + ├─ dream_cycle (308 B) + ├─ lipsum (446 B) + └─ the_yellow_king (143 B)" ), "Failed to print dirs-only." ) From 6c0d5983cbd9577cd9b0323720aafb10bcfd6d70 Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Thu, 23 Mar 2023 20:42:54 +0100 Subject: [PATCH 5/7] Revert "fixup! Implement dirs-only option" This reverts commit 18e78771f9d1294b225edfa535a23955dc641344. --- src/render/tree/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render/tree/mod.rs b/src/render/tree/mod.rs index 16b5d252..f18fce98 100644 --- a/src/render/tree/mod.rs +++ b/src/render/tree/mod.rs @@ -89,6 +89,9 @@ impl Tree { let mut root_id = None; while let Ok(TraversalState::Ongoing(node)) = rx.recv() { + if ctx.dirs_only && !node.is_dir() { + continue + } if node.is_dir() { let node_path = node.path(); @@ -249,9 +252,6 @@ impl Display for Tree { ctx: &Context, f: &mut Formatter<'_>, ) -> fmt::Result { - if ctx.dirs_only && !node.is_dir() { - return Ok(()); - } if ctx.size_left && !ctx.suppress_size { node.display_size_left(f, base_prefix, ctx)?; } else { From 333358631635562c3a3e31a56dc3725fdce9265e Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Thu, 23 Mar 2023 21:20:01 +0100 Subject: [PATCH 6/7] fixup! Implement dirs-only option --- src/render/tree/mod.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/render/tree/mod.rs b/src/render/tree/mod.rs index f18fce98..8c196a8d 100644 --- a/src/render/tree/mod.rs +++ b/src/render/tree/mod.rs @@ -89,9 +89,6 @@ impl Tree { let mut root_id = None; while let Ok(TraversalState::Ongoing(node)) = rx.recv() { - if ctx.dirs_only && !node.is_dir() { - continue - } if node.is_dir() { let node_path = node.path(); @@ -134,6 +131,10 @@ impl Tree { Self::prune_directories(root, &mut tree); } + if ctx.dirs_only { + Self::prune_files(root, &mut tree); + } + Ok::<(Arena, NodeId), Error>((tree, root)) }); @@ -215,6 +216,25 @@ impl Tree { node_id.remove_subtree(tree) } } + + /// Function to remove files. + fn prune_files(root_id: NodeId, tree: &mut Arena) { + let mut to_prune = vec![]; + + for node_id in root_id.descendants(tree) { + let node = Node::get(node_id, tree).unwrap(); + + if !node.is_dir() { + if node_id.children(tree).peekable().peek().is_none() { + to_prune.push(node_id); + } + } + } + + for node_id in to_prune { + node_id.remove_subtree(tree) + } + } } impl TryFrom<&Context> for WalkParallel { From cf40d392e4aabf8b4b559b393a3ac4473d29275f Mon Sep 17 00:00:00 2001 From: Andreas Linz Date: Thu, 23 Mar 2023 21:20:08 +0100 Subject: [PATCH 7/7] Fix typos --- src/render/tree/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/tree/mod.rs b/src/render/tree/mod.rs index 8c196a8d..558e85e0 100644 --- a/src/render/tree/mod.rs +++ b/src/render/tree/mod.rs @@ -70,7 +70,7 @@ impl Tree { /// Parallel traversal of the root directory and its contents. Parallel traversal relies on /// `WalkParallel`. Any filesystem I/O or related system calls are expected to occur during - /// parallel traversal; post-processing post-processing of all directory entries should + /// parallel traversal; post-processing of all directory entries should /// be completely CPU-bound. fn traverse(ctx: &Context) -> TreeResult<(Arena, NodeId)> { let walker = WalkParallel::try_from(ctx)?; @@ -83,7 +83,7 @@ impl Tree { // Key represents path of parent directory and values represent children. let mut branches: HashMap> = HashMap::new(); - // Set used to prevent double counting hard-links in the same file-tree hiearchy. + // Set used to prevent double counting hard-links in the same file-tree hierarchy. let mut inodes = HashSet::new(); let mut root_id = None;