diff options
author | andy.boot <bootandy@gmail.com> | 2023-01-28 17:54:02 +0000 |
---|---|---|
committer | andy.boot <bootandy@gmail.com> | 2023-01-29 09:34:40 +0000 |
commit | 1495251ebc7b049c96d3da50f7c779295a9a30d2 (patch) | |
tree | 4ab76b9f8d2facd2454b08515c7e784a06548fc0 | |
parent | 520c439edcba7fd8e8884e19d98f448553e6a42d (diff) |
feature: --files-only -F
Add feature to only show files skipping directories.
-rw-r--r-- | completions/_dust | 6 | ||||
-rw-r--r-- | completions/_dust.ps1 | 2 | ||||
-rw-r--r-- | completions/dust.bash | 2 | ||||
-rw-r--r-- | completions/dust.elv | 2 | ||||
-rw-r--r-- | completions/dust.fish | 1 | ||||
-rw-r--r-- | man-page/dust.1 | 5 | ||||
-rw-r--r-- | src/cli.rs | 10 | ||||
-rw-r--r-- | src/config.rs | 9 | ||||
-rw-r--r-- | src/filter.rs | 56 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | tests/test_flags.rs | 9 |
11 files changed, 81 insertions, 22 deletions
diff --git a/completions/_dust b/completions/_dust index 27dc7d0..5ad53b7 100644 --- a/completions/_dust +++ b/completions/_dust @@ -58,8 +58,10 @@ _dust() { '--si[print sizes in powers of 1000 (e.g., 1.1G)]' \ '-P[Disable the progress indication.]' \ '--no-progress[Disable the progress indication.]' \ -'-D[Only directories will be displayed.]' \ -'--only-dir[Only directories will be displayed.]' \ +'(-F --only-file)-D[Only directories will be displayed.]' \ +'(-F --only-file)--only-dir[Only directories will be displayed.]' \ +'(-D --only-dir)-F[Only files will be displayed. (Finds your largest files)]' \ +'(-D --only-dir)--only-file[Only files will be displayed. (Finds your largest files)]' \ '*::inputs:' \ && ret=0 } diff --git a/completions/_dust.ps1 b/completions/_dust.ps1 index b59804a..69ccc41 100644 --- a/completions/_dust.ps1 +++ b/completions/_dust.ps1 @@ -66,6 +66,8 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock { [CompletionResult]::new('--no-progress', 'no-progress', [CompletionResultType]::ParameterName, 'Disable the progress indication.') [CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'Only directories will be displayed.') [CompletionResult]::new('--only-dir', 'only-dir', [CompletionResultType]::ParameterName, 'Only directories will be displayed.') + [CompletionResult]::new('-F', 'F', [CompletionResultType]::ParameterName, 'Only files will be displayed. (Finds your largest files)') + [CompletionResult]::new('--only-file', 'only-file', [CompletionResultType]::ParameterName, 'Only files will be displayed. (Finds your largest files)') break } }) diff --git a/completions/dust.bash b/completions/dust.bash index ce5876d..64b39a8 100644 --- a/completions/dust.bash +++ b/completions/dust.bash @@ -19,7 +19,7 @@ _dust() { case "${cmd}" in dust) - opts="-h -V -d -n -p -X -L -x -s -r -c -b -z -f -i -v -e -t -w -H -P -D --help --version --depth --number-of-lines --full-paths --ignore-directory --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --no-percent-bars --min-size --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --si --no-progress --only-dir <inputs>..." + opts="-h -V -d -n -p -X -L -x -s -r -c -b -z -f -i -v -e -t -w -H -P -D -F --help --version --depth --number-of-lines --full-paths --ignore-directory --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --no-percent-bars --min-size --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --si --no-progress --only-dir --only-file <inputs>..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/completions/dust.elv b/completions/dust.elv index 0c82af5..acb8ef9 100644 --- a/completions/dust.elv +++ b/completions/dust.elv @@ -63,6 +63,8 @@ set edit:completion:arg-completer[dust] = {|@words| cand --no-progress 'Disable the progress indication.' cand -D 'Only directories will be displayed.' cand --only-dir 'Only directories will be displayed.' + cand -F 'Only files will be displayed. (Finds your largest files)' + cand --only-file 'Only files will be displayed. (Finds your largest files)' } ] $completions[$command] diff --git a/completions/dust.fish b/completions/dust.fish index eb2b623..c5bcfc6 100644 --- a/completions/dust.fish +++ b/completions/dust.fish @@ -21,3 +21,4 @@ complete -c dust -s t -l file_types -d 'show only these file types' complete -c dust -s H -l si -d 'print sizes in powers of 1000 (e.g., 1.1G)' complete -c dust -s P -l no-progress -d 'Disable the progress indication.' complete -c dust -s D -l only-dir -d 'Only directories will be displayed.' +complete -c dust -s F -l only-file -d 'Only files will be displayed. (Finds your largest files)' diff --git a/man-page/dust.1 b/man-page/dust.1 index 69445f2..17f93e0 100644 --- a/man-page/dust.1 +++ b/man-page/dust.1 @@ -4,7 +4,7 @@ .SH NAME Dust \- Like du but more intuitive .SH SYNOPSIS -\fBDust\fR [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-L\fR|\fB\-\-dereference\-links\fR] [\fB\-x\fR|\fB\-\-limit\-filesystem\fR] [\fB\-s\fR|\fB\-\-apparent\-size\fR] [\fB\-r\fR|\fB\-\-reverse\fR] [\fB\-c\fR|\fB\-\-no\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-\-skip\-total\fR] [\fB\-f\fR|\fB\-\-filecount\fR] [\fB\-i\fR|\fB\-\-ignore_hidden\fR] [\fB\-v\fR|\fB\-\-invert\-filter\fR] [\fB\-e\fR|\fB\-\-filter\fR] [\fB\-t\fR|\fB\-\-file_types\fR] [\fB\-w\fR|\fB\-\-terminal_width\fR] [\fB\-H\fR|\fB\-\-si\fR] [\fB\-P\fR|\fB\-\-no\-progress\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fIinputs\fR] +\fBDust\fR [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-L\fR|\fB\-\-dereference\-links\fR] [\fB\-x\fR|\fB\-\-limit\-filesystem\fR] [\fB\-s\fR|\fB\-\-apparent\-size\fR] [\fB\-r\fR|\fB\-\-reverse\fR] [\fB\-c\fR|\fB\-\-no\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-\-skip\-total\fR] [\fB\-f\fR|\fB\-\-filecount\fR] [\fB\-i\fR|\fB\-\-ignore_hidden\fR] [\fB\-v\fR|\fB\-\-invert\-filter\fR] [\fB\-e\fR|\fB\-\-filter\fR] [\fB\-t\fR|\fB\-\-file_types\fR] [\fB\-w\fR|\fB\-\-terminal_width\fR] [\fB\-H\fR|\fB\-\-si\fR] [\fB\-P\fR|\fB\-\-no\-progress\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fIinputs\fR] .SH DESCRIPTION Like du but more intuitive .SH OPTIONS @@ -78,6 +78,9 @@ Disable the progress indication. \fB\-D\fR, \fB\-\-only\-dir\fR Only directories will be displayed. .TP +\fB\-F\fR, \fB\-\-only\-file\fR +Only files will be displayed. (Finds your largest files) +.TP [\fIinputs\fR] .SH VERSION @@ -146,11 +146,19 @@ pub fn build_cli() -> Command<'static> { .long("no-progress") .help("Disable the progress indication."), ) - .arg(Arg::new("inputs").multiple_occurrences(true)) .arg( Arg::new("only_dir") .short('D') .long("only-dir") + .conflicts_with("only_file") .help("Only directories will be displayed."), ) + .arg( + Arg::new("only_file") + .short('F') + .long("only-file") + .conflicts_with("only_dir") + .help("Only files will be displayed. (Finds your largest files)"), + ) + .arg(Arg::new("inputs").multiple_occurrences(true)) } diff --git a/src/config.rs b/src/config.rs index 701b3c0..91294ab 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,6 +20,7 @@ pub struct Config { pub iso: Option<bool>, pub min_size: Option<String>, pub only_dir: Option<bool>, + pub only_file: Option<bool>, pub disable_progress: Option<bool>, } @@ -37,7 +38,10 @@ impl Config { Some(true) == self.ignore_hidden || options.is_present("ignore_hidden") } pub fn get_full_paths(&self, options: &ArgMatches) -> bool { - Some(true) == self.display_full_paths || options.is_present("display_full_paths") + // If we are only showing files, always show full paths + Some(true) == self.display_full_paths + || options.is_present("display_full_paths") + || self.get_only_file(options) } pub fn get_reverse(&self, options: &ArgMatches) -> bool { Some(true) == self.reverse || options.is_present("reverse") @@ -69,6 +73,9 @@ impl Config { pub fn get_only_dir(&self, options: &ArgMatches) -> bool { Some(true) == self.only_dir || options.is_present("only_dir") } + pub fn get_only_file(&self, options: &ArgMatches) -> bool { + Some(true) == self.only_file || options.is_present("only_file") + } } fn convert_min_size(input: &str, iso: bool) -> Option<usize> { diff --git a/src/filter.rs b/src/filter.rs index d8df86e..740b549 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,13 +1,14 @@ use crate::display_node::DisplayNode; use crate::node::Node; use std::collections::BinaryHeap; -use std::collections::HashSet; +use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; pub struct AggregateData { pub min_size: Option<usize>, pub only_dir: bool, + pub only_file: bool, pub number_of_lines: usize, pub depth: usize, pub using_a_filter: bool, @@ -38,31 +39,34 @@ pub fn get_biggest(top_level_nodes: Vec<Node>, display_data: AggregateData) -> O heap = add_children(&display_data, &root, heap); } - let nol = display_data.number_of_lines; - let remaining = nol.saturating_sub(number_top_level_nodes); - fill_remaining_lines(heap, &root, remaining, display_data) + fill_remaining_lines(heap, &root, display_data) } pub fn fill_remaining_lines<'a>( mut heap: BinaryHeap<&'a Node>, root: &'a Node, - remaining_lines: usize, display_data: AggregateData, ) -> Option<DisplayNode> { - let mut allowed_nodes = HashSet::new(); - allowed_nodes.insert(root.name.as_path()); + let mut allowed_nodes = HashMap::new(); - for _ in 0..remaining_lines { + while allowed_nodes.len() < display_data.number_of_lines { let line = heap.pop(); match line { Some(line) => { - allowed_nodes.insert(line.name.as_path()); + if !display_data.only_file || line.children.is_empty() { + allowed_nodes.insert(line.name.as_path(), line); + } heap = add_children(&display_data, line, heap); } None => break, } } - recursive_rebuilder(&allowed_nodes, root) + + if display_data.only_file { + flat_rebuilder(allowed_nodes, root) + } else { + recursive_rebuilder(&allowed_nodes, root) + } } fn add_children<'a>( @@ -101,19 +105,39 @@ fn always_add_children<'a>( heap } -fn recursive_rebuilder(allowed_nodes: &HashSet<&Path>, current: &Node) -> Option<DisplayNode> { - let mut new_children: Vec<_> = current +// Finds children of current, if in allowed_nodes adds them as children to new DisplayNode +fn recursive_rebuilder( + allowed_nodes: &HashMap<&Path, &Node>, + current: &Node, +) -> Option<DisplayNode> { + let new_children: Vec<_> = current .children .iter() - .filter(|c| allowed_nodes.contains(c.name.as_path())) + .filter(|c| allowed_nodes.contains_key(c.name.as_path())) .filter_map(|c| recursive_rebuilder(allowed_nodes, c)) .collect(); - new_children.sort_by(|lhs, rhs| lhs.cmp(rhs).reverse()); + Some(build_node(new_children, current)) +} + +// Applies all allowed nodes as children to current node +fn flat_rebuilder(allowed_nodes: HashMap<&Path, &Node>, current: &Node) -> Option<DisplayNode> { + let new_children: Vec<DisplayNode> = allowed_nodes + .into_values() + .map(|v| DisplayNode { + name: v.name.clone(), + size: v.size, + children: vec![], + }) + .collect::<Vec<DisplayNode>>(); + Some(build_node(new_children, current)) +} - Some(DisplayNode { +fn build_node(mut new_children: Vec<DisplayNode>, current: &Node) -> DisplayNode { + new_children.sort_by(|lhs, rhs| lhs.cmp(rhs).reverse()); + DisplayNode { name: current.name.clone(), size: current.size, children: new_children, - }) + } } diff --git a/src/main.rs b/src/main.rs index fc8f554..5a0dcf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -199,6 +199,7 @@ fn main() { let agg_data = AggregateData { min_size: config.get_min_size(&options, iso), only_dir: config.get_only_dir(&options), + only_file: config.get_only_file(&options), number_of_lines, depth, using_a_filter: options.values_of("filter").is_some() diff --git a/tests/test_flags.rs b/tests/test_flags.rs index 610d1e1..d291e87 100644 --- a/tests/test_flags.rs +++ b/tests/test_flags.rs @@ -118,6 +118,15 @@ pub fn test_show_files_by_type() { } #[test] +#[cfg(target_family = "unix")] +pub fn test_show_files_only() { + let output = build_command(vec!["-c", "-F", "tests/test_dir"]); + assert!(output.contains("tests/test_dir/many/a_file")); + assert!(output.contains("tests/test_dir/many/hello_file")); + assert!(!output.contains("tests/test_dir/many ")); +} + +#[test] pub fn test_output_skip_total() { let output = build_command(vec![ "--skip-total", |