wash_cli/appearance/
spinner.rs

1use std::borrow::Cow;
2
3use anyhow::Result;
4use indicatif::{ProgressBar, ProgressStyle};
5use wash_lib::cli::OutputKind;
6
7// For more spinners check out the cli-spinners project:
8// https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json
9pub const DOTS_12: &[&str; 56] = &[
10    "⢀⠀", "⡀⠀", "⠄⠀", "⢂⠀", "⡂⠀", "⠅⠀", "⢃⠀", "⡃⠀", "⠍⠀", "⢋⠀", "⡋⠀", "⠍⠁", "⢋⠁", "⡋⠁", "⠍⠉", "⠋⠉",
11    "⠋⠉", "⠉⠙", "⠉⠙", "⠉⠩", "⠈⢙", "⠈⡙", "⢈⠩", "⡀⢙", "⠄⡙", "⢂⠩", "⡂⢘", "⠅⡘", "⢃⠨", "⡃⢐", "⠍⡐", "⢋⠠",
12    "⡋⢀", "⠍⡁", "⢋⠁", "⡋⠁", "⠍⠉", "⠋⠉", "⠋⠉", "⠉⠙", "⠉⠙", "⠉⠩", "⠈⢙", "⠈⡙", "⠈⠩", "⠀⢙", "⠀⡙", "⠀⠩",
13    "⠀⢘", "⠀⡘", "⠀⠨", "⠀⢐", "⠀⡐", "⠀⠠", "⠀⢀", "⠀⡀",
14];
15
16pub struct Spinner {
17    spinner: Option<ProgressBar>,
18}
19
20impl Spinner {
21    pub fn new(output_kind: &OutputKind) -> Result<Self> {
22        match output_kind {
23            OutputKind::Text => {
24                let style = ProgressStyle::default_spinner()
25                    .tick_strings(DOTS_12)
26                    .template("{prefix:.bold.dim} {spinner:.bold.dim} {wide_msg:.bold.dim}")?;
27
28                let spinner = ProgressBar::new_spinner().with_style(style);
29
30                spinner.enable_steady_tick(std::time::Duration::from_millis(200));
31                Ok(Self {
32                    spinner: Some(spinner),
33                })
34            }
35            OutputKind::Json => Ok(Self { spinner: None }),
36        }
37    }
38
39    /// Handles updating the spinner for text output
40    /// JSON output will be corrupted with a spinner
41    pub fn update_spinner_message(&self, msg: impl Into<Cow<'static, str>>) {
42        if let Some(spinner) = &self.spinner {
43            spinner.set_prefix(">>>");
44            spinner.set_message(msg);
45        }
46    }
47
48    pub fn finish_and_clear(&self) {
49        if let Some(progress_bar) = &self.spinner {
50            progress_bar.finish_and_clear()
51        }
52    }
53}