diff --git a/exports/completion.elv b/exports/completion.elv index 24909cf5..4e4c3bbd 100644 --- a/exports/completion.elv +++ b/exports/completion.elv @@ -22,9 +22,9 @@ set edit:completion:arg-completer[pdu] = {|@words| cand --bytes-format 'How to display the numbers of bytes' cand -q 'Aspect of the files/directories to be measured' cand --quantity 'Aspect of the files/directories to be measured' - cand -d 'Maximum depth to display the data (must be greater than 0)' - cand --max-depth 'Maximum depth to display the data (must be greater than 0)' - cand --depth 'Maximum depth to display the data (must be greater than 0)' + cand -d 'Maximum depth to display the data. Could be either "inf" or a positive integer' + cand --max-depth 'Maximum depth to display the data. Could be either "inf" or a positive integer' + cand --depth 'Maximum depth to display the data. Could be either "inf" or a positive integer' cand -w 'Width of the visualization' cand --total-width 'Width of the visualization' cand --width 'Width of the visualization' diff --git a/exports/completion.fish b/exports/completion.fish index b260c23d..74ceb5b8 100644 --- a/exports/completion.fish +++ b/exports/completion.fish @@ -4,7 +4,7 @@ binary\t'Use binary scale, i.e. 1K = 1024B, 1M = 1024K, and so on'" complete -c pdu -s q -l quantity -d 'Aspect of the files/directories to be measured' -r -f -a "apparent-size\t'Measure apparent sizes' block-size\t'Measure block sizes (block-count * 512B)' block-count\t'Count numbers of blocks'" -complete -c pdu -s d -l max-depth -l depth -d 'Maximum depth to display the data (must be greater than 0)' -r +complete -c pdu -s d -l max-depth -l depth -d 'Maximum depth to display the data. Could be either "inf" or a positive integer' -r complete -c pdu -s w -l total-width -l width -d 'Width of the visualization' -r complete -c pdu -l column-width -d 'Maximum widths of the tree column and width of the bar column' -r complete -c pdu -s m -l min-ratio -d 'Minimal size proportion required to appear' -r diff --git a/exports/completion.ps1 b/exports/completion.ps1 index 091975c0..3c1a31ef 100644 --- a/exports/completion.ps1 +++ b/exports/completion.ps1 @@ -25,9 +25,9 @@ Register-ArgumentCompleter -Native -CommandName 'pdu' -ScriptBlock { [CompletionResult]::new('--bytes-format', '--bytes-format', [CompletionResultType]::ParameterName, 'How to display the numbers of bytes') [CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'Aspect of the files/directories to be measured') [CompletionResult]::new('--quantity', '--quantity', [CompletionResultType]::ParameterName, 'Aspect of the files/directories to be measured') - [CompletionResult]::new('-d', '-d', [CompletionResultType]::ParameterName, 'Maximum depth to display the data (must be greater than 0)') - [CompletionResult]::new('--max-depth', '--max-depth', [CompletionResultType]::ParameterName, 'Maximum depth to display the data (must be greater than 0)') - [CompletionResult]::new('--depth', '--depth', [CompletionResultType]::ParameterName, 'Maximum depth to display the data (must be greater than 0)') + [CompletionResult]::new('-d', '-d', [CompletionResultType]::ParameterName, 'Maximum depth to display the data. Could be either "inf" or a positive integer') + [CompletionResult]::new('--max-depth', '--max-depth', [CompletionResultType]::ParameterName, 'Maximum depth to display the data. Could be either "inf" or a positive integer') + [CompletionResult]::new('--depth', '--depth', [CompletionResultType]::ParameterName, 'Maximum depth to display the data. Could be either "inf" or a positive integer') [CompletionResult]::new('-w', '-w', [CompletionResultType]::ParameterName, 'Width of the visualization') [CompletionResult]::new('--total-width', '--total-width', [CompletionResultType]::ParameterName, 'Width of the visualization') [CompletionResult]::new('--width', '--width', [CompletionResultType]::ParameterName, 'Width of the visualization') diff --git a/exports/completion.zsh b/exports/completion.zsh index 3e655e5a..1b30b4b9 100644 --- a/exports/completion.zsh +++ b/exports/completion.zsh @@ -27,9 +27,9 @@ block-count\:"Count numbers of blocks"))' \ '--quantity=[Aspect of the files/directories to be measured]:QUANTITY:((apparent-size\:"Measure apparent sizes" block-size\:"Measure block sizes (block-count * 512B)" block-count\:"Count numbers of blocks"))' \ -'-d+[Maximum depth to display the data (must be greater than 0)]:MAX_DEPTH:_default' \ -'--max-depth=[Maximum depth to display the data (must be greater than 0)]:MAX_DEPTH:_default' \ -'--depth=[Maximum depth to display the data (must be greater than 0)]:MAX_DEPTH:_default' \ +'-d+[Maximum depth to display the data. Could be either "inf" or a positive integer]:MAX_DEPTH:_default' \ +'--max-depth=[Maximum depth to display the data. Could be either "inf" or a positive integer]:MAX_DEPTH:_default' \ +'--depth=[Maximum depth to display the data. Could be either "inf" or a positive integer]:MAX_DEPTH:_default' \ '(--column-width)-w+[Width of the visualization]:TOTAL_WIDTH:_default' \ '(--column-width)--total-width=[Width of the visualization]:TOTAL_WIDTH:_default' \ '(--column-width)--width=[Width of the visualization]:TOTAL_WIDTH:_default' \ diff --git a/src/app/sub.rs b/src/app/sub.rs index 3c18749f..3500a5f3 100644 --- a/src/app/sub.rs +++ b/src/app/sub.rs @@ -1,5 +1,5 @@ use crate::{ - args::Fraction, + args::{Depth, Fraction}, data_tree::DataTree, fs_tree_builder::FsTreeBuilder, get_size::GetSize, @@ -14,7 +14,7 @@ use crate::{ }; use pipe_trait::Pipe; use serde::Serialize; -use std::{io::stdout, iter::once, num::NonZeroU64, path::PathBuf}; +use std::{io::stdout, iter::once, path::PathBuf}; /// The sub program of the main application. pub struct Sub @@ -38,7 +38,7 @@ where /// Distribution and number of characters/blocks can be placed in a line. pub column_width_distribution: ColumnWidthDistribution, /// Maximum number of levels that should be visualized. - pub max_depth: NonZeroU64, + pub max_depth: Depth, /// [Get the size](GetSize) of files/directories. pub size_getter: SizeGetter, /// Handle to detect, record, and deduplicate hardlinks. diff --git a/src/args.rs b/src/args.rs index 0fb30011..19951e47 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,7 +1,9 @@ +pub mod depth; pub mod fraction; pub mod quantity; pub mod threads; +pub use depth::Depth; pub use fraction::Fraction; pub use quantity::Quantity; pub use threads::Threads; @@ -10,7 +12,7 @@ use crate::{bytes_format::BytesFormat, visualizer::ColumnWidthDistribution}; use clap::{ColorChoice, Parser}; use derive_setters::Setters; use smart_default::SmartDefault; -use std::{num::NonZeroU64, path::PathBuf}; +use std::path::PathBuf; use terminal_size::{terminal_size, Width}; use text_block_macros::text_block; @@ -41,7 +43,7 @@ use text_block_macros::text_block; " $ pdu --bytes-format=binary" " $ pdu --min-ratio=0" " $ pdu --min-ratio=0.05" - " $ pdu --min-ratio=0 --json-output | jq" + " $ pdu --min-ratio=0 --max-depth=inf --json-output | jq" " $ pdu --json-input < disk-usage.json" }, @@ -75,7 +77,7 @@ use text_block_macros::text_block; " $ pdu --min-ratio=0.05" "" " Show disk usage data as JSON instead of chart" - " $ pdu --min-ratio=0 --json-output | jq" + " $ pdu --min-ratio=0 --max-depth=inf --json-output | jq" "" " Visualize existing JSON representation of disk usage data" " $ pdu --json-input < disk-usage.json" @@ -123,10 +125,10 @@ pub struct Args { #[default(Quantity::DEFAULT)] pub quantity: Quantity, - /// Maximum depth to display the data (must be greater than 0). + /// Maximum depth to display the data. Could be either "inf" or a positive integer. #[clap(long, short = 'd', default_value = "10", visible_alias = "depth")] #[default(_code = "10.try_into().unwrap()")] - pub max_depth: NonZeroU64, + pub max_depth: Depth, /// Width of the visualization. #[clap( diff --git a/src/args/depth.rs b/src/args/depth.rs new file mode 100644 index 00000000..d4d5a4b1 --- /dev/null +++ b/src/args/depth.rs @@ -0,0 +1,53 @@ +use derive_more::{Display, Error}; +use std::{ + num::{NonZeroU64, ParseIntError, TryFromIntError}, + str::FromStr, +}; + +const INFINITE: &str = "inf"; + +/// Maximum depth of the tree. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Display)] +pub enum Depth { + #[display("{INFINITE}")] + Infinite, + Finite(NonZeroU64), +} + +impl Depth { + /// Convert depth into something comparable. + pub(crate) fn get(self) -> u64 { + match self { + Depth::Infinite => u64::MAX, + Depth::Finite(value) => value.get(), + } + } +} + +/// Error that occurs when parsing a string as [`Depth`]. +#[derive(Debug, Display, Clone, PartialEq, Eq, Error)] +#[non_exhaustive] +pub enum FromStrError { + #[display("Value is neither {INFINITE:?} nor a positive integer: {_0}")] + InvalidSyntax(ParseIntError), +} + +impl FromStr for Depth { + type Err = FromStrError; + fn from_str(text: &str) -> Result { + let text = text.trim(); + if text == INFINITE { + return Ok(Depth::Infinite); + } + text.parse() + .map_err(FromStrError::InvalidSyntax) + .map(Depth::Finite) + } +} + +impl TryFrom for Depth { + type Error = TryFromIntError; + fn try_from(value: u64) -> Result { + value.try_into().map(Depth::Finite) + } +} diff --git a/tests/cli_errors.rs b/tests/cli_errors.rs index e0f21e9f..c33f0d9a 100644 --- a/tests/cli_errors.rs +++ b/tests/cli_errors.rs @@ -97,7 +97,7 @@ fn max_depth_0() { assert_eq!( stderr, text_block! { - "error: invalid value '0' for '--max-depth ': number would be zero for non-zero type" + r#"error: invalid value '0' for '--max-depth ': Value is neither "inf" nor a positive integer: number would be zero for non-zero type"# "" "For more information, try '--help'." }