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