-
-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathargs.rs
More file actions
196 lines (169 loc) · 6.56 KB
/
args.rs
File metadata and controls
196 lines (169 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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;
use crate::{bytes_format::BytesFormat, visualizer::ColumnWidthDistribution};
use clap::{ColorChoice, Parser};
use derive_setters::Setters;
use smart_default::SmartDefault;
use std::path::PathBuf;
use terminal_size::{terminal_size, Width};
use text_block_macros::text_block;
/// The CLI arguments.
#[derive(Debug, SmartDefault, Setters, Clone, Parser)]
#[clap(
name = "pdu",
version,
about = "Summarize disk usage of the set of files, recursively for directories.",
long_about = text_block! {
"Summarize disk usage of the set of files, recursively for directories."
""
"Copyright: Apache-2.0 © 2021 Hoàng Văn Khải <https://github.com/KSXGitHub/>"
"Sponsor: https://github.com/sponsors/KSXGitHub"
},
after_help = text_block! {
"Examples:"
" $ pdu"
" $ pdu path/to/file/or/directory"
" $ pdu file.txt dir/"
" $ pdu --quantity=apparent-size"
" $ pdu --deduplicate-hardlinks"
" $ pdu --bytes-format=plain"
" $ pdu --bytes-format=binary"
" $ pdu --min-ratio=0"
" $ pdu --min-ratio=0.05"
" $ pdu --min-ratio=0 --max-depth=inf --json-output | jq"
" $ pdu --json-input < disk-usage.json"
},
after_long_help = text_block! {
"Examples:"
" Show disk usage chart of current working directory"
" $ pdu"
""
" Show disk usage chart of a single file or directory"
" $ pdu path/to/file/or/directory"
""
" Compare disk usages of multiple files and/or directories"
" $ pdu file.txt dir/"
""
" Show chart in apparent sizes instead of block sizes"
" $ pdu --quantity=apparent-size"
""
" Detect and subtract the sizes of hardlinks from their parent nodes"
" $ pdu --deduplicate-hardlinks"
""
" Show sizes in plain numbers instead of metric units"
" $ pdu --bytes-format=plain"
""
" Show sizes in base 2¹⁰ units (binary) instead of base 10³ units (metric)"
" $ pdu --bytes-format=binary"
""
" Show disk usage chart of all entries regardless of size"
" $ pdu --min-ratio=0"
""
" Only show disk usage chart of entries whose size is at least 5% of total"
" $ pdu --min-ratio=0.05"
""
" Show disk usage data as JSON instead of chart"
" $ pdu --min-ratio=0 --max-depth=inf --json-output | jq"
""
" Visualize existing JSON representation of disk usage data"
" $ pdu --json-input < disk-usage.json"
},
color = ColorChoice::Never,
)]
#[setters(prefix = "with_")]
#[non_exhaustive]
pub struct Args {
/// List of files and/or directories.
pub files: Vec<PathBuf>,
/// Read JSON data from stdin.
#[clap(
long,
conflicts_with_all = ["quantity", "deduplicate_hardlinks"]
)]
pub json_input: bool,
/// Print JSON data instead of an ASCII chart.
#[clap(long)]
pub json_output: bool,
/// How to display the numbers of bytes.
#[clap(long, short, value_enum, default_value_t = BytesFormat::MetricUnits)]
#[default(BytesFormat::MetricUnits)]
pub bytes_format: BytesFormat,
/// Detect and subtract the sizes of hardlinks from their parent directory totals.
#[clap(long, short = 'H', visible_aliases = ["detect-links", "dedupe-links"])]
#[cfg_attr(not(unix), clap(hide = true))]
pub deduplicate_hardlinks: bool,
/// Print the tree top-down instead of bottom-up.
#[clap(long)]
pub top_down: bool,
/// Set the root of the bars to the right.
#[clap(long)]
pub align_right: bool,
/// Aspect of the files/directories to be measured.
#[clap(long, short, value_enum, default_value_t = Quantity::DEFAULT)]
#[default(Quantity::DEFAULT)]
pub quantity: Quantity,
/// 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: Depth,
/// Width of the visualization.
#[clap(
long,
short = 'w',
conflicts_with = "column_width",
visible_alias = "width"
)]
pub total_width: Option<usize>,
/// Maximum widths of the tree column and width of the bar column.
#[clap(long, number_of_values = 2, value_names = &["TREE_WIDTH", "BAR_WIDTH"])]
pub column_width: Option<Vec<usize>>,
/// Minimal size proportion required to appear.
#[clap(long, short, default_value = "0.01")]
pub min_ratio: Fraction,
/// Do not sort the branches in the tree.
#[clap(long)]
pub no_sort: bool,
/// Prevent filesystem error messages from appearing in stderr.
#[clap(long, short, visible_alias = "no-errors")]
pub silent_errors: bool,
/// Report progress being made at the expense of performance.
#[clap(long, short)]
pub progress: bool,
/// Set the maximum number of threads to spawn. Could be either "auto", "max", or a number.
#[clap(long, default_value_t = Threads::Auto)]
pub threads: Threads,
/// Do not output `.shared.details` in the JSON output.
#[clap(long, requires = "json_output", requires = "deduplicate_hardlinks")]
pub omit_json_shared_details: bool,
/// Do not output `.shared.summary` in the JSON output.
#[clap(long, requires = "json_output", requires = "deduplicate_hardlinks")]
pub omit_json_shared_summary: bool,
}
impl Args {
/// Deduce [`ColumnWidthDistribution`] from `--total-width` or `--column-width`.
pub(crate) fn column_width_distribution(&self) -> ColumnWidthDistribution {
match (self.total_width, self.column_width.as_deref()) {
(None, None) => {
ColumnWidthDistribution::total(if let Some((Width(width), _)) = terminal_size() {
width as usize
} else {
150
})
}
(Some(total_width), None) => ColumnWidthDistribution::total(total_width),
(None, Some([tree_width, bar_width])) => {
ColumnWidthDistribution::components(*tree_width, *bar_width)
}
(total_width, column_width) => {
dbg!(total_width, column_width);
panic!("Something goes wrong")
}
}
}
}