diff --git a/completions/_dust b/completions/_dust index ec51dd1e..4b306627 100644 --- a/completions/_dust +++ b/completions/_dust @@ -66,6 +66,8 @@ _dust() { '(-F --only-file -t --file_types)--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)]' \ +'-k[display the size of a file or directory in kilobytes]' \ +'--display-kb[display the size of a file or directory in kilobytes]' \ '-h[Print help]' \ '--help[Print help]' \ '-V[Print version]' \ diff --git a/completions/_dust.ps1 b/completions/_dust.ps1 index f59c04e9..b8cfb0de 100644 --- a/completions/_dust.ps1 +++ b/completions/_dust.ps1 @@ -72,6 +72,8 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock { [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)') + [CompletionResult]::new('-k', 'k', [CompletionResultType]::ParameterName, 'display the size of a file or directory in kilobytes') + [CompletionResult]::new('--display-kb', 'display-kb', [CompletionResultType]::ParameterName, 'display the size of a file or directory in kilobytes') [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version') diff --git a/completions/dust.bash b/completions/dust.bash index eddf14f7..23f3a325 100644 --- a/completions/dust.bash +++ b/completions/dust.bash @@ -19,7 +19,7 @@ _dust() { case "${cmd}" in dust) - opts="-d -n -p -X -I -L -x -s -r -c -b -B -z -R -f -i -v -e -t -w -H -P -D -F -S -h -V --depth --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --si --no-progress --only-dir --only-file --stack-size --help --version [params]..." + opts="-d -n -p -X -I -L -x -s -r -c -b -B -z -R -f -i -v -e -t -w -H -P -D -F -k -S -h -V --depth --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --si --no-progress --only-dir --only-file --display-kb --stack-size --help --version [params]..." 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 f5faf473..915e7493 100644 --- a/completions/dust.elv +++ b/completions/dust.elv @@ -69,6 +69,8 @@ set edit:completion:arg-completer[dust] = {|@words| 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)' + cand -k 'display the size of a file or directory in kilobytes' + cand --display-kb 'display the size of a file or directory in kilobytes' cand -h 'Print help' cand --help 'Print help' cand -V 'Print version' diff --git a/completions/dust.fish b/completions/dust.fish index c36e86e1..a193a90a 100644 --- a/completions/dust.fish +++ b/completions/dust.fish @@ -24,5 +24,6 @@ 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)' +complete -c dust -s k -l display-kb -d 'display the size of a file or directory in kilobytes' complete -c dust -s h -l help -d 'Print help' complete -c dust -s V -l version -d 'Print version' diff --git a/man-page/dust.1 b/man-page/dust.1 index 8960aebd..0e344201 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\-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\-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\-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] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIparams\fR] +\fBDust\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\-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\-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\-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] [\fB\-k\fR|\fB\-\-display\-kb\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIparams\fR] .SH DESCRIPTION Like du but more intuitive .SH OPTIONS @@ -84,6 +84,9 @@ Only directories will be displayed. \fB\-F\fR, \fB\-\-only\-file\fR Only files will be displayed. (Finds your largest files) .TP +\fB\-k\fR, \fB\-\-display\-kb\fR +display the size of a file or directory in kilobytes +.TP \fB\-S\fR, \fB\-\-stack\-size\fR Specify memory to use as stack size \- use if you see: \*(Aqfatal runtime error: stack overflow\*(Aq (default low memory=1048576, high memory=1073741824) .TP diff --git a/src/cli.rs b/src/cli.rs index 468f93c2..dd5d01b2 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -193,6 +193,13 @@ pub fn build_cli() -> Command { .action(clap::ArgAction::SetTrue) .help("Only files will be displayed. (Finds your largest files)"), ) + .arg( + Arg::new("display_kb") + .short('k') + .long("display-kb") + .action(clap::ArgAction::SetTrue) + .help("display the size of a file or directory in kilobytes"), + ) .arg( Arg::new("stack_size") .short('S') diff --git a/src/config.rs b/src/config.rs index d74528ab..3e058c22 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,6 +26,7 @@ pub struct Config { pub disable_progress: Option, pub depth: Option, pub bars_on_right: Option, + pub display_kb: Option, pub stack_size: Option, } @@ -104,6 +105,9 @@ impl Config { from_cmd_line.copied() } } + pub fn get_display_kb(&self, options: &ArgMatches) -> bool { + Some(true) == self.display_kb || options.get_flag("display_kb") + } } fn convert_min_size(input: &str, iso: bool) -> Option { diff --git a/src/display.rs b/src/display.rs index 0516f2fd..68bbb4dd 100644 --- a/src/display.rs +++ b/src/display.rs @@ -25,6 +25,7 @@ pub struct InitialDisplayData { pub is_screen_reader: bool, pub iso: bool, pub bars_on_right: bool, + pub display_kb: bool, } pub struct DisplayData { @@ -129,6 +130,7 @@ pub fn draw_it( terminal_width: usize, root_node: &DisplayNode, skip_total: bool, + display_kb: bool, ) { let biggest = match skip_total { false => root_node, @@ -142,7 +144,7 @@ pub fn draw_it( let max_size = biggest.size; max_size.separate_with_commas().chars().count() } else { - find_biggest_size_str(root_node, idd.iso) + find_biggest_size_str(root_node, idd.iso, display_kb) }; assert!( @@ -190,10 +192,12 @@ pub fn draw_it( } } -fn find_biggest_size_str(node: &DisplayNode, iso: bool) -> usize { - let mut mx = human_readable_number(node.size, iso).chars().count(); +fn find_biggest_size_str(node: &DisplayNode, iso: bool, display_kb: bool) -> usize { + let mut mx = human_readable_number(node.size, iso, display_kb) + .chars() + .count(); for n in node.children.iter() { - mx = max(mx, find_biggest_size_str(n, iso)); + mx = max(mx, find_biggest_size_str(n, iso, display_kb)); } mx } @@ -375,7 +379,11 @@ fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayD let output = if display_data.initial.by_filecount { node.size.separate_with_commas() } else { - human_readable_number(node.size, display_data.initial.iso) + human_readable_number( + node.size, + display_data.initial.iso, + display_data.initial.display_kb, + ) }; let spaces_to_add = display_data.num_chars_needed_on_left_most - output.chars().count(); let output = " ".repeat(spaces_to_add) + output.as_str(); @@ -407,9 +415,12 @@ fn get_pretty_name( } } -pub fn human_readable_number(size: u64, iso: bool) -> String { +pub fn human_readable_number(size: u64, iso: bool, display_kb: bool) -> String { + let num: u64 = if iso { 1000 } else { 1024 }; + if display_kb { + return format!("{:.1}{}", (size as f32 / num as f32), 'K'); + } for (i, u) in UNITS.iter().enumerate() { - let num: u64 = if iso { 1000 } else { 1024 }; let marker = num.pow((UNITS.len() - i) as u32); if size >= marker { if size / marker < 10 { @@ -438,6 +449,7 @@ mod tests { is_screen_reader: false, iso: false, bars_on_right: false, + display_kb: false, }; DisplayData { initial, @@ -503,20 +515,23 @@ mod tests { #[test] fn test_human_readable_number() { - assert_eq!(human_readable_number(1, false), "1B"); - assert_eq!(human_readable_number(956, false), "956B"); - assert_eq!(human_readable_number(1004, false), "1004B"); - assert_eq!(human_readable_number(1024, false), "1.0K"); - assert_eq!(human_readable_number(1536, false), "1.5K"); - assert_eq!(human_readable_number(1024 * 512, false), "512K"); - assert_eq!(human_readable_number(1024 * 1024, false), "1.0M"); + assert_eq!(human_readable_number(1, false, false), "1B"); + assert_eq!(human_readable_number(956, false, false), "956B"); + assert_eq!(human_readable_number(1004, false, false), "1004B"); + assert_eq!(human_readable_number(1024, false, false), "1.0K"); + assert_eq!(human_readable_number(1536, false, false), "1.5K"); + assert_eq!(human_readable_number(1024 * 512, false, false), "512K"); + assert_eq!(human_readable_number(1024 * 1024, false, false), "1.0M"); assert_eq!( - human_readable_number(1024 * 1024 * 1024 - 1, false), + human_readable_number(1024 * 1024 * 1024 - 1, false, false), "1023M" ); - assert_eq!(human_readable_number(1024 * 1024 * 1024 * 20, false), "20G"); assert_eq!( - human_readable_number(1024 * 1024 * 1024 * 1024, false), + human_readable_number(1024 * 1024 * 1024 * 20, false, false), + "20G" + ); + assert_eq!( + human_readable_number(1024 * 1024 * 1024 * 1024, false, false), "1.0T" ); } @@ -574,4 +589,16 @@ mod tests { let bar = dd.generate_bar(&n, 5); assert_eq!(bar, "████▓▓▓▓▓▓▓▓▓"); } + #[test] + fn test_human_readable_number_kb() { + assert_eq!(human_readable_number(1, false, true), "0.0K"); + assert_eq!(human_readable_number(1024, false, true), "1.0K"); + assert_eq!(human_readable_number(1536, false, true), "1.5K"); + assert_eq!(human_readable_number(1024 * 512, false, true), "512.0K"); + assert_eq!(human_readable_number(1024 * 1024, false, true), "1024.0K"); + assert_eq!( + human_readable_number(1024 * 1000 * 1000 * 20, false, true), + "20000000.0K" + ); + } } diff --git a/src/main.rs b/src/main.rs index 0b81002d..ac93139e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,11 +180,13 @@ fn main() { let iso = config.get_iso(&options); + let display_kb = config.get_display_kb(&options); + let ignore_hidden = config.get_ignore_hidden(&options); let mut indicator = PIndicator::build_me(); if !config.get_disable_progress(&options) { - indicator.spawn(iso); + indicator.spawn(iso, display_kb); } let walk_data = WalkData { @@ -255,6 +257,7 @@ fn main() { iso, is_screen_reader: config.get_screen_reader(&options), bars_on_right: config.get_bars_on_right(&options), + display_kb, }; draw_it( idd, @@ -262,6 +265,7 @@ fn main() { terminal_width, &root_node, config.get_skip_total(&options), + display_kb, ) } } diff --git a/src/progress.rs b/src/progress.rs index b4d7a89d..afeee047 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -77,16 +77,26 @@ pub struct RuntimeErrors { /* -------------------------------------------------------------------------- */ -fn format_preparing_str(prog_char: char, data: &PAtomicInfo, is_iso: bool) -> String { +fn format_preparing_str( + prog_char: char, + data: &PAtomicInfo, + is_iso: bool, + is_display_kb: bool, +) -> String { let path_in = data.current_path.get(); - let size = human_readable_number(data.total_file_size.load(ORDERING), is_iso); + let size = human_readable_number(data.total_file_size.load(ORDERING), is_iso, is_display_kb); format!("Preparing: {path_in} {size} ... {prog_char}") } -fn format_indexing_str(prog_char: char, data: &PAtomicInfo, is_iso: bool) -> String { +fn format_indexing_str( + prog_char: char, + data: &PAtomicInfo, + is_iso: bool, + display_kb: bool, +) -> String { let path_in = data.current_path.get(); let file_count = data.num_files.load(ORDERING); - let size = human_readable_number(data.total_file_size.load(ORDERING), is_iso); + let size = human_readable_number(data.total_file_size.load(ORDERING), is_iso, display_kb); let file_str = format!("{file_count} files, {size}"); format!("Indexing: {path_in} {file_str} ... {prog_char}") } @@ -106,7 +116,7 @@ impl PIndicator { } } - pub fn spawn(&mut self, is_iso: bool) { + pub fn spawn(&mut self, is_iso: bool, display_kb: bool) { let data = self.data.clone(); let (stop_handler, receiver) = mpsc::channel::<()>(); @@ -125,8 +135,12 @@ impl PIndicator { let prog_char = PROGRESS_CHARS[progress_char_i]; msg = match data.state.load(ORDERING) { - Operation::INDEXING => format_indexing_str(prog_char, &data, is_iso), - Operation::PREPARING => format_preparing_str(prog_char, &data, is_iso), + Operation::INDEXING => { + format_indexing_str(prog_char, &data, is_iso, display_kb) + } + Operation::PREPARING => { + format_preparing_str(prog_char, &data, is_iso, display_kb) + } _ => panic!("Unknown State"), };