ralph_workflow/logger/
progress.rs1use super::Colors;
6
7pub fn print_progress(current: u32, total: u32, label: &str) {
17 let c = Colors::new();
18
19 if total == 0 {
20 println!(
21 "{}{}:{} {}[no progress data]{}",
22 c.dim(),
23 label,
24 c.reset(),
25 c.yellow(),
26 c.reset()
27 );
28 return;
29 }
30
31 let bar_width: usize = 20;
32 let pct = u32::try_from(
34 (u64::from(current))
35 .saturating_mul(100)
36 .saturating_div(u64::from(total))
37 .min(100),
38 )
39 .unwrap_or(0);
40 let filled = usize::try_from(
42 (u64::from(current))
43 .saturating_mul(bar_width as u64)
44 .saturating_div(u64::from(total))
45 .min(bar_width as u64),
46 )
47 .unwrap_or(0);
48 let empty = bar_width - filled;
49
50 let bar: String = format!("{}{}", "█".repeat(filled), "░".repeat(empty));
51
52 println!(
53 "{}{}:{} {}[{}]{} {}{}%{} ({}/{})",
54 c.dim(),
55 label,
56 c.reset(),
57 c.cyan(),
58 bar,
59 c.reset(),
60 c.bold(),
61 pct,
62 c.reset(),
63 current,
64 total
65 );
66}
67
68#[cfg(test)]
69mod tests {
70 fn generate_progress_bar(current: u32, total: u32) -> (u32, String) {
72 if total == 0 {
73 return (0, String::new());
74 }
75 let bar_width: usize = 20;
76 let pct = u32::try_from(
77 (u64::from(current))
78 .saturating_mul(100)
79 .saturating_div(u64::from(total))
80 .min(100),
81 )
82 .unwrap_or(0);
83 let filled = usize::try_from(
84 (u64::from(current))
85 .saturating_mul(bar_width as u64)
86 .saturating_div(u64::from(total))
87 .min(bar_width as u64),
88 )
89 .unwrap_or(0);
90 let empty = bar_width - filled;
91 let bar: String = format!("{}{}", "█".repeat(filled), "░".repeat(empty));
92 (pct, bar)
93 }
94
95 #[test]
96 fn test_progress_bar_50_percent() {
97 let (pct, bar) = generate_progress_bar(5, 10);
98 assert_eq!(pct, 50);
99 assert_eq!(bar, "██████████░░░░░░░░░░");
100 }
101
102 #[test]
103 fn test_progress_bar_100_percent() {
104 let (pct, bar) = generate_progress_bar(10, 10);
105 assert_eq!(pct, 100);
106 assert_eq!(bar, "████████████████████");
107 }
108
109 #[test]
110 fn test_progress_bar_0_percent() {
111 let (pct, bar) = generate_progress_bar(0, 10);
112 assert_eq!(pct, 0);
113 assert_eq!(bar, "░░░░░░░░░░░░░░░░░░░░");
114 }
115
116 #[test]
117 fn test_progress_bar_zero_total() {
118 let (pct, bar) = generate_progress_bar(0, 0);
119 assert_eq!(pct, 0);
120 assert_eq!(bar, "");
121 }
122}