diff --git a/completions/_dust b/completions/_dust index 48e608db..2fb2dede 100644 --- a/completions/_dust +++ b/completions/_dust @@ -14,15 +14,16 @@ _dust() { fi local context curcontext="$curcontext" state line - _arguments "${_arguments_options[@]}" \ + _arguments "${_arguments_options[@]}" : \ '-d+[Depth to show]:DEPTH: ' \ '--depth=[Depth to show]:DEPTH: ' \ '-T+[Number of threads to use]: : ' \ '--threads=[Number of threads to use]: : ' \ +'--config=[Specify a config file to use]:FILE:_files' \ '-n+[Number of lines of output to show. (Default is terminal_height - 10)]:NUMBER: ' \ '--number-of-lines=[Number of lines of output to show. (Default is terminal_height - 10)]:NUMBER: ' \ -'*-X+[Exclude any file or directory with this name]:PATH:_files' \ -'*--ignore-directory=[Exclude any file or directory with this name]:PATH:_files' \ +'*-X+[Exclude any file or directory with this path]:PATH:_files' \ +'*--ignore-directory=[Exclude any file or directory with this path]:PATH:_files' \ '-I+[Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter]:FILE:_files' \ '--ignore-all-in-file=[Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter]:FILE:_files' \ '-z+[Minimum size file to include in output]:MIN_SIZE: ' \ diff --git a/completions/_dust.ps1 b/completions/_dust.ps1 index 0432af17..edca87a3 100644 --- a/completions/_dust.ps1 +++ b/completions/_dust.ps1 @@ -25,10 +25,11 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock { [CompletionResult]::new('--depth', 'depth', [CompletionResultType]::ParameterName, 'Depth to show') [CompletionResult]::new('-T', 'T ', [CompletionResultType]::ParameterName, 'Number of threads to use') [CompletionResult]::new('--threads', 'threads', [CompletionResultType]::ParameterName, 'Number of threads to use') + [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'Specify a config file to use') [CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Number of lines of output to show. (Default is terminal_height - 10)') [CompletionResult]::new('--number-of-lines', 'number-of-lines', [CompletionResultType]::ParameterName, 'Number of lines of output to show. (Default is terminal_height - 10)') - [CompletionResult]::new('-X', 'X ', [CompletionResultType]::ParameterName, 'Exclude any file or directory with this name') - [CompletionResult]::new('--ignore-directory', 'ignore-directory', [CompletionResultType]::ParameterName, 'Exclude any file or directory with this name') + [CompletionResult]::new('-X', 'X ', [CompletionResultType]::ParameterName, 'Exclude any file or directory with this path') + [CompletionResult]::new('--ignore-directory', 'ignore-directory', [CompletionResultType]::ParameterName, 'Exclude any file or directory with this path') [CompletionResult]::new('-I', 'I ', [CompletionResultType]::ParameterName, 'Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter') [CompletionResult]::new('--ignore-all-in-file', 'ignore-all-in-file', [CompletionResultType]::ParameterName, 'Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter') [CompletionResult]::new('-z', 'z', [CompletionResultType]::ParameterName, 'Minimum size file to include in output') diff --git a/completions/dust.bash b/completions/dust.bash index a0babd24..9b0b365f 100644 --- a/completions/dust.bash +++ b/completions/dust.bash @@ -19,7 +19,7 @@ _dust() { case "${cmd}" in dust) - opts="-d -T -n -p -X -I -L -x -s -r -c -C -b -B -z -R -f -i -v -e -t -w -P -D -F -o -S -j -M -A -y -m -h -V --depth --threads --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --force-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --no-progress --print-errors --only-dir --only-file --output-format --stack-size --output-json --mtime --atime --ctime --files0-from --filetime --help --version [PATH]..." + opts="-d -T -n -p -X -I -L -x -s -r -c -C -b -B -z -R -f -i -v -e -t -w -P -D -F -o -S -j -M -A -y -m -h -V --depth --threads --config --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --force-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --no-progress --print-errors --only-dir --only-file --output-format --stack-size --output-json --mtime --atime --ctime --files0-from --filetime --help --version [PATH]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -41,6 +41,21 @@ _dust() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --config) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' + COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi + return 0 + ;; --number-of-lines) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -59,12 +74,12 @@ _dust() { ;; --ignore-all-in-file) local oldifs - if [[ -v IFS ]]; then + if [ -n "${IFS+x}" ]; then oldifs="$IFS" fi IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) - if [[ -v oldifs ]]; then + if [ -n "${oldifs+x}" ]; then IFS="$oldifs" fi if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then @@ -74,12 +89,12 @@ _dust() { ;; -I) local oldifs - if [[ -v IFS ]]; then + if [ -n "${IFS+x}" ]; then oldifs="$IFS" fi IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) - if [[ -v oldifs ]]; then + if [ -n "${oldifs+x}" ]; then IFS="$oldifs" fi if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then diff --git a/completions/dust.elv b/completions/dust.elv index fa62ef7a..5ba01abd 100644 --- a/completions/dust.elv +++ b/completions/dust.elv @@ -22,10 +22,11 @@ set edit:completion:arg-completer[dust] = {|@words| cand --depth 'Depth to show' cand -T 'Number of threads to use' cand --threads 'Number of threads to use' + cand --config 'Specify a config file to use' cand -n 'Number of lines of output to show. (Default is terminal_height - 10)' cand --number-of-lines 'Number of lines of output to show. (Default is terminal_height - 10)' - cand -X 'Exclude any file or directory with this name' - cand --ignore-directory 'Exclude any file or directory with this name' + cand -X 'Exclude any file or directory with this path' + cand --ignore-directory 'Exclude any file or directory with this path' cand -I 'Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter' cand --ignore-all-in-file 'Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter' cand -z 'Minimum size file to include in output' diff --git a/completions/dust.fish b/completions/dust.fish index ff6fd611..4e733c68 100644 --- a/completions/dust.fish +++ b/completions/dust.fish @@ -1,19 +1,20 @@ complete -c dust -s d -l depth -d 'Depth to show' -r complete -c dust -s T -l threads -d 'Number of threads to use' -r +complete -c dust -l config -d 'Specify a config file to use' -r -F complete -c dust -s n -l number-of-lines -d 'Number of lines of output to show. (Default is terminal_height - 10)' -r -complete -c dust -s X -l ignore-directory -d 'Exclude any file or directory with this name' -r -F +complete -c dust -s X -l ignore-directory -d 'Exclude any file or directory with this path' -r -F complete -c dust -s I -l ignore-all-in-file -d 'Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by --invert_filter' -r -F complete -c dust -s z -l min-size -d 'Minimum size file to include in output' -r complete -c dust -s v -l invert-filter -d 'Exclude filepaths matching this regex. To ignore png files type: -v "\\.png$" ' -r complete -c dust -s e -l filter -d 'Only include filepaths matching this regex. For png files type: -e "\\.png$" ' -r complete -c dust -s w -l terminal_width -d 'Specify width of output overriding the auto detection of terminal width' -r -complete -c dust -s o -l output-format -d 'Changes output display size. si will print sizes in powers of 1000. b k m g t kb mb gb tb will print the whole tree in that size.' -r -f -a "{si '',b '',k '',m '',g '',t '',kb '',mb '',gb '',tb ''}" +complete -c dust -s o -l output-format -d 'Changes output display size. si will print sizes in powers of 1000. b k m g t kb mb gb tb will print the whole tree in that size.' -r -f -a "{si\t'',b\t'',k\t'',m\t'',g\t'',t\t'',kb\t'',mb\t'',gb\t'',tb\t''}" complete -c dust -s S -l stack-size -d 'Specify memory to use as stack size - use if you see: \'fatal runtime error: stack overflow\' (default low memory=1048576, high memory=1073741824)' -r complete -c dust -s M -l mtime -d '+/-n matches files modified more/less than n days ago , and n matches files modified exactly n days ago, days are rounded down.That is +n => (−∞, curr−(n+1)), n => [curr−(n+1), curr−n), and -n => (𝑐𝑢𝑟𝑟−𝑛, +∞)' -r complete -c dust -s A -l atime -d 'just like -mtime, but based on file access time' -r complete -c dust -s y -l ctime -d 'just like -mtime, but based on file change time' -r complete -c dust -l files0-from -d 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input' -r -F -complete -c dust -s m -l filetime -d 'Directory \'size\' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time' -r -f -a "{a '',c '',m ''}" +complete -c dust -s m -l filetime -d 'Directory \'size\' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time' -r -f -a "{a\t'',c\t'',m\t''}" complete -c dust -s p -l full-paths -d 'Subdirectories will not have their path shortened' complete -c dust -s L -l dereference-links -d 'dereference sym links - Treat sym links as directories and go into them' complete -c dust -s x -l limit-filesystem -d 'Only count the files and directories on the same filesystem as the supplied directory' diff --git a/man-page/dust.1 b/man-page/dust.1 index 5ceebdde..f67c8c83 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\-d\fR|\fB\-\-depth\fR] [\fB\-T\fR|\fB\-\-threads\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-I\fR|\fB\-\-ignore\-all\-in\-file\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\-C\fR|\fB\-\-force\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-B\fR|\fB\-\-bars\-on\-right\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-R\fR|\fB\-\-screen\-reader\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\-P\fR|\fB\-\-no\-progress\fR] [\fB\-\-print\-errors\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fB\-o\fR|\fB\-\-output\-format\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-j\fR|\fB\-\-output\-json\fR] [\fB\-M\fR|\fB\-\-mtime\fR] [\fB\-A\fR|\fB\-\-atime\fR] [\fB\-y\fR|\fB\-\-ctime\fR] [\fB\-\-files0\-from\fR] [\fB\-m\fR|\fB\-\-filetime\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIPATH\fR] +\fBdust\fR [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-T\fR|\fB\-\-threads\fR] [\fB\-\-config\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-I\fR|\fB\-\-ignore\-all\-in\-file\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\-C\fR|\fB\-\-force\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-B\fR|\fB\-\-bars\-on\-right\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-R\fR|\fB\-\-screen\-reader\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\-P\fR|\fB\-\-no\-progress\fR] [\fB\-\-print\-errors\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fB\-o\fR|\fB\-\-output\-format\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-j\fR|\fB\-\-output\-json\fR] [\fB\-M\fR|\fB\-\-mtime\fR] [\fB\-A\fR|\fB\-\-atime\fR] [\fB\-y\fR|\fB\-\-ctime\fR] [\fB\-\-files0\-from\fR] [\fB\-m\fR|\fB\-\-filetime\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIPATH\fR] .SH DESCRIPTION Like du but more intuitive .SH OPTIONS @@ -15,6 +15,9 @@ Depth to show \fB\-T\fR, \fB\-\-threads\fR Number of threads to use .TP +\fB\-\-config\fR=\fIFILE\fR +Specify a config file to use +.TP \fB\-n\fR, \fB\-\-number\-of\-lines\fR=\fINUMBER\fR Number of lines of output to show. (Default is terminal_height \- 10) .TP @@ -22,7 +25,7 @@ Number of lines of output to show. (Default is terminal_height \- 10) Subdirectories will not have their path shortened .TP \fB\-X\fR, \fB\-\-ignore\-directory\fR=\fIPATH\fR -Exclude any file or directory with this name +Exclude any file or directory with this path .TP \fB\-I\fR, \fB\-\-ignore\-all\-in\-file\fR=\fIFILE\fR Exclude any file or directory with a regex matching that listed in this file, the file entries will be added to the ignore regexs provided by \-\-invert_filter diff --git a/src/cli.rs b/src/cli.rs index 66a8c0c8..d8d8cb4d 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -24,6 +24,15 @@ pub fn build_cli() -> Command { .help("Number of threads to use") .num_args(1) ) + .arg( + Arg::new("config") + .long("config") + .help("Specify a config file to use") + .value_name("FILE") + .value_hint(clap::ValueHint::FilePath) + .value_parser(value_parser!(String)) + .num_args(1) + ) .arg( Arg::new("number_of_lines") .short('n') @@ -47,7 +56,7 @@ pub fn build_cli() -> Command { .value_name("PATH") .value_hint(clap::ValueHint::AnyPath) .action(clap::ArgAction::Append) - .help("Exclude any file or directory with this name"), + .help("Exclude any file or directory with this path"), ) .arg( Arg::new("ignore_all_in_file") diff --git a/src/config.rs b/src/config.rs index 723a1ec4..49a5f563 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,7 +15,6 @@ pub static DAY_SECONDS: i64 = 24 * 60 * 60; #[derive(Deserialize, Default)] #[serde(rename_all = "kebab-case")] -#[serde(deny_unknown_fields)] pub struct Config { pub display_full_paths: Option, pub display_apparent_size: Option, @@ -231,7 +230,7 @@ fn convert_min_size(input: &str) -> Option { match number_format { Some((multiple, _)) => Some(parsed_digits * (multiple as usize)), None => { - if letters.eq("") { + if letters.is_empty() { Some(parsed_digits) } else { eprintln!("Ignoring invalid min-size: {input}"); @@ -254,12 +253,29 @@ fn get_config_locations(base: &Path) -> Vec { ] } -pub fn get_config() -> Config { - if let Some(home) = directories::BaseDirs::new() { - for path in get_config_locations(home.home_dir()) { +pub fn get_config(conf_path: Option) -> Config { + match conf_path { + Some(path_str) => { + let path = Path::new(&path_str); if path.exists() { - if let Ok(config) = Config::from_config_file(path) { - return config; + match Config::from_config_file(path) { + Ok(config) => return config, + Err(e) => { + eprintln!("Ignoring invalid config file '{}': {}", &path.display(), e) + } + } + } else { + eprintln!("Config file {:?} doesn't exists", &path.display()); + } + } + None => { + if let Some(home) = directories::BaseDirs::new() { + for path in get_config_locations(home.home_dir()) { + if path.exists() { + if let Ok(config) = Config::from_config_file(&path) { + return config; + } + } } } } diff --git a/src/main.rs b/src/main.rs index ea280ef8..ddc50ee1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,7 +112,7 @@ fn get_regex_value(maybe_value: Option>) -> Vec { fn main() { let options = build_cli().get_matches(); - let config = get_config(); + let config = get_config(options.get_one::("config").cloned()); let errors = RuntimeErrors::default(); let error_listen_for_ctrlc = Arc::new(Mutex::new(errors));