probar 0.1.1

A progress bar.
Documentation
use crossterm::terminal::size;
use std::fmt;

#[derive(Debug, Clone)]
pub struct ProgressBar {
    current: usize,
    total: usize,
    columns: usize,
}

impl ProgressBar {
    pub fn new<T>(total: T) -> Self
    where
        T: TryInto<usize>,
        T::Error: fmt::Debug,
    {
        let (t_columns, _) = size().unwrap();

        Self {
            current: 0,
            total: total.try_into().unwrap(),
            columns: t_columns.into(),
        }
    }
}

impl Iterator for ProgressBar {
    type Item = ProgressBar;
    fn next(&mut self) -> Option<Self::Item> {
        if self.current == self.total {
            println!();
            return None;
        }
        self.current += 1;
        let percent = (self.current as f64 / self.total as f64 * 100.0) as usize;

        let calc_message = format!(
            "  current: {:3}/{:3} {:3}% ",
            self.current, self.total, percent
        );

        let mut bar = String::new();

        let actual_columns = self.columns - calc_message.len() - 2;

        let actual_percent = (percent as f64 / 100.0) * actual_columns as f64;

        bar.push('[');
        for _ in 0..actual_percent as usize {
            bar.push('#');
        }
        for _ in actual_percent as usize..actual_columns {
            bar.push('.');
        }
        bar.push(']');

        let message = format!("\r{}{}", bar, calc_message);
        print!("{}", message);
        std::io::Write::flush(&mut std::io::stdout()).unwrap();

        Some(self.clone())
    }
}

impl<A> FromIterator<A> for ProgressBar {
    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
        let count = iter.into_iter().count();
        Self::new(count as u64)
    }
}

#[cfg(test)]
mod test {
    use std::ops::Range;

    use crate::ProgressBar;

    #[test]
    fn test_hello_world() {
        assert!("hello world".to_string().len() > 0)
    }

    #[test]
    fn test_iter_one() {
        let mut p = ProgressBar::new(10);
        p.next();
        assert_eq!(p.current, 1)
    }
    #[test]
    fn test_iter_two() {
        let mut p = ProgressBar::new(10);
        p.next();
        p.next();
        assert_eq!(p.current, 2)
    }
    #[test]
    fn test_iter_final() {
        let mut p = ProgressBar::new(10);
        for _ in 0..10 {
            p.next();
        }
        assert_eq!(p.current, 10)
    }
    #[test]
    fn test_iter() {
        let p = ProgressBar::new(10);
        let mut count = 0;
        for _ in p {
            count += 1;
        }
        assert_eq!(count, 10)
    }

    #[test]
    fn test_from_iter_i32() {
        let iter: Range<i32> = (0..500).into_iter();
        let mut count = 0;
        let p = ProgressBar::from_iter(iter);
        for _ in p {
            count += 1;
        }
        assert_eq!(count, 500)
    }
}