Skip to content

feat!: infinite depth #306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions exports/completion.elv
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion exports/completion.fish
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions exports/completion.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
6 changes: 3 additions & 3 deletions exports/completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -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' \
Expand Down
6 changes: 3 additions & 3 deletions src/app/sub.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
args::Fraction,
args::{Depth, Fraction},
data_tree::DataTree,
fs_tree_builder::FsTreeBuilder,
get_size::GetSize,
Expand All @@ -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<Size, SizeGetter, HardlinksHandler, Report>
Expand All @@ -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.
Expand Down
12 changes: 7 additions & 5 deletions src/args.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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"
},

Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand Down
53 changes: 53 additions & 0 deletions src/args/depth.rs
Original file line number Diff line number Diff line change
@@ -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<Self, Self::Err> {
let text = text.trim();
if text == INFINITE {
return Ok(Depth::Infinite);
}
text.parse()
.map_err(FromStrError::InvalidSyntax)
.map(Depth::Finite)
}
}

impl TryFrom<u64> for Depth {
type Error = TryFromIntError;
fn try_from(value: u64) -> Result<Self, Self::Error> {
value.try_into().map(Depth::Finite)
}
}
2 changes: 1 addition & 1 deletion tests/cli_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fn max_depth_0() {
assert_eq!(
stderr,
text_block! {
"error: invalid value '0' for '--max-depth <MAX_DEPTH>': number would be zero for non-zero type"
r#"error: invalid value '0' for '--max-depth <MAX_DEPTH>': Value is neither "inf" nor a positive integer: number would be zero for non-zero type"#
""
"For more information, try '--help'."
}
Expand Down
Loading