use std::io::{self, Write};
use std::thread;
use std::time::Duration;
use rand::prelude::*;
pub enum Styles {
Square,
Arrow,
Npm,
Custom(char, char),
}
pub struct Bar<'a> {
style: Styles,
title: Option<&'a str>,
width: u16,
pub percent: u8,
}
impl<'a> Bar<'a> {
pub fn new(style: Styles) -> Self {
let width = match term_size::dimensions() {
Some((w, _)) => w,
None => 80,
};
Self {
style,
title: None,
width: width.try_into().unwrap(),
percent: 0,
}
}
pub fn set_title(&mut self, title: &'a str) {
self.title = Some(title)
}
pub fn set_width(&mut self, percent: u16) {
let (w, _) = term_size::dimensions().unwrap_or((80, 24));
self.width = (w as f32 * (percent as f32 / 100.0)) as u16;
}
pub fn print(&mut self, amount: u8) {
let (done, todo) = match self.style {
Styles::Square => ('█'.to_string(), ' '.to_string()),
Styles::Arrow => ('>'.to_string(), ' '.to_string()),
Styles::Npm => (
"\x1B[48;2;130;139;184m#\x1B[0m".to_string(),
"\x1B[48;2;80;83;105m·\x1B[0m".to_string(),
),
Styles::Custom(done_char, todo_char) => (done_char.to_string(), todo_char.to_string()),
};
self.percent = amount;
let bar_width = (self.width as u16 - 7) as f32;
let done_width = (self.percent as f32 / 100.0 * bar_width) as u16;
let todo_width = bar_width as u16 - done_width;
print!("\r[");
for _ in 0..done_width {
print!("{}", done);
}
for _ in 0..todo_width {
print!("{}", todo);
}
print!("] {:>3}%", self.percent);
io::stdout().flush().unwrap();
}
pub fn start(&mut self) {
let title = match self.title {
Some(title) => format!("{}", title),
None => String::new(),
};
println!("{}", title);
self.print(0);
}
pub fn jump(&mut self, amount: u8) {
self.print(amount)
}
pub fn inc(&mut self, amount: u8) {
self.percent += amount;
self.print(self.percent);
}
pub fn repeat_until<F>(&mut self, mut f: F, s: u64)
where
F: FnMut(),
{
let mut percent: u8 = 0;
loop {
self.print(percent);
thread::sleep(Duration::from_millis(s));
percent += rand::thread_rng().gen_range(1..=2);
if percent >= 12 {
break;
}
}
f();
percent += rand::thread_rng().gen_range(19..=23);
self.print(percent);
loop {
self.print(percent);
if percent >= 100 {
break;
}
percent += rand::thread_rng().gen_range(3..=14);
percent = percent.min(100);
thread::sleep(Duration::from_millis(500));
}
}
pub fn end(&self) {
println!();
}
}