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}