Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement dirs-only option #95

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/render/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ pub struct Context {
#[arg(long)]
/// Print completions for a given shell to stdout
pub completions: Option<clap_complete::Shell>,

#[arg(short = 'D', long)]
/// Only show directories
pub dirs_only: bool,
}

impl Context {
Expand Down
27 changes: 25 additions & 2 deletions src/render/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Node>, NodeId)> {
let walker = WalkParallel::try_from(ctx)?;
Expand All @@ -83,7 +83,7 @@ impl Tree {
// Key represents path of parent directory and values represent children.
let mut branches: HashMap<PathBuf, Vec<NodeId>> = 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;
Expand Down Expand Up @@ -131,6 +131,10 @@ impl Tree {
Self::prune_directories(root, &mut tree);
}

if ctx.dirs_only {
Self::prune_files(root, &mut tree);
}

Ok::<(Arena<Node>, NodeId), Error>((tree, root))
});

Expand Down Expand Up @@ -212,6 +216,25 @@ impl Tree {
node_id.remove_subtree(tree)
}
}

/// Function to remove files.
fn prune_files(root_id: NodeId, tree: &mut Arena<Node>) {
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 {
Expand Down
18 changes: 18 additions & 0 deletions tests/dirs_only.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use indoc::indoc;

mod utils;

#[test]
fn level() {
assert_eq!(
utils::run_cmd(&["--sort", "name", "--no-config", "--dirs-only", "tests/data"]),
indoc!(
"
data (1.21 KiB)
├─ dream_cycle (308 B)
├─ lipsum (446 B)
└─ the_yellow_king (143 B)"
),
"Failed to print dirs-only."
)
}