Skip to content

Commit 2a8c6bc

Browse files
Switch to 'indicatif' for progress reporting
1 parent 22ce45e commit 2a8c6bc

File tree

3 files changed

+101
-63
lines changed

3 files changed

+101
-63
lines changed

Cargo.lock

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ color-print = "0.3"
2929
thiserror = "2"
3030
shellexpand = "3.1"
3131
regex = "1"
32+
indicatif = "0.17"
3233

3334
log = "0.4"
3435
rustls = { version = "0.23", features = ["aws_lc_rs"] }

src/output.rs

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::fmt;
2727
use sysexits::ExitCode;
2828
use tabled::settings::object::Rows;
2929

30-
use std::io::{self, Write};
30+
use indicatif::{ProgressBar, ProgressStyle};
3131
use tabled::settings::{Panel, Remove, Style};
3232
use tabled::{
3333
Table, Tabled,
@@ -467,131 +467,123 @@ pub trait ProgressReporter {
467467

468468
#[allow(dead_code)]
469469
pub struct InteractiveProgressReporter {
470-
operation_name: String,
470+
bar: Option<ProgressBar>,
471471
failures: usize,
472-
current_position: usize,
473-
total: usize,
474-
results: Vec<char>,
475472
}
476473

477474
#[allow(dead_code)]
478475
impl InteractiveProgressReporter {
479476
pub fn new() -> Self {
480477
Self {
481-
operation_name: String::new(),
478+
bar: None,
482479
failures: 0,
483-
current_position: 0,
484-
total: 0,
485-
results: Vec::new(),
486480
}
487481
}
488482
}
489483

490484
impl ProgressReporter for InteractiveProgressReporter {
491485
fn start_operation(&mut self, total: usize, operation_name: &str) {
492-
self.operation_name = operation_name.to_string();
486+
let bar = ProgressBar::new(total as u64);
487+
bar.set_style(
488+
ProgressStyle::with_template(
489+
"{msg} [{bar:40.cyan/blue}] {pos}/{len} ({percent}%) {elapsed_precise}",
490+
)
491+
.unwrap(),
492+
);
493+
bar.set_message(operation_name.to_string());
494+
self.bar = Some(bar);
493495
self.failures = 0;
494-
self.current_position = 0;
495-
self.total = total;
496-
self.results = vec!['.'; total];
497-
println!("{}...", operation_name);
498496
}
499497

500498
fn report_progress(&mut self, _current: usize, _total: usize, _item_name: &str) {
501-
if self.current_position < self.results.len() {
502-
self.results[self.current_position] = '#';
499+
if let Some(bar) = &self.bar {
500+
bar.inc(1);
503501
}
504-
self.current_position += 1;
505-
let percentage = if self.total > 0 {
506-
(self.current_position * 100) / self.total
507-
} else {
508-
0
509-
};
510-
let bar: String = self.results.iter().collect();
511-
print!("\rProgress: [{:3}%] [{}]", percentage, bar);
512-
io::stdout().flush().unwrap();
513502
}
514503

515504
fn report_success(&mut self, _item_name: &str) {
516-
// No-op: progress bar already shows the advancement
505+
// No-op: progress already incremented in report_progress
517506
}
518507

519508
fn report_skip(&mut self, _item_name: &str, _reason: &str) {
520-
// No-op: progress bar already shows the advancement
509+
// No-op: progress already incremented in report_progress
521510
}
522511

523512
fn report_failure(&mut self, _item_name: &str, _error: &str) {
524513
self.failures += 1;
525-
if self.current_position < self.results.len() {
526-
self.results[self.current_position] = 'X';
514+
if let Some(bar) = &self.bar {
515+
bar.inc(1);
527516
}
528-
self.current_position += 1;
529-
let percentage = if self.total > 0 {
530-
(self.current_position * 100) / self.total
531-
} else {
532-
0
533-
};
534-
let bar: String = self.results.iter().collect();
535-
print!("\rProgress: [{:3}%] [{}]", percentage, bar);
536-
io::stdout().flush().unwrap();
537517
}
538518

539519
fn finish_operation(&mut self, total: usize) {
540-
let successes = total - self.failures;
541-
if self.failures == 0 {
542-
println!("\n✅ Completed: {} items processed successfully", total);
543-
} else if successes == 0 {
544-
println!("\n❌ Failed: All {} items failed to process", total);
545-
} else {
546-
println!(
547-
"\n⚠️ Completed with failures: {} succeeded, {} failed out of {} total",
548-
successes, self.failures, total
549-
);
520+
if let Some(bar) = &self.bar {
521+
bar.finish();
522+
523+
let successes = total - self.failures;
524+
if self.failures == 0 {
525+
println!("✅ Completed: {} items processed successfully", total);
526+
} else if successes == 0 {
527+
println!("❌ Failed: All {} items failed to process", total);
528+
} else {
529+
println!(
530+
"⚠️ Completed with failures: {} succeeded, {} failed out of {} total",
531+
successes, self.failures, total
532+
);
533+
}
550534
}
535+
self.bar = None;
551536
}
552537
}
553538

554539
#[allow(dead_code)]
555540
pub struct NonInteractiveProgressReporter {
556-
operation_name: String,
541+
bar: Option<ProgressBar>,
557542
}
558543

559544
#[allow(dead_code)]
560545
impl NonInteractiveProgressReporter {
561546
pub fn new() -> Self {
562-
Self {
563-
operation_name: String::new(),
564-
}
547+
Self { bar: None }
565548
}
566549
}
567550

568551
impl ProgressReporter for NonInteractiveProgressReporter {
569-
fn start_operation(&mut self, _total: usize, operation_name: &str) {
570-
self.operation_name = operation_name.to_string();
571-
print!("{}: ", operation_name);
572-
io::stdout().flush().unwrap();
552+
fn start_operation(&mut self, total: usize, operation_name: &str) {
553+
let bar = ProgressBar::new(total as u64);
554+
bar.set_style(
555+
ProgressStyle::with_template("{msg}: {pos}/{len} [{elapsed_precise}]").unwrap(),
556+
);
557+
bar.set_message(operation_name.to_string());
558+
self.bar = Some(bar);
573559
}
574560

575561
fn report_progress(&mut self, _current: usize, _total: usize, _item_name: &str) {
576-
print!(".");
577-
io::stdout().flush().unwrap();
562+
if let Some(bar) = &self.bar {
563+
bar.inc(1);
564+
}
578565
}
579566

580567
fn report_success(&mut self, _item_name: &str) {
581-
// Hash already printed in report_progress
568+
// No-op: progress already incremented in report_progress
582569
}
583570

584571
fn report_skip(&mut self, _item_name: &str, _reason: &str) {
585-
// Hash already printed in report_progress
572+
// No-op: progress already incremented in report_progress
586573
}
587574

588575
fn report_failure(&mut self, _item_name: &str, _error: &str) {
589-
print!("x");
590-
io::stdout().flush().unwrap();
576+
if let Some(bar) = &self.bar {
577+
bar.inc(1);
578+
}
591579
}
592580

593581
fn finish_operation(&mut self, total: usize) {
594-
println!("\nCompleted: {} items processed", total);
582+
if let Some(bar) = &self.bar {
583+
bar.finish();
584+
println!("Completed: {} items processed", total);
585+
}
586+
self.bar = None;
595587
}
596588
}
597589

0 commit comments

Comments
 (0)