use std::io::{self, Write};
use std::time::Instant;
use crate::spinner::Spinner;
pub struct Status {
pub spinner: Spinner,
pub status: String,
pub started: Option<Instant>,
}
impl std::fmt::Debug for Status {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Status")
.field("status", &self.status)
.field("started", &self.started)
.finish()
}
}
impl Status {
pub fn new(status: impl Into<String>) -> Self {
Self {
spinner: Spinner::default(),
status: status.into(),
started: None,
}
}
pub fn spinner(mut self, spinner: Spinner) -> Self { self.spinner = spinner; self }
pub fn start(&mut self) -> io::Result<()> {
self.started = Some(Instant::now());
self.write_status()
}
pub fn update(&mut self, status: impl Into<String>) -> io::Result<()> {
self.status = status.into();
self.write_status()
}
pub fn stop(&mut self) -> io::Result<()> {
let _ = write!(io::stdout(), "\r\x1b[K");
let _ = io::stdout().flush();
self.started = None;
Ok(())
}
pub fn refresh(&mut self) -> io::Result<()> {
self.write_status()
}
fn write_status(&mut self) -> io::Result<()> {
let elapsed = self.started.map(|s| s.elapsed()).unwrap_or_default();
let spinner_str = self.spinner.render(elapsed);
write!(io::stdout(), "\r{spinner_str} {}", self.status)?;
io::stdout().flush()
}
}