dependency: upgrade to clap 4

This commit is contained in:
andy.boot
2023-11-21 23:13:07 +00:00
parent 6e0505bfd7
commit c8b61d2f46
11 changed files with 233 additions and 213 deletions
+31 -18
View File
@@ -1,9 +1,9 @@
use clap::{Arg, Command};
use clap::{value_parser, Arg, Command};
// For single thread mode set this variable on your command line:
// export RAYON_NUM_THREADS=1
pub fn build_cli() -> Command<'static> {
pub fn build_cli() -> Command {
Command::new("Dust")
.about("Like du but more intuitive")
.version(env!("CARGO_PKG_VERSION"))
@@ -12,111 +12,120 @@ pub fn build_cli() -> Command<'static> {
Arg::new("depth")
.short('d')
.long("depth")
.value_parser(value_parser!(usize))
.help("Depth to show")
.takes_value(true)
.num_args(1)
)
.arg(
Arg::new("number_of_lines")
.short('n')
.long("number-of-lines")
.value_parser(value_parser!(usize))
.help("Number of lines of output to show. (Default is terminal_height - 10)")
.takes_value(true)
.num_args(1)
)
.arg(
Arg::new("display_full_paths")
.short('p')
.long("full-paths")
.action(clap::ArgAction::SetTrue)
.help("Subdirectories will not have their path shortened"),
)
.arg(
Arg::new("ignore_directory")
.short('X')
.long("ignore-directory")
.takes_value(true)
.number_of_values(1)
.multiple_occurrences(true)
.action(clap::ArgAction::Append)
.help("Exclude any file or directory with this name"),
)
.arg(
Arg::new("dereference_links")
.short('L')
.long("dereference-links")
.action(clap::ArgAction::SetTrue)
.help("dereference sym links - Treat sym links as directories and go into them"),
)
.arg(
Arg::new("limit_filesystem")
.short('x')
.long("limit-filesystem")
.action(clap::ArgAction::SetTrue)
.help("Only count the files and directories on the same filesystem as the supplied directory"),
)
.arg(
Arg::new("display_apparent_size")
.short('s')
.long("apparent-size")
.action(clap::ArgAction::SetTrue)
.help("Use file length instead of blocks"),
)
.arg(
Arg::new("reverse")
.short('r')
.long("reverse")
.action(clap::ArgAction::SetTrue)
.help("Print tree upside down (biggest highest)"),
)
.arg(
Arg::new("no_colors")
.short('c')
.long("no-colors")
.action(clap::ArgAction::SetTrue)
.help("No colors will be printed (Useful for commands like: watch)"),
)
.arg(
Arg::new("no_bars")
.short('b')
.long("no-percent-bars")
.action(clap::ArgAction::SetTrue)
.help("No percent bars or percentages will be displayed"),
)
.arg(
Arg::new("bars_on_right")
.short('B')
.long("bars-on-right")
.action(clap::ArgAction::SetTrue)
.help("percent bars moved to right side of screen"),
)
.arg(
Arg::new("min_size")
.short('z')
.long("min-size")
.takes_value(true)
.number_of_values(1)
.num_args(1)
.help("Minimum size file to include in output"),
)
.arg(
Arg::new("screen_reader")
.short('R')
.long("screen-reader")
.action(clap::ArgAction::SetTrue)
.help("For screen readers. Removes bars. Adds new column: depth level (May want to use -p too for full path)"),
)
.arg(
Arg::new("skip_total")
.long("skip-total")
.action(clap::ArgAction::SetTrue)
.help("No total row will be displayed"),
)
.arg(
Arg::new("by_filecount")
.short('f')
.long("filecount")
.action(clap::ArgAction::SetTrue)
.help("Directory 'size' is number of child files instead of disk size"),
)
.arg(
Arg::new("ignore_hidden")
.short('i') // Do not use 'h' this is used by 'help'
.long("ignore_hidden")
.action(clap::ArgAction::SetTrue)
.help("Do not display hidden files"),
)
.arg(
Arg::new("invert_filter")
.short('v')
.long("invert-filter")
.takes_value(true)
.number_of_values(1)
.multiple_occurrences(true)
.action(clap::ArgAction::Append)
.conflicts_with("filter")
.conflicts_with("types")
.help("Exclude filepaths matching this regex. To ignore png files type: -v \"\\.png$\" "),
@@ -125,9 +134,7 @@ pub fn build_cli() -> Command<'static> {
Arg::new("filter")
.short('e')
.long("filter")
.takes_value(true)
.number_of_values(1)
.multiple_occurrences(true)
.action(clap::ArgAction::Append)
.conflicts_with("types")
.help("Only include filepaths matching this regex. For png files type: -e \"\\.png$\" "),
)
@@ -137,26 +144,29 @@ pub fn build_cli() -> Command<'static> {
.long("file_types")
.conflicts_with("depth")
.conflicts_with("only_dir")
.action(clap::ArgAction::SetTrue)
.help("show only these file types"),
)
.arg(
Arg::new("width")
.short('w')
.long("terminal_width")
.takes_value(true)
.number_of_values(1)
.num_args(1)
.value_parser(value_parser!(usize))
.help("Specify width of output overriding the auto detection of terminal width"),
)
.arg(
Arg::new("iso")
.short('H')
.long("si")
.action(clap::ArgAction::SetTrue)
.help("print sizes in powers of 1000 (e.g., 1.1G)")
)
.arg(
Arg::new("disable_progress")
.short('P')
.long("no-progress")
.action(clap::ArgAction::SetTrue)
.help("Disable the progress indication."),
)
.arg(
@@ -165,6 +175,7 @@ pub fn build_cli() -> Command<'static> {
.long("only-dir")
.conflicts_with("only_file")
.conflicts_with("types")
.action(clap::ArgAction::SetTrue)
.help("Only directories will be displayed."),
)
.arg(
@@ -172,7 +183,9 @@ pub fn build_cli() -> Command<'static> {
.short('F')
.long("only-file")
.conflicts_with("only_dir")
.action(clap::ArgAction::SetTrue)
.help("Only files will be displayed. (Finds your largest files)"),
)
.arg(Arg::new("inputs").multiple_occurrences(true))
.arg(Arg::new("params").num_args(1..)
.value_parser(value_parser!(String)))
}
+26 -24
View File
@@ -30,54 +30,52 @@ pub struct Config {
impl Config {
pub fn get_no_colors(&self, options: &ArgMatches) -> bool {
Some(true) == self.no_colors || options.is_present("no_colors")
Some(true) == self.no_colors || options.get_flag("no_colors")
}
pub fn get_disable_progress(&self, options: &ArgMatches) -> bool {
Some(true) == self.disable_progress
|| options.is_present("disable_progress")
|| options.get_flag("disable_progress")
|| !std::io::stdout().is_terminal()
}
pub fn get_apparent_size(&self, options: &ArgMatches) -> bool {
Some(true) == self.display_apparent_size || options.is_present("display_apparent_size")
Some(true) == self.display_apparent_size || options.get_flag("display_apparent_size")
}
pub fn get_ignore_hidden(&self, options: &ArgMatches) -> bool {
Some(true) == self.ignore_hidden || options.is_present("ignore_hidden")
Some(true) == self.ignore_hidden || options.get_flag("ignore_hidden")
}
pub fn get_full_paths(&self, options: &ArgMatches) -> bool {
// If we are only showing files, always show full paths
Some(true) == self.display_full_paths
|| options.is_present("display_full_paths")
|| options.get_flag("display_full_paths")
|| self.get_only_file(options)
}
pub fn get_reverse(&self, options: &ArgMatches) -> bool {
Some(true) == self.reverse || options.is_present("reverse")
Some(true) == self.reverse || options.get_flag("reverse")
}
pub fn get_no_bars(&self, options: &ArgMatches) -> bool {
Some(true) == self.no_bars || options.is_present("no_bars")
Some(true) == self.no_bars || options.get_flag("no_bars")
}
pub fn get_iso(&self, options: &ArgMatches) -> bool {
Some(true) == self.iso || options.is_present("iso")
Some(true) == self.iso || options.get_flag("iso")
}
pub fn get_skip_total(&self, options: &ArgMatches) -> bool {
Some(true) == self.skip_total || options.is_present("skip_total")
Some(true) == self.skip_total || options.get_flag("skip_total")
}
pub fn get_screen_reader(&self, options: &ArgMatches) -> bool {
Some(true) == self.screen_reader || options.is_present("screen_reader")
Some(true) == self.screen_reader || options.get_flag("screen_reader")
}
pub fn get_depth(&self, options: &ArgMatches) -> usize {
if let Some(v) = options.value_of("depth") {
if let Ok(v) = v.parse::<usize>() {
return v;
}
if let Some(v) = options.get_one::<usize>("depth") {
return *v;
}
self.depth.unwrap_or(usize::MAX)
}
pub fn get_min_size(&self, options: &ArgMatches, iso: bool) -> Option<usize> {
let size_from_param = options.value_of("min_size");
let size_from_param = options.get_one::<String>("min_size");
self._get_min_size(size_from_param, iso)
}
fn _get_min_size(&self, min_size: Option<&str>, iso: bool) -> Option<usize> {
fn _get_min_size(&self, min_size: Option<&String>, iso: bool) -> Option<usize> {
let size_from_param = min_size.and_then(|a| convert_min_size(a, iso));
if size_from_param.is_none() {
@@ -89,13 +87,13 @@ impl Config {
}
}
pub fn get_only_dir(&self, options: &ArgMatches) -> bool {
Some(true) == self.only_dir || options.is_present("only_dir")
Some(true) == self.only_dir || options.get_flag("only_dir")
}
pub fn get_only_file(&self, options: &ArgMatches) -> bool {
Some(true) == self.only_file || options.is_present("only_file")
Some(true) == self.only_file || options.get_flag("only_file")
}
pub fn get_bars_on_right(&self, options: &ArgMatches) -> bool {
Some(true) == self.bars_on_right || options.is_present("bars_on_right")
Some(true) == self.bars_on_right || options.get_flag("bars_on_right")
}
}
@@ -158,7 +156,7 @@ pub fn get_config() -> Config {
mod tests {
#[allow(unused_imports)]
use super::*;
use clap::{Arg, ArgMatches, Command};
use clap::{value_parser, Arg, ArgMatches, Command};
#[test]
fn test_conversion() {
@@ -178,10 +176,10 @@ mod tests {
..Default::default()
};
assert_eq!(c._get_min_size(None, false), Some(1024));
assert_eq!(c._get_min_size(Some("2K"), false), Some(2048));
assert_eq!(c._get_min_size(Some(&"2K".into()), false), Some(2048));
assert_eq!(c._get_min_size(None, true), Some(1000));
assert_eq!(c._get_min_size(Some("2K"), true), Some(2000));
assert_eq!(c._get_min_size(Some(&"2K".into()), true), Some(2000));
}
#[test]
@@ -215,8 +213,12 @@ mod tests {
fn get_args(args: Vec<&str>) -> ArgMatches {
Command::new("Dust")
.trailing_var_arg(true)
.arg(Arg::new("depth").long("depth").takes_value(true))
.arg(
Arg::new("depth")
.long("depth")
.num_args(1)
.value_parser(value_parser!(usize)),
)
.get_matches_from(args)
}
}
+33 -32
View File
@@ -11,6 +11,7 @@ mod progress;
mod utils;
use crate::cli::build_cli;
use clap::parser::ValuesRef;
use dir_walker::WalkData;
use display::InitialDisplayData;
use filter::AggregateData;
@@ -22,7 +23,6 @@ use std::process;
use sysinfo::{System, SystemExt};
use self::display::draw_it;
use clap::Values;
use config::get_config;
use dir_walker::walk_it;
use filter::get_biggest;
@@ -86,7 +86,7 @@ fn get_width_of_terminal() -> usize {
.unwrap_or(DEFAULT_TERMINAL_WIDTH)
}
fn get_regex_value(maybe_value: Option<Values>) -> Vec<Regex> {
fn get_regex_value(maybe_value: Option<ValuesRef<String>>) -> Vec<Regex> {
maybe_value
.unwrap_or_default()
.map(|reg| {
@@ -102,49 +102,50 @@ fn main() {
let options = build_cli().get_matches();
let config = get_config();
let target_dirs = match options.values_of("inputs") {
Some(values) => values.collect(),
let target_dirs = match options.get_many::<String>("params") {
Some(values) => values.map(|v| v.as_str()).collect::<Vec<&str>>(),
None => vec!["."],
};
let summarize_file_types = options.is_present("types");
let summarize_file_types = options.get_flag("types");
let filter_regexs = get_regex_value(options.values_of("filter"));
let invert_filter_regexs = get_regex_value(options.values_of("invert_filter"));
let filter_regexs = get_regex_value(options.get_many("filter"));
let invert_filter_regexs = get_regex_value(options.get_many("invert_filter"));
let terminal_width = options
.value_of_t("width")
.unwrap_or_else(|_| get_width_of_terminal());
let terminal_width: usize = match options.get_one::<usize>("width") {
Some(&val) => val,
None => get_width_of_terminal(),
};
let depth = config.get_depth(&options);
// If depth is set, then we set the default number_of_lines to be max
// instead of screen height
let default_height = if depth != usize::MAX {
usize::MAX
} else {
get_height_of_terminal()
};
let number_of_lines = options
.value_of("number_of_lines")
.and_then(|v| {
v.parse()
.map_err(|_| eprintln!("Ignoring bad value for number_of_lines"))
.ok()
})
.unwrap_or(default_height);
let number_of_lines = match options.get_one::<usize>("number_of_lines") {
Some(&val) => val,
None => {
if depth != usize::MAX {
usize::MAX
} else {
get_height_of_terminal()
}
}
};
let no_colors = init_color(config.get_no_colors(&options));
let ignore_directories = options
.values_of("ignore_directory")
.unwrap_or_default()
.map(PathBuf::from);
let ignore_directories = match options.get_many::<String>("ignore_directory") {
Some(values) => values
.map(|v| v.as_str())
.map(PathBuf::from)
.collect::<Vec<PathBuf>>(),
None => vec![],
};
let by_filecount = options.is_present("by_filecount");
let limit_filesystem = options.is_present("limit_filesystem");
let follow_links = options.is_present("dereference_links");
let by_filecount = options.get_flag("by_filecount");
let limit_filesystem = options.get_flag("limit_filesystem");
let follow_links = options.get_flag("dereference_links");
let simplified_dirs = simplify_dir_names(target_dirs);
let allowed_filesystems = limit_filesystem
@@ -152,6 +153,7 @@ fn main() {
.unwrap_or_default();
let ignored_full_path: HashSet<PathBuf> = ignore_directories
.into_iter()
.flat_map(|x| simplified_dirs.iter().map(move |d| d.join(&x)))
.collect();
@@ -192,8 +194,7 @@ fn main() {
only_file: config.get_only_file(&options),
number_of_lines,
depth,
using_a_filter: options.values_of("filter").is_some()
|| options.value_of("invert_filter").is_some(),
using_a_filter: !filter_regexs.is_empty() || !invert_filter_regexs.is_empty(),
};
get_biggest(top_level_nodes, agg_data)
}