libcli_rs/
progress.rs

1use std::time::Duration;
2use indicatif::{ProgressBar as PBar, ProgressStyle};
3
4use crate::result::Result;
5
6pub trait ProgressTrait {
7    type ProgressResultType;
8
9    fn update(&self, msg: &str) -> Result<Self::ProgressResultType>;
10    fn done(&self, msg: &str) -> Result<Self::ProgressResultType>;
11    fn done_without_indicator(&self, msg: &str) -> Result<Self::ProgressResultType>;
12}
13
14pub struct ProgressBar {
15    bar: PBar,
16}
17
18impl ProgressBar {
19    pub fn new() -> Self {
20        let bar = PBar::new_spinner();
21        bar.enable_steady_tick(Duration::from_millis(80));
22        bar.set_style(
23            ProgressStyle::default_spinner()
24                // https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json
25                .tick_strings(&["⢹", "⢺", "⢼", "⣸", "⣇", "⡧", "⡗", "✔"])
26                .template("{spinner} {msg}").unwrap_or(ProgressStyle::default_spinner()),
27        );
28
29        Self { bar }
30    }
31}
32
33impl ProgressTrait for ProgressBar {
34    type ProgressResultType = ();
35
36    fn update(&self, msg: &str) -> Result<Self::ProgressResultType> {
37        self.bar.set_message(msg.to_owned());
38
39        Ok(())
40    }
41
42    fn done(&self, msg: &str) -> Result<Self::ProgressResultType> {
43        self.bar.finish_with_message(msg.to_owned());
44
45        Ok(())
46    }
47
48    fn done_without_indicator(&self, msg: &str) -> Result<Self::ProgressResultType> {
49        self.bar.finish_and_clear();
50        if !msg.is_empty() {
51            println!("{}", msg);
52        }
53
54        Ok(())
55    }
56}