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
pub mod fraction;
pub mod quantity;
pub use fraction::Fraction;
pub use quantity::Quantity;
use crate::{bytes_format::BytesFormat, visualizer::ColumnWidthDistribution};
use std::{num::NonZeroUsize, path::PathBuf};
use structopt::StructOpt;
use strum::VariantNames;
use terminal_size::{terminal_size, Width};
use text_block_macros::text_block;
#[derive(Debug, Clone, StructOpt)]
#[structopt(
name = "pdu",
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://ksxgithub.github.io/>"
"Donation: https://patreon.com/khai96_"
},
after_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 block sizes instead of apparent sizes"
" $ pdu --quantity=blksize"
""
" Show data in plain numbers instead of metric units"
" $ pdu --bytes-format=plain"
""
" Show data 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"
},
)]
pub struct Args {
#[structopt(name = "files")]
pub files: Vec<PathBuf>,
#[structopt(long, possible_values = BytesFormat::VARIANTS, default_value = BytesFormat::default_value())]
pub bytes_format: BytesFormat,
#[structopt(long)]
pub top_down: bool,
#[structopt(long, possible_values = Quantity::VARIANTS, default_value = Quantity::default_value())]
pub quantity: Quantity,
#[structopt(long, default_value = "10")]
pub max_depth: NonZeroUsize,
#[structopt(long, conflicts_with = "column-width")]
pub total_width: Option<usize>,
#[structopt(long, number_of_values = 2, value_names = &["tree-width", "bar-width"])]
pub column_width: Option<Vec<usize>>,
#[structopt(long, default_value = "0.01")]
pub min_ratio: Fraction,
#[structopt(long)]
pub no_sort: bool,
#[structopt(long)]
pub silent_errors: bool,
#[structopt(long)]
pub progress: bool,
}
impl Args {
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")
}
}
}
}