velocity 0.1.2

A next level TUI Library
Documentation
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!();
    }
}