alopex_cli/progress/
indicator.rs1use 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}