Skip to content

Commit

Permalink
feat: add support for -d
Browse files Browse the repository at this point in the history
- only list directories by using `-d` flag
  • Loading branch information
sk314e committed Aug 28, 2024
1 parent 640b050 commit abb2a52
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 27 deletions.
19 changes: 14 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::path::Path;
use globset::Glob;
use term::TerminfoTerminal;

#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Parser)]
struct Args {
/// Show hidden files
Expand All @@ -38,6 +39,9 @@ struct Args {
/// Descend only <level> directories deep
#[clap(short = 'L', long = "level", default_value_t = usize::max_value())]
max_level: usize,
/// List directories only
#[clap(short = 'd', default_value = "false")]
only_dirs: bool,
}

impl TryFrom<&Args> for Config {
Expand All @@ -55,6 +59,7 @@ impl TryFrom<&Args> for Config {
Ok(Config {
use_color: value.color_on || !value.color_off,
show_hidden: value.show_all,
show_only_dirs: value.only_dirs,
max_level: value.max_level,
include_glob,
})
Expand All @@ -75,11 +80,15 @@ fn main() -> Result<(), Box<dyn Error>> {
.map_err(|e| format!("Program failed with error: {e}"))?
};

writeln!(
&mut term,
"\n{} directories, {} files",
summary.num_folders, summary.num_files
)
if args.only_dirs {
writeln!(&mut term, "\n{} directories", summary.num_folders)
} else {
writeln!(
&mut term,
"\n{} directories, {} files",
summary.num_folders, summary.num_files
)
}
.map_err(|e| format!("Failed to print summary: {e}"))?;

Ok(())
Expand Down
49 changes: 27 additions & 22 deletions src/pathiterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl IteratorItem {
#[derive(Debug)]
pub struct FileIteratorConfig {
pub show_hidden: bool,
pub show_only_dirs: bool,
pub max_level: usize,
pub include_glob: Option<GlobMatcher>,
}
Expand All @@ -57,9 +58,18 @@ fn order_dir_entry(a: &DirEntry, b: &DirEntry) -> Ordering {
b.file_name().cmp(&a.file_name())
}

fn get_sorted_dir_entries(path: &Path) -> io::Result<Vec<DirEntry>> {
fn get_sorted_dir_entries(path: &Path, only_dirs: bool) -> io::Result<Vec<DirEntry>> {
let entries = fs::read_dir(path)?;
let mut dir_entries: Vec<DirEntry> = entries.into_iter().collect::<io::Result<Vec<_>>>()?;
let mut dir_entries: Vec<DirEntry> = entries
.into_iter()
.filter(|entry| {
entry.as_ref().is_ok_and(|entry| {
entry
.metadata()
.is_ok_and(|meta| !only_dirs || meta.is_dir())
})
})
.collect::<io::Result<Vec<_>>>()?;
dir_entries.sort_by(order_dir_entry);
Ok(dir_entries)
}
Expand All @@ -79,29 +89,24 @@ impl FileIterator {
}

fn is_included(&self, name: &str, is_dir: bool) -> bool {
(!name.starts_with('.') && self.config.show_hidden) || is_dir || self.is_glob_included(name)
(self.config.show_hidden || !name.starts_with('.'))
&& (is_dir || self.is_glob_included(name))
}

fn push_dir(&mut self, item: &IteratorItem) {
let entries = get_sorted_dir_entries(&item.path).unwrap_or_else(|_| {
panic!(
"Couldn't retrieve files in directory: {}",
item.path.display()
)
});

let mut entries: Vec<IteratorItem> = entries
.iter()
.map(|e| IteratorItem::new(&e.path(), item.level + 1, false))
.filter(|item| self.is_included(&item.file_name, item.is_dir()))
.collect();

if let Some(item) = entries.first_mut() {
item.is_last = true;
}

for item in entries {
self.queue.push_back(item);
let entries = get_sorted_dir_entries(&item.path, self.config.show_only_dirs)
.unwrap_or_else(|_| {
panic!(
"Couldn't retrieve files in directory: {}",
item.path.display()
)
});

for (index, entry) in entries.iter().enumerate() {
let item = IteratorItem::new(&entry.path(), item.level + 1, index == 0);
if self.is_included(&item.file_name, item.is_dir()) {
self.queue.push_back(item);
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/tree_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ fn is_executable(metadata: &Metadata) -> bool {
pub struct Config {
pub use_color: bool,
pub show_hidden: bool,
pub show_only_dirs: bool,
pub max_level: usize,
pub include_glob: Option<GlobMatcher>,
}
Expand All @@ -125,6 +126,7 @@ impl Default for Config {
Self {
use_color: false,
show_hidden: false,
show_only_dirs: false,
max_level: usize::MAX,
include_glob: None,
}
Expand Down Expand Up @@ -165,6 +167,7 @@ impl<'a, T: Terminal<Output = W>, W: std::io::Write> TreePrinter<'a, T, W> {
include_glob: self.config.include_glob.clone(),
max_level: self.config.max_level,
show_hidden: self.config.show_hidden,
show_only_dirs: self.config.show_only_dirs,
};

let list = pathiterator::FileIterator::new(path, config);
Expand Down

0 comments on commit abb2a52

Please sign in to comment.