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
ByteBaker committed Aug 24, 2024
1 parent 178714e commit a980c86
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 25 deletions.
21 changes: 16 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ fn is_executable(metadata: &Metadata) -> bool {
struct Config {
use_color: bool,
show_hidden: bool,
show_only_dirs: bool,
max_level: usize,
include_glob: Option<GlobMatcher>,
}
Expand All @@ -138,6 +139,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 Down Expand Up @@ -178,6 +180,7 @@ impl<'a> TreePrinter<'a> {
fn get_iterator(&self, path: &Path) -> filter::FilteredIterator {
let config = pathiterator::FileIteratorConfig {
include_glob: self.config.include_glob.clone(),
show_only_dirs: self.config.show_only_dirs,
max_level: self.config.max_level,
show_hidden: self.config.show_hidden,
};
Expand Down Expand Up @@ -229,6 +232,7 @@ impl<'a> TreePrinter<'a> {
}
}

#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Parser)]
struct Args {
/// Show hidden files
Expand All @@ -249,6 +253,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,
}

fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -264,11 +271,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: 29 additions & 20 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,28 @@ 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;
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 entry in entries {
let item = IteratorItem::new(&entry.path(), item.level + 1, false);
if self.is_included(&item.file_name, item.is_dir()) {
self.queue.push_back(item);
}
}

for item in entries {
self.queue.push_back(item);
if let Some(item) = self.queue.back_mut() {
item.is_last = true;
}
}
}
Expand Down

0 comments on commit a980c86

Please sign in to comment.