#![allow(dead_code)]
use indicatif::{ProgressBar as IndicatifBar, ProgressStyle};
use std::time::Duration;
pub struct Spinner {
inner: IndicatifBar,
}
impl Spinner {
pub fn new(message: &str) -> Self {
let pb = IndicatifBar::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));
Self { inner: pb }
}
pub fn with_style(message: &str, color: &str) -> Self {
let pb = IndicatifBar::new_spinner();
let template = format!("{{spinner:.{}}} {{msg}}", color);
pb.set_style(
ProgressStyle::default_spinner().template(&template).unwrap().tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"),
);
pb.set_message(message.to_string());
pb.enable_steady_tick(Duration::from_millis(80));
Self { inner: pb }
}
pub fn set_message(&self, message: &str) {
self.inner.set_message(message.to_string());
}
pub fn finish(&self) {
self.inner.finish_and_clear();
}
pub fn finish_with_message(&self, message: &str) {
self.inner.finish_with_message(message.to_string());
}
}
pub struct ProgressBar {
inner: IndicatifBar,
}
impl ProgressBar {
pub fn new(total: u64) -> Self {
let pb = IndicatifBar::new(total);
pb.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{bar:40.cyan/blue}] {pos}/{len} ({percent}%) {msg}")
.unwrap()
.progress_chars("━━╺"),
);
Self { inner: pb }
}
pub fn new_bytes(total: u64) -> Self {
let pb = IndicatifBar::new(total);
pb.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}) {msg}")
.unwrap()
.progress_chars("━━╺"),
);
Self { inner: pb }
}
pub fn new_files(total: u64) -> Self {
let pb = IndicatifBar::new(total);
pb.set_style(
ProgressStyle::default_bar()
.template(
"{spinner:.green} [{bar:40.cyan/blue}] {pos}/{len} files ({percent}%) {msg}",
)
.unwrap()
.progress_chars("━━╺"),
);
Self { inner: pb }
}
pub fn set_position(&self, pos: u64) {
self.inner.set_position(pos);
}
pub fn inc(&self, delta: u64) {
self.inner.inc(delta);
}
pub fn set_message(&self, message: &str) {
self.inner.set_message(message.to_string());
}
pub fn finish(&self) {
self.inner.finish();
}
pub fn finish_and_clear(&self) {
self.inner.finish_and_clear();
}
pub fn finish_with_message(&self, message: &str) {
self.inner.finish_with_message(message.to_string());
}
pub fn position(&self) -> u64 {
self.inner.position()
}
pub fn length(&self) -> Option<u64> {
self.inner.length()
}
}
pub struct MultiProgress {
inner: indicatif::MultiProgress,
}
impl MultiProgress {
pub fn new() -> Self {
Self { inner: indicatif::MultiProgress::new() }
}
pub fn add_spinner(&self, message: &str) -> Spinner {
let pb = self.inner.add(IndicatifBar::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));
Spinner { inner: pb }
}
pub fn add_progress(&self, total: u64) -> ProgressBar {
let pb = self.inner.add(IndicatifBar::new(total));
pb.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{bar:40.cyan/blue}] {pos}/{len} ({percent}%) {msg}")
.unwrap()
.progress_chars("━━╺"),
);
ProgressBar { inner: pb }
}
}
impl Default for MultiProgress {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_spinner_creation() {
let spinner = Spinner::new("Testing...");
spinner.set_message("Updated");
spinner.finish();
}
#[test]
fn test_progress_bar_creation() {
let pb = ProgressBar::new(100);
pb.set_position(50);
pb.inc(10);
assert_eq!(pb.position(), 60);
pb.finish();
}
#[test]
fn test_progress_bar_bytes() {
let pb = ProgressBar::new_bytes(1024 * 1024);
pb.set_position(512 * 1024);
pb.finish();
}
}