alopex_cli/progress/
indicator.rs

1use std::time::Duration;
2
3use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
4
5use crate::batch::BatchMode;
6
7pub struct ProgressIndicator {
8    bar: Option<ProgressBar>,
9    finished: bool,
10}
11
12impl ProgressIndicator {
13    pub fn new(
14        batch_mode: &BatchMode,
15        explicit_progress: bool,
16        quiet: bool,
17        message: impl Into<String>,
18    ) -> Self {
19        if quiet || !batch_mode.should_show_progress(explicit_progress) {
20            return Self {
21                bar: None,
22                finished: false,
23            };
24        }
25
26        let bar = ProgressBar::new_spinner();
27        bar.set_draw_target(ProgressDrawTarget::stderr());
28        let style = ProgressStyle::with_template("{spinner} {msg}")
29            .unwrap()
30            .tick_strings(&["-", "\\", "|", "/"]);
31        bar.set_style(style);
32        bar.set_message(message.into());
33        bar.enable_steady_tick(Duration::from_millis(120));
34
35        Self {
36            bar: Some(bar),
37            finished: false,
38        }
39    }
40
41    pub fn finish_with_message(&mut self, message: impl Into<String>) {
42        if let Some(bar) = &self.bar {
43            bar.finish_with_message(message.into());
44            self.finished = true;
45        }
46    }
47
48    pub fn finish_and_clear(&mut self) {
49        if let Some(bar) = &self.bar {
50            bar.finish_and_clear();
51            self.finished = true;
52        }
53    }
54}
55
56impl Drop for ProgressIndicator {
57    fn drop(&mut self) {
58        if self.bar.is_some() && !self.finished {
59            self.finish_and_clear();
60        }
61    }
62}