vika_cli/
progress.rs

1use colored::Colorize;
2use indicatif::{ProgressBar, ProgressStyle};
3use std::sync::Arc;
4
5pub struct ProgressReporter {
6    verbose: bool,
7    spinner: Option<Arc<ProgressBar>>,
8}
9
10impl ProgressReporter {
11    pub fn new(verbose: bool) -> Self {
12        Self {
13            verbose,
14            spinner: None,
15        }
16    }
17
18    pub fn start_spinner(&mut self, message: &str) {
19        if !self.verbose {
20            let pb = ProgressBar::new_spinner();
21            pb.set_style(
22                ProgressStyle::default_spinner()
23                    .template("{spinner:.cyan} {msg}")
24                    .unwrap(),
25            );
26            pb.set_message(message.to_string());
27            pb.enable_steady_tick(std::time::Duration::from_millis(100));
28            self.spinner = Some(Arc::new(pb));
29        } else {
30            println!("{}", format!("⏳ {}", message).bright_cyan());
31        }
32    }
33
34    pub fn finish_spinner(&mut self, message: &str) {
35        if let Some(spinner) = self.spinner.take() {
36            spinner.finish_with_message(message.to_string());
37        } else if self.verbose {
38            println!("{}", format!("✅ {}", message).green());
39        }
40    }
41
42    pub fn info(&self, message: &str) {
43        if self.verbose {
44            println!("{}", format!("ℹ️  {}", message).bright_blue());
45        }
46    }
47
48    pub fn success(&self, message: &str) {
49        println!("{}", format!("✅ {}", message).green());
50    }
51
52    pub fn warning(&self, message: &str) {
53        println!("{}", format!("⚠️  {}", message).yellow());
54    }
55
56    pub fn error(&self, message: &str) {
57        eprintln!("{}", format!("❌ {}", message).red());
58    }
59}
60
61impl Drop for ProgressReporter {
62    fn drop(&mut self) {
63        if let Some(spinner) = self.spinner.take() {
64            spinner.finish_and_clear();
65        }
66    }
67}