fitscube_rs/progress.rs
1//! Progress bars and spinners for long-running CLI work.
2//!
3//! Mirrors the helpers in the sibling `convolve-rs` tool. These are opt-in: the
4//! library only builds them when a caller sets `progress` on its options
5//! (the CLI does; the Python bindings leave it off so importing the module
6//! stays quiet). The work loops in [`crate::combine`] drive them.
7use std::time::Duration;
8
9use indicatif::{ProgressBar, ProgressStyle};
10
11/// A determinate bar for `total` items (e.g. one tick per written channel).
12pub fn progress_bar(total: u64) -> ProgressBar {
13 let pb = ProgressBar::new(total);
14 pb.set_style(
15 ProgressStyle::default_bar()
16 .template("{spinner:.green} [{elapsed}] [{bar:40.cyan/blue}] {pos}/{len} {msg}")
17 .unwrap()
18 .progress_chars("=>-"),
19 );
20 // Steady tick animates the `{spinner}` even when `pos` is not advancing, so
21 // idle-but-busy phases (e.g. the parallel readers warming up before the
22 // first plane lands) still show live activity rather than a frozen bar.
23 pb.enable_steady_tick(Duration::from_millis(100));
24 pb
25}
26
27/// An indeterminate spinner for blocking phases with no item count (e.g.
28/// solving for a common bounding box). The caller clears it via
29/// `finish_and_clear` when the work completes.
30pub fn spinner(msg: impl Into<String>) -> ProgressBar {
31 let pb = ProgressBar::new_spinner();
32 pb.set_style(
33 ProgressStyle::default_spinner()
34 .template("{spinner:.green} [{elapsed}] {msg}")
35 .unwrap(),
36 );
37 pb.set_message(msg.into());
38 pb.enable_steady_tick(Duration::from_millis(100));
39 pb
40}