use std::io::IsTerminal;
use std::time::Duration;
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
#[derive(Debug)]
pub struct Walk(Option<ProgressBar>);
impl Walk {
#[must_use]
pub fn start(what: &str) -> Self {
if !std::io::stderr().is_terminal() {
return Self(None);
}
let bar = ProgressBar::new_spinner();
bar.set_draw_target(ProgressDrawTarget::stderr());
if let Ok(style) = ProgressStyle::with_template("{spinner} {msg}") {
bar.set_style(style);
}
bar.set_message(what.to_owned());
bar.enable_steady_tick(Duration::from_millis(120));
Self(Some(bar))
}
pub fn page(&self, page: u32, collected: usize, total: Option<u64>) {
let Some(bar) = &self.0 else { return };
let of = total.map_or_else(|| "unknown total".to_owned(), |total| total.to_string());
bar.set_message(format!("page {page}: {collected} of {of}"));
}
pub fn finish(self) {
if let Some(bar) = self.0 {
bar.finish_and_clear();
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_captured_stderr_gets_no_progress() {
let walk = Walk::start("searching");
assert!(walk.0.is_none());
walk.page(2, 50, Some(340));
walk.finish();
}
}