use clap::Parser;
use dirwalk::output::{self, Format, GroupBy};
use dirwalk::{Sort, Threads, WalkBuilder};
use std::io::{self, BufWriter, Write};
use std::process;
#[derive(Parser)]
#[command(
name = "dirwalk",
about = "Platform-optimized recursive directory walker"
)]
struct Cli {
#[arg(default_value = ".")]
path: String,
#[arg(long)]
max_depth: Option<u32>,
#[arg(long)]
hidden: bool,
#[arg(long)]
gitignore: bool,
#[arg(long)]
follow_links: bool,
#[arg(long, value_delimiter = ',')]
extensions: Option<Vec<String>>,
#[arg(long)]
glob: Option<String>,
#[arg(long)]
min_size: Option<u64>,
#[arg(long)]
max_size: Option<u64>,
#[arg(long, value_enum)]
sort: Option<Sort>,
#[arg(long)]
dirs_first: bool,
#[arg(long, value_enum)]
group_by: Option<GroupBy>,
#[arg(long)]
stats: bool,
#[arg(long, value_enum, default_value = "plain")]
format: Format,
#[arg(long, default_value = "0")]
threads: Threads,
}
fn main() {
let cli = Cli::parse();
let mut builder = WalkBuilder::new(&cli.path)
.hidden(cli.hidden)
.follow_links(cli.follow_links)
.gitignore(cli.gitignore)
.stats(cli.stats)
.dirs_first(cli.dirs_first)
.threads(cli.threads);
if let Some(depth) = cli.max_depth {
builder = builder.max_depth(depth);
}
if let Some(ref exts) = cli.extensions {
builder = builder.extensions(exts);
}
if let Some(ref pattern) = cli.glob {
builder = match builder.glob(pattern) {
Ok(b) => b,
Err(e) => {
eprintln!("invalid glob pattern: {}", e);
process::exit(1);
}
};
}
if let Some(size) = cli.min_size {
builder = builder.min_size(size);
}
if let Some(size) = cli.max_size {
builder = builder.max_size(size);
}
if let Some(sort) = cli.sort {
builder = builder.sort(sort);
}
let result = match builder.build() {
Ok(r) => r,
Err(e) => {
eprintln!("error: {}", e);
process::exit(1);
}
};
let stdout = io::stdout().lock();
let mut w = BufWriter::new(stdout);
if let Err(e) = output::write_entries(&mut w, &result.entries, cli.format, cli.group_by) {
eprintln!("output error: {}", e);
process::exit(1);
}
if let Some(ref stats) = result.stats
&& let Err(e) = output::write_stats(&mut w, stats)
{
eprintln!("output error: {}", e);
process::exit(1);
}
if let Err(e) = w.flush() {
if e.kind() != std::io::ErrorKind::BrokenPipe {
eprintln!("output error: {}", e);
process::exit(1);
}
}
}