term_kit/
progressbar.rs

1use crossterm::{
2    cursor, execute,
3    style::{Color, Print, ResetColor, SetForegroundColor},
4    terminal::{Clear, ClearType},
5};
6use std::io::{stdout, Write};
7
8pub struct ProgressBar {
9    pub value: u16,
10    pub max: u16,
11    pub width: u16,
12    pub label: String,
13}
14
15impl ProgressBar {
16    pub fn new(value: u16, max: u16, width: u16, label: String) -> Self {
17        Self {
18            value,
19            max,
20            width,
21            label,
22        }
23    }
24
25    pub fn render(&self) -> Result<(), Box<dyn std::error::Error>> {
26        let percent = (self.value as f64 / self.max as f64) * 100.0;
27        let filled_width = (percent / 100.0 * self.width as f64).round() as u16;
28        let mut stdout = stdout();
29
30        execute!(stdout, cursor::MoveToColumn(0))?;
31        execute!(stdout, Clear(ClearType::UntilNewLine))?;
32        execute!(stdout, Print(format!("{: <20}", self.label)))?;
33        execute!(stdout, Print("["))?;
34        execute!(stdout, SetForegroundColor(Color::Green))?;
35
36        for _ in 0..filled_width {
37            execute!(stdout, Print("■"))?;
38        }
39
40        execute!(stdout, ResetColor)?;
41        for _ in filled_width..self.width {
42            execute!(stdout, Print("-"))?;
43        }
44
45        execute!(stdout, Print("] "), Print(format!("{:.1}%", percent)),)?;
46
47        stdout.flush()?;
48        Ok(())
49    }
50}