Skip to content

Commit 8c06e3c

Browse files
committed
fix the padding on hero. Change extensions to default to 10, but user configurable.
1 parent e9c6b52 commit 8c06e3c

2 files changed

Lines changed: 72 additions & 15 deletions

File tree

src/display.rs

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,74 @@ use crate::age;
55
use crate::file_info;
66
use crate::utils;
77

8+
fn truncate_to_width(s: &str, max_width: usize) -> String {
9+
if s.chars().count() <= max_width {
10+
s.to_string()
11+
} else if max_width <= 3 {
12+
".".repeat(max_width)
13+
} else {
14+
let truncated: String = s.chars().take(max_width - 3).collect();
15+
format!("{}...", truncated)
16+
}
17+
}
18+
19+
// Calculate display width accounting for emojis (4 bytes but 2 display chars)
20+
fn display_width(s: &str) -> usize {
21+
let mut width = 0;
22+
for c in s.chars() {
23+
if c.len_utf8() == 4 {
24+
width += 2; // emoji - 2 display chars
25+
} else {
26+
width += 1;
27+
}
28+
}
29+
width
30+
}
31+
32+
fn pad_to_width(s: &str, target_width: usize) -> String {
33+
let current_width = display_width(s);
34+
if current_width >= target_width {
35+
s.to_string()
36+
} else {
37+
format!("{}{}", s, " ".repeat(target_width - current_width))
38+
}
39+
}
40+
841
pub fn print_hero(
942
td: &str,
1043
dstats: &age::AgeStats,
1144
top_file_by_size: (&String, u64),
1245
top_n_percentage: f64,
1346
) {
1447
let width = 90;
15-
let title = format!("dirpulse · {}", td);
48+
let inner_width = width - 2; // space for "│ " and " │"
49+
50+
// Truncate title if needed
51+
let title = truncate_to_width(&format!("dirpulse · {}", td), inner_width);
52+
53+
// Calculate available space for filename in stats line
54+
// Format: "🔴 {stale} Stale, 📦 Largest: {name} ({size}), 📊 Top 10 = {pct}%"
55+
let stale_str = utils::bytes_to_human(dstats.stale.size);
56+
let size_str = utils::bytes_to_human(top_file_by_size.1);
57+
let pct_str = format!("{:.2}%", top_n_percentage);
58+
59+
// Calculate fixed parts display width
60+
// "🔴 " (4) + stale + " Stale, 📦 Largest: " (20) + name + " (" (2) + size + "), 📊 Top 10 = " (16) + pct
61+
// Each emoji is 2 display chars, so: 🔴=2, 📦=2, 📊=2
62+
let fixed_display_width = 4 + stale_str.len() + 20 + 2 + size_str.len() + 16 + pct_str.len();
63+
let max_name_len = inner_width.saturating_sub(fixed_display_width);
64+
65+
let truncated_name = truncate_to_width(top_file_by_size.0, max_name_len);
66+
1667
let stats = format!(
17-
"🔴 {:<5} Stale, 📦 Largest: {} ({}), 📊 Top 10 = {:.2}%",
18-
utils::bytes_to_human(dstats.stale.size),
19-
top_file_by_size.0,
20-
utils::bytes_to_human(top_file_by_size.1),
21-
top_n_percentage
68+
"🔴 {} Stale, 📦 Largest: {} ({}), 📊 Top 10 = {}",
69+
stale_str, truncated_name, size_str, pct_str
2270
);
71+
2372
println!("┌{}┐", "─".repeat(width));
24-
println!("│ {:<w$} │", title, w = width - 2);
73+
println!("│ {} │", pad_to_width(&title, inner_width));
2574
println!("├{}┤", "─".repeat(width));
26-
println!("│ {:<w$} │", stats, w = width - 5);
75+
println!("│ {} │", pad_to_width(&stats, inner_width));
2776
println!("└{}┘", "─".repeat(width));
2877
}
2978

@@ -38,14 +87,14 @@ pub fn print_stat_line(file_count: u64, dir_count: u64, total_size: u64) {
3887

3988
pub fn print_top_largest(top_size: u64, sorted_heap: &Vec<Reverse<file_info::FileInfo>>) {
4089
println!(
41-
"── Top {} Largest ────────────────────────────────────────────────────",
90+
"── Top {} Largest ───────────────────────────────────────────────────────",
4291
top_size
4392
);
4493

4594
let mut count = 1;
4695
for entry in sorted_heap {
4796
println!(
48-
"{:<10} {:<7} {:<40}",
97+
"{:<10} {:<10} {:<40}",
4998
count,
5099
utils::bytes_to_human(entry.0.size),
51100
entry
@@ -59,9 +108,12 @@ pub fn print_top_largest(top_size: u64, sorted_heap: &Vec<Reverse<file_info::Fil
59108
}
60109
}
61110

62-
pub fn print_extensions(file_types: &HashMap<String, file_info::TypeStats>) {
63-
println!("── By Extension ──────────────────────────────────────────────────────");
64-
let mut sorted_exts: Vec<_> = file_types.iter().collect();
111+
pub fn print_extensions(file_types: &HashMap<String, file_info::TypeStats>, top_extensions: u64) {
112+
println!(
113+
"── Top {} Extension ─────────────────────────────────────────────────────",
114+
top_extensions
115+
);
116+
let mut sorted_exts: Vec<_> = file_types.iter().take(top_extensions as usize).collect();
65117
sorted_exts.sort_by(|a, b| b.1.file_count.cmp(&a.1.file_count));
66118
for (key, value) in sorted_exts {
67119
println!(
@@ -74,7 +126,7 @@ pub fn print_extensions(file_types: &HashMap<String, file_info::TypeStats>) {
74126
}
75127

76128
pub fn print_file_age(file_age: &age::AgeStats) {
77-
println!("── File Age ──────────────────────────────────────────────────────────");
129+
println!("── File Age ──────────────────────────────────────────────────────────────");
78130
println!(
79131
"{:<30} {:>5} files {:>10} ",
80132
"🟢 Fresh (< 30 days)",

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ mod utils;
77

88
#[derive(Parser)]
99
struct Cli {
10+
/// Directory to audit
1011
target_directory: String,
12+
/// Top files by size
1113
#[clap(short = 'n', long = "top-size", default_value_t = 10)]
1214
top_size: u64,
15+
/// Top files by extenstion
16+
#[clap(short = 'e', long = "top-extensions", default_value_t = 10)]
17+
top_extensions: u64,
1318
}
1419

1520
fn main() {
@@ -43,7 +48,7 @@ fn main() {
4348
println!();
4449
display::print_top_largest(cli.top_size, &sorted_heap);
4550
println!();
46-
display::print_extensions(&dstats.types);
51+
display::print_extensions(&dstats.types, cli.top_extensions);
4752
println!();
4853
display::print_file_age(&dstats.age);
4954
}

0 commit comments

Comments
 (0)