Indicatif Progress Bar CLI Logging
Render multi-stage CLI progress with indicatif: throttled bars, nested stages, log interception, and clean terminal restoration.
Code
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
// progress logging: println pauses bar redraw to keep output clean
use std::time::Duration;
fn make_style(template: &str) -> ProgressStyle {
ProgressStyle::with_template(template)
.unwrap()
.progress_chars("=>-")
}
async fn process_stage(
bar: &ProgressBar,
total: u64,
item_ms: u64,
) -> u64 {
let mut checksum = 0u64;
for i in 0..total {
tokio::time::sleep(Duration::from_millis(item_ms)).await;
checksum = checksum.wrapping_add(i * 31);
bar.inc(1);
}
checksum
}
#[tokio::main]
async fn main() {
let multi = MultiProgress::new();
let download = multi.add(ProgressBar::new(40));
download.set_style(make_style(
"[{bar:40.cyan/blue}] {pos}/{len} files ({eta})",
));
let verify = multi.add(ProgressBar::new(20));
verify.set_style(make_style(
"[{bar:40.green/white}] {pos}/{len} chunks {msg}",
));
// 进度条与日志共存:suspend 暂停渲染打印普通输出
multi.println("starting pipeline").unwrap();
let sum1 = process_stage(&download, 40, 10).await;
download.finish_with_message("download complete");
verify.set_message("verifying");
let sum2 = process_stage(&verify, 20, 15).await;
multi.println(format!("checksums: {sum1} / {sum2}")).unwrap();
// 短任务用 spinner:避免为毫秒级操作渲染完整进度条
let spinner = multi.add(ProgressBar::new_spinner());
spinner.set_style(make_style("{spinner:.magenta} {msg}"));
spinner.set_message("finalizing");
tokio::time::sleep(Duration::from_millis(300)).await;
spinner.finish_with_message("done");
multi.clear().unwrap();
}Report a problem with this exampleOpens a pre-filled issue on GitHub.