use std::{fmt::Display, io::IsTerminal, time::Instant};
use cliclack::{spinner, ProgressBar};
use crate::{config::global_config, logger};
pub struct Spinner {
msg: String,
output: SpinnerOutput,
time: Instant,
}
impl Spinner {
pub fn new(msg: &str) -> Self {
let output = if std::io::stdout().is_terminal() {
let pb = spinner();
pb.start(msg);
if global_config().verbose {
pb.stop(msg);
}
SpinnerOutput::Progress(pb)
} else {
logger::info(msg);
SpinnerOutput::Plain()
};
Spinner {
msg: msg.to_owned(),
output,
time: Instant::now(),
}
}
pub fn finish(self) {
self.output.stop(format!(
"{} done in {} secs",
self.msg,
self.time.elapsed().as_secs_f64()
));
}
pub fn fail(self) {
self.output.error(format!(
"{} failed in {} secs",
self.msg,
self.time.elapsed().as_secs_f64()
));
}
pub fn freeze(self) {
self.output.stop(self.msg);
}
}
enum SpinnerOutput {
Progress(ProgressBar),
Plain(),
}
impl SpinnerOutput {
fn error(&self, msg: impl Display) {
match self {
SpinnerOutput::Progress(pb) => pb.error(msg),
SpinnerOutput::Plain() => logger::error(msg),
}
}
fn stop(self, msg: impl Display) {
match self {
SpinnerOutput::Progress(pb) => pb.stop(msg),
SpinnerOutput::Plain() => logger::info(msg),
}
}
}