summaryrefslogtreecommitdiff
path: root/src/progress_bar.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/progress_bar.rs')
-rw-r--r--src/progress_bar.rs93
1 files changed, 23 insertions, 70 deletions
diff --git a/src/progress_bar.rs b/src/progress_bar.rs
index 7f07ad5..837c4c7 100644
--- a/src/progress_bar.rs
+++ b/src/progress_bar.rs
@@ -1,100 +1,53 @@
-use anyhow::{bail, Result};
-use ratatui::text::{Line, Span};
-use std::fmt::Write;
+use std::io::{self, StdoutLock, Write};
-const PREFIX: &str = "Progress: [";
+use crossterm::{
+ style::{Color, ResetColor, SetForegroundColor},
+ QueueableCommand,
+};
+
+const PREFIX: &[u8] = b"Progress: [";
const PREFIX_WIDTH: u16 = PREFIX.len() as u16;
// Leaving the last char empty (_) for `total` > 99.
const POSTFIX_WIDTH: u16 = "] xxx/xx exercises_".len() as u16;
const WRAPPER_WIDTH: u16 = PREFIX_WIDTH + POSTFIX_WIDTH;
const MIN_LINE_WIDTH: u16 = WRAPPER_WIDTH + 4;
-const PROGRESS_EXCEEDS_MAX_ERR: &str =
- "The progress of the progress bar is higher than the maximum";
-
/// Terminal progress bar to be used when not using Ratataui.
-pub fn progress_bar(progress: u16, total: u16, line_width: u16) -> Result<String> {
- use ratatui::crossterm::style::Stylize;
-
- if progress > total {
- bail!(PROGRESS_EXCEEDS_MAX_ERR);
- }
+pub fn progress_bar(
+ stdout: &mut StdoutLock,
+ progress: u16,
+ total: u16,
+ line_width: u16,
+) -> io::Result<()> {
+ debug_assert!(progress <= total);
if line_width < MIN_LINE_WIDTH {
- return Ok(format!("Progress: {progress}/{total} exercises"));
+ return write!(stdout, "Progress: {progress}/{total} exercises");
}
- let mut line = String::with_capacity(usize::from(line_width));
- line.push_str(PREFIX);
+ stdout.write_all(PREFIX)?;
let width = line_width - WRAPPER_WIDTH;
let filled = (width * progress) / total;
- let mut green_part = String::with_capacity(usize::from(filled + 1));
+ stdout.queue(SetForegroundColor(Color::Green))?;
for _ in 0..filled {
- green_part.push('#');
+ stdout.write_all(b"#")?;
}
if filled < width {
- green_part.push('>');
+ stdout.write_all(b">")?;
}
- write!(line, "{}", green_part.green()).unwrap();
let width_minus_filled = width - filled;
if width_minus_filled > 1 {
let red_part_width = width_minus_filled - 1;
- let mut red_part = String::with_capacity(usize::from(red_part_width));
+ stdout.queue(SetForegroundColor(Color::Red))?;
for _ in 0..red_part_width {
- red_part.push('-');
+ stdout.write_all(b"-")?;
}
- write!(line, "{}", red_part.red()).unwrap();
- }
-
- writeln!(line, "] {progress:>3}/{total} exercises").unwrap();
-
- Ok(line)
-}
-
-/// Progress bar to be used with Ratataui.
-// Not using Ratatui's Gauge widget to keep the progress bar consistent.
-pub fn progress_bar_ratatui(progress: u16, total: u16, line_width: u16) -> Result<Line<'static>> {
- use ratatui::style::Stylize;
-
- if progress > total {
- bail!(PROGRESS_EXCEEDS_MAX_ERR);
- }
-
- if line_width < MIN_LINE_WIDTH {
- return Ok(Line::raw(format!("Progress: {progress}/{total} exercises")));
}
- let mut spans = Vec::with_capacity(4);
- spans.push(Span::raw(PREFIX));
-
- let width = line_width - WRAPPER_WIDTH;
- let filled = (width * progress) / total;
-
- let mut green_part = String::with_capacity(usize::from(filled + 1));
- for _ in 0..filled {
- green_part.push('#');
- }
-
- if filled < width {
- green_part.push('>');
- }
- spans.push(green_part.green());
-
- let width_minus_filled = width - filled;
- if width_minus_filled > 1 {
- let red_part_width = width_minus_filled - 1;
- let mut red_part = String::with_capacity(usize::from(red_part_width));
- for _ in 0..red_part_width {
- red_part.push('-');
- }
- spans.push(red_part.red());
- }
-
- spans.push(Span::raw(format!("] {progress:>3}/{total} exercises")));
-
- Ok(Line::from(spans))
+ stdout.queue(ResetColor)?;
+ write!(stdout, "] {progress:>3}/{total} exercises")
}