mirror of
https://github.com/bootandy/dust.git
synced 2026-06-08 11:29:05 +03:00
dependency: upgrade to clap 4
This commit is contained in:
+31
-18
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user