multi-progressbar 0.1.0

A library for displaying multiple progress bars in the terminal designed to not stand in your way.
Documentation
use std::sync::{Arc, Mutex};

use clap::{Parser, ValueEnum};
use multi_progressbar::{
    bar::block::BlockProgressBar, bar::classic::ClassicProgressBar, MultiProgressBar, ProgressBar,
    TaskProgress,
};

#[derive(Debug, Parser)]
struct Cli {
    #[clap(short, long, default_value = "1")]
    num_tasks: usize,
    #[clap(long, default_value = "classic")]
    bar_type: BarType,
}

#[derive(Debug, Clone, ValueEnum)]
enum BarType {
    Classic,
    Block,
}

struct Task {
    id: usize,
    progress: u64,
    total: u64,
}

impl Task {
    fn new(id: usize, total: u64) -> Self {
        Task {
            id,
            progress: 0,
            total,
        }
    }
    fn inc(&mut self) {
        if self.progress >= self.total {
            return;
        }
        self.progress += 1;
    }
}

impl TaskProgress for Task {
    fn progress(&self) -> (u64, u64) {
        (self.progress, self.total)
    }
    fn before(&self) -> Option<String> {
        Some(format!("task {}", self.id))
    }
}

fn run_demo<P>(cli: &Cli, mp: MultiProgressBar<P>)
where
    P: ProgressBar<Task = Task>,
{
    let tasks = (0..cli.num_tasks)
        .map(|i| Task::new(i, 20))
        .collect::<Vec<_>>();

    let tasks = Arc::new(Mutex::new(tasks));

    let tasks_clone = tasks.clone();

    let drive_task = move || loop {
        std::thread::sleep(std::time::Duration::from_millis(100));
        let mut tasks = tasks_clone.lock().unwrap();
        for task in tasks.iter_mut() {
            task.inc();
        }
    };

    std::thread::spawn(drive_task);

    let mut i = 0;
    loop {
        std::thread::sleep(std::time::Duration::from_millis(100));
        let tasks = tasks.lock().unwrap();

        {
            mp.log(format!("log {}", i).as_str(), tasks.len()).unwrap();
            mp.draw(tasks.as_slice()).unwrap();
        }

        if tasks.is_empty() {
            break;
        }
        i += 1;
    }
}

fn main() {
    let cli = Cli::parse();
    match cli.bar_type {
        BarType::Classic => {
            let mp = MultiProgressBar::new(ClassicProgressBar::new());
            run_demo(&cli, mp);
        }
        BarType::Block => {
            let mp = MultiProgressBar::new(BlockProgressBar::new());
            run_demo(&cli, mp);
        }
    };
}