summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormo8it <mo8it@proton.me>2024-04-10 00:42:32 +0200
committermo8it <mo8it@proton.me>2024-04-10 00:42:32 +0200
commit4a80bf64411f228c35c173b6188df5114d4c52fa (patch)
tree7b4c09c8029167166f3cb5f31dc815eac854a831 /src
parentc8d217ad50a7117fe35735b4083f2aa1e2b47d97 (diff)
Colorize the progress bar
Diffstat (limited to 'src')
-rw-r--r--src/list/state.rs6
-rw-r--r--src/progress_bar.rs92
2 files changed, 77 insertions, 21 deletions
diff --git a/src/list/state.rs b/src/list/state.rs
index b67c624..8918979 100644
--- a/src/list/state.rs
+++ b/src/list/state.rs
@@ -7,7 +7,7 @@ use ratatui::{
Frame,
};
-use crate::{exercise::Exercise, progress_bar::progress_bar, state_file::StateFile};
+use crate::{exercise::Exercise, progress_bar::progress_bar_ratatui, state_file::StateFile};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Filter {
@@ -166,11 +166,11 @@ impl UiState {
);
frame.render_widget(
- Paragraph::new(Span::raw(progress_bar(
+ Paragraph::new(progress_bar_ratatui(
self.progress,
self.exercises.len() as u16,
area.width,
- )?))
+ )?)
.block(Block::default().borders(Borders::BOTTOM)),
Rect {
x: 0,
diff --git a/src/progress_bar.rs b/src/progress_bar.rs
index ee55ba7..97c8ad9 100644
--- a/src/progress_bar.rs
+++ b/src/progress_bar.rs
@@ -1,41 +1,97 @@
use anyhow::{bail, Result};
+use ratatui::text::{Line, Span};
use std::fmt::Write;
+const PREFIX: &str = "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";
+
pub fn progress_bar(progress: u16, total: u16, line_width: u16) -> Result<String> {
+ use crossterm::style::Stylize;
+
if progress > total {
- bail!("The progress of the progress bar is higher than the maximum");
+ bail!(PROGRESS_EXCEEDS_MAX_ERR);
}
- // "Progress: [".len() == 11
- // "] xxx/xx exercises_".len() == 19 (leaving the last char empty for `total` > 99)
- // 11 + 19 = 30
- let wrapper_width = 30;
-
- // If the line width is too low for a progress bar, just show the ratio.
- if line_width < wrapper_width + 4 {
+ if line_width < MIN_LINE_WIDTH {
return Ok(format!("Progress: {progress}/{total} exercises"));
}
let mut line = String::with_capacity(usize::from(line_width));
- line.push_str("Progress: [");
+ line.push_str(PREFIX);
- let remaining_width = line_width.saturating_sub(wrapper_width);
- let filled = (remaining_width * progress) / total;
+ 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 {
- line.push('=');
+ green_part.push('#');
}
- if filled < remaining_width {
- line.push('>');
+ if filled < width {
+ green_part.push('>');
}
+ write!(line, "{}", green_part.green()).unwrap();
- for _ in 0..(remaining_width - filled).saturating_sub(1) {
- line.push(' ');
+ 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('-');
+ }
+ write!(line, "{}", red_part.red()).unwrap();
}
- line.write_fmt(format_args!("] {progress:>3}/{total} exercises"))
- .unwrap();
+ write!(line, "] {progress:>3}/{total} exercises").unwrap();
Ok(line)
}
+
+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))
+}