summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormo8it <mo8it@proton.me>2024-10-14 01:06:11 +0200
committermo8it <mo8it@proton.me>2024-10-14 01:06:11 +0200
commitea73af9ba37bc1f6155a910c72f2ded8a0b64805 (patch)
tree039b8011ae5140baacc848195530d337725a319b /src
parentfc5fc0920f3590d1b1e8c8186309ac1c5ec6fba5 (diff)
Separate initialization with a struct
Diffstat (limited to 'src')
-rw-r--r--src/app_state.rs13
-rw-r--r--src/term.rs125
2 files changed, 74 insertions, 64 deletions
diff --git a/src/app_state.rs b/src/app_state.rs
index 76a4c45..57ffea8 100644
--- a/src/app_state.rs
+++ b/src/app_state.rs
@@ -20,7 +20,7 @@ use crate::{
embedded::EMBEDDED_FILES,
exercise::{Exercise, RunnableExercise},
info_file::ExerciseInfo,
- term::{self, show_exercises_check_progress},
+ term::{self, ExercisesCheckProgressVisualizer},
};
const STATE_FILE_NAME: &str = ".rustlings-state.txt";
@@ -409,13 +409,12 @@ impl AppState {
}
fn check_all_exercises_impl(&mut self, stdout: &mut StdoutLock) -> Result<Option<usize>> {
- stdout.write_all("Checking all exercises…\n".as_bytes())?;
- let next_exercise_ind = AtomicUsize::new(0);
let term_width = terminal::size()
.context("Failed to get the terminal size")?
.0;
- clear_terminal(stdout)?;
+ let mut progress_visualizer = ExercisesCheckProgressVisualizer::build(stdout, term_width)?;
+ let next_exercise_ind = AtomicUsize::new(0);
let mut progresses = vec![ExerciseCheckProgress::None; self.exercises.len()];
thread::scope(|s| {
@@ -464,7 +463,7 @@ impl AppState {
while let Ok((exercise_ind, progress)) = exercise_progress_receiver.recv() {
progresses[exercise_ind] = progress;
- show_exercises_check_progress(stdout, &progresses, term_width)?;
+ progress_visualizer.update(&progresses)?;
}
Ok::<_, Error>(())
@@ -487,7 +486,7 @@ impl AppState {
// it could be because we exceeded the limit of open file descriptors.
// Therefore, try running exercises with errors sequentially.
progresses[exercise_ind] = ExerciseCheckProgress::Checking;
- show_exercises_check_progress(stdout, &progresses, term_width)?;
+ progress_visualizer.update(&progresses)?;
let exercise = &self.exercises[exercise_ind];
let success = exercise.run_exercise(None, &self.cmd_runner)?;
@@ -501,7 +500,7 @@ impl AppState {
}
self.set_status(exercise_ind, success)?;
- show_exercises_check_progress(stdout, &progresses, term_width)?;
+ progress_visualizer.update(&progresses)?;
}
}
}
diff --git a/src/term.rs b/src/term.rs
index 8a2f8c5..13d5657 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -87,6 +87,74 @@ impl<'a> CountedWrite<'a> for StdoutLock<'a> {
}
}
+pub struct ExercisesCheckProgressVisualizer<'a, 'b> {
+ stdout: &'a mut StdoutLock<'b>,
+ n_cols: usize,
+}
+
+impl<'a, 'b> ExercisesCheckProgressVisualizer<'a, 'b> {
+ pub fn build(stdout: &'a mut StdoutLock<'b>, term_width: u16) -> io::Result<Self> {
+ clear_terminal(stdout)?;
+ stdout.write_all("Checking all exercises…\n".as_bytes())?;
+
+ // Legend
+ stdout.write_all(b"Color of exercise number: ")?;
+ stdout.queue(SetForegroundColor(Color::Blue))?;
+ stdout.write_all(b"Checking")?;
+ stdout.queue(ResetColor)?;
+ stdout.write_all(b" - ")?;
+ stdout.queue(SetForegroundColor(Color::Green))?;
+ stdout.write_all(b"Done")?;
+ stdout.queue(ResetColor)?;
+ stdout.write_all(b" - ")?;
+ stdout.queue(SetForegroundColor(Color::Red))?;
+ stdout.write_all(b"Pending")?;
+ stdout.queue(ResetColor)?;
+ stdout.write_all(b"\n")?;
+
+ // Exercise numbers with up to 3 digits.
+ // +1 because the last column doesn't end with a whitespace.
+ let n_cols = usize::from(term_width + 1) / 4;
+
+ Ok(Self { stdout, n_cols })
+ }
+
+ pub fn update(&mut self, progresses: &[ExerciseCheckProgress]) -> io::Result<()> {
+ self.stdout.queue(MoveTo(0, 2))?;
+
+ let mut exercise_num = 1;
+ for exercise_progress in progresses {
+ match exercise_progress {
+ ExerciseCheckProgress::None => (),
+ ExerciseCheckProgress::Checking => {
+ self.stdout.queue(SetForegroundColor(Color::Blue))?;
+ }
+ ExerciseCheckProgress::Done => {
+ self.stdout.queue(SetForegroundColor(Color::Green))?;
+ }
+ ExerciseCheckProgress::Pending => {
+ self.stdout.queue(SetForegroundColor(Color::Red))?;
+ }
+ }
+
+ write!(self.stdout, "{exercise_num:<3}")?;
+ self.stdout.queue(ResetColor)?;
+
+ if exercise_num != progresses.len() {
+ if exercise_num % self.n_cols == 0 {
+ self.stdout.write_all(b"\n")?;
+ } else {
+ self.stdout.write_all(b" ")?;
+ }
+
+ exercise_num += 1;
+ }
+ }
+
+ self.stdout.flush()
+ }
+}
+
pub fn progress_bar<'a>(
writer: &mut impl CountedWrite<'a>,
progress: u16,
@@ -137,63 +205,6 @@ pub fn progress_bar<'a>(
write!(stdout, "] {progress:>3}/{total}")
}
-pub fn show_exercises_check_progress(
- stdout: &mut StdoutLock,
- progresses: &[ExerciseCheckProgress],
- term_width: u16,
-) -> io::Result<()> {
- stdout.queue(MoveTo(0, 0))?;
-
- // Legend
- stdout.write_all(b"Color of exercise number: ")?;
- stdout.queue(SetForegroundColor(Color::Blue))?;
- stdout.write_all(b"Checking")?;
- stdout.queue(ResetColor)?;
- stdout.write_all(b" - ")?;
- stdout.queue(SetForegroundColor(Color::Green))?;
- stdout.write_all(b"Done")?;
- stdout.queue(ResetColor)?;
- stdout.write_all(b" - ")?;
- stdout.queue(SetForegroundColor(Color::Red))?;
- stdout.write_all(b"Pending")?;
- stdout.queue(ResetColor)?;
- stdout.write_all(b"\n")?;
-
- // Exercise numbers with up to 3 digits.
- let n_cols = usize::from(term_width + 1) / 4;
-
- let mut exercise_num = 1;
- for exercise_progress in progresses {
- match exercise_progress {
- ExerciseCheckProgress::None => (),
- ExerciseCheckProgress::Checking => {
- stdout.queue(SetForegroundColor(Color::Blue))?;
- }
- ExerciseCheckProgress::Done => {
- stdout.queue(SetForegroundColor(Color::Green))?;
- }
- ExerciseCheckProgress::Pending => {
- stdout.queue(SetForegroundColor(Color::Red))?;
- }
- }
-
- write!(stdout, "{exercise_num:<3}")?;
- stdout.queue(ResetColor)?;
-
- if exercise_num != progresses.len() {
- if exercise_num % n_cols == 0 {
- stdout.write_all(b"\n")?;
- } else {
- stdout.write_all(b" ")?;
- }
-
- exercise_num += 1;
- }
- }
-
- stdout.flush()
-}
-
pub fn clear_terminal(stdout: &mut StdoutLock) -> io::Result<()> {
stdout
.queue(MoveTo(0, 0))?