use std::time::{Duration, Instant};
use console::style;
use indicatif::{ProgressBar, ProgressStyle};
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Verbosity {
Quiet,
Normal,
Verbose,
}
pub struct Reporter {
verbosity: Verbosity,
start_time: Instant,
}
impl Reporter {
pub fn new(verbosity: Verbosity) -> Self {
Self {
verbosity,
start_time: Instant::now(),
}
}
pub fn section(&self, icon: &str, title: &str) {
if self.verbosity == Verbosity::Quiet {
return;
}
println!();
println!("{} {}", icon, style(title).bold().cyan());
}
pub fn step(&self, message: &str) -> Step {
Step::new(self.verbosity, message)
}
pub fn warning(&self, message: &str) {
if self.verbosity == Verbosity::Quiet {
return;
}
println!(" {} {}", style("⚠").yellow(), style(message).yellow());
}
pub fn finish(&self) {
if self.verbosity == Verbosity::Quiet {
return;
}
println!();
println!(
"{} Done in {:.1}s",
style("✨").green(),
self.start_time.elapsed().as_secs_f64()
);
}
}
pub struct Step {
spinner: Option<ProgressBar>,
verbosity: Verbosity,
message: String,
}
impl Step {
fn new(verbosity: Verbosity, message: &str) -> Self {
let spinner = if verbosity == Verbosity::Normal {
let pb = ProgressBar::new_spinner();
pb.set_style(
ProgressStyle::default_spinner()
.template(" {spinner:.cyan} {msg}")
.unwrap()
.tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"),
);
pb.set_message(message.to_string());
pb.enable_steady_tick(Duration::from_millis(80));
Some(pb)
} else {
None
};
if verbosity == Verbosity::Verbose {
println!(" {} {}", style("→").cyan(), message);
}
Self {
spinner,
verbosity,
message: message.to_string(),
}
}
pub fn is_verbose(&self) -> bool {
self.verbosity == Verbosity::Verbose
}
pub fn finish_success(self) {
if let Some(pb) = self.spinner {
pb.finish_and_clear();
}
if self.verbosity != Verbosity::Quiet {
println!(" {} {}", style("✓").green(), self.message);
}
}
pub fn finish_success_with(self, message: &str) {
if let Some(pb) = self.spinner {
pb.finish_and_clear();
}
if self.verbosity != Verbosity::Quiet {
println!(" {} {}", style("✓").green(), message);
}
}
}