summaryrefslogtreecommitdiff
path: root/src/app_state.rs
diff options
context:
space:
mode:
authorNahor <nahor.j+github@gmail.com>2024-10-02 15:28:42 -0700
committerNahor <nahor.j+github@gmail.com>2024-10-02 15:28:42 -0700
commitaa83fd6bc46167477447ee9b95d21e551e163411 (patch)
treec15cc593bf41d6f6d7ea965bfc52d58a2ff64e80 /src/app_state.rs
parente2f7734f37394097f330c4073bf7784500afdc9d (diff)
Show a progress bar when running check_all
Replace the "Progress: xxx/yyy" with a progress bar when checking all the exercises
Diffstat (limited to 'src/app_state.rs')
-rw-r--r--src/app_state.rs93
1 files changed, 72 insertions, 21 deletions
diff --git a/src/app_state.rs b/src/app_state.rs
index ec79188..f4cc180 100644
--- a/src/app_state.rs
+++ b/src/app_state.rs
@@ -1,4 +1,9 @@
use anyhow::{bail, Context, Result};
+use crossterm::{
+ queue,
+ style::{Print, ResetColor, SetForegroundColor},
+ terminal,
+};
use std::{
env,
fs::{File, OpenOptions},
@@ -16,7 +21,7 @@ use crate::{
embedded::EMBEDDED_FILES,
exercise::{Exercise, RunnableExercise},
info_file::ExerciseInfo,
- term,
+ term::{self, progress_bar_with_success},
};
const STATE_FILE_NAME: &str = ".rustlings-state.txt";
@@ -428,10 +433,16 @@ impl AppState {
// No more exercises
break;
};
- if tx
- .send((exercise_ind, exercise.run_exercise(None, &this.cmd_runner)))
- .is_err()
- {
+
+ // Notify the progress bar that this exercise is pending
+ if tx.send((exercise_ind, None)).is_err() {
+ break;
+ };
+
+ let result = exercise.run_exercise(None, &this.cmd_runner);
+
+ // Notify the progress bar that this exercise is done
+ if tx.send((exercise_ind, Some(result))).is_err() {
break;
}
}
@@ -443,28 +454,68 @@ impl AppState {
// there are `tx` clones, i.e. threads)
drop(tx);
+ // Print the legend
+ queue!(
+ stdout,
+ Print("Color legend: "),
+ SetForegroundColor(term::PROGRESS_FAILED_COLOR),
+ Print("Failure"),
+ ResetColor,
+ Print(" - "),
+ SetForegroundColor(term::PROGRESS_SUCCESS_COLOR),
+ Print("Success"),
+ ResetColor,
+ Print(" - "),
+ SetForegroundColor(term::PROGRESS_PENDING_COLOR),
+ Print("Checking"),
+ ResetColor,
+ Print("\n"),
+ )
+ .unwrap();
+ // We expect at least a few "pending" notifications shortly, so don't
+ // bother printing the initial state of the progress bar and flushing
+ // stdout
+
+ let line_width = terminal::size().unwrap().0;
let mut results = vec![AllExercisesResult::Pending; n_exercises];
- let mut checked_count = 0;
- write!(stdout, "\rProgress: {checked_count}/{n_exercises}")?;
- stdout.flush()?;
+ let mut pending = 0;
+ let mut success = 0;
+ let mut failed = 0;
+
while let Ok((exercise_ind, result)) = rx.recv() {
- results[exercise_ind] = result.map_or_else(
- |_| AllExercisesResult::Error,
- |success| {
- checked_count += 1;
- if success {
- AllExercisesResult::Success
- } else {
- AllExercisesResult::Failed
- }
- },
- );
+ match result {
+ None => {
+ pending += 1;
+ }
+ Some(Err(_)) => {
+ results[exercise_ind] = AllExercisesResult::Error;
+ }
+ Some(Ok(true)) => {
+ results[exercise_ind] = AllExercisesResult::Success;
+ pending -= 1;
+ success += 1;
+ }
+ Some(Ok(false)) => {
+ results[exercise_ind] = AllExercisesResult::Failed;
+ pending -= 1;
+ failed += 1;
+ }
+ }
- write!(stdout, "\rProgress: {checked_count}/{n_exercises}")?;
+ write!(stdout, "\r").unwrap();
+ progress_bar_with_success(
+ stdout,
+ pending,
+ failed,
+ success,
+ n_exercises as u16,
+ line_width,
+ )
+ .unwrap();
stdout.flush()?;
}
- Ok::<_, io::Error>((checked_count, results))
+ Ok::<_, io::Error>((success, results))
})?;
// If we got an error while checking all exercises in parallel,