diff --git a/src/app_state.rs b/src/app_state.rs index de5a382..99772b7 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -396,8 +396,16 @@ impl AppState { } // Return the exercise index of the first pending exercise found. - fn check_all_exercises(&mut self, stdout: &mut StdoutLock) -> Result> { - stdout.write_all(FINAL_CHECK_MSG)?; + pub fn check_all_exercises( + &mut self, + stdout: &mut StdoutLock, + final_check: bool, + ) -> Result> { + if !final_check { + stdout.write_all(INTERMEDIATE_CHECK_MSG)?; + } else { + stdout.write_all(FINAL_CHECK_MSG)?; + } let n_exercises = self.exercises.len(); let (mut checked_count, mut results) = thread::scope(|s| { @@ -513,7 +521,7 @@ impl AppState { stdout.write_all(b"\n")?; } - if let Some(pending_exercise_ind) = self.check_all_exercises(stdout)? { + if let Some(pending_exercise_ind) = self.check_all_exercises(stdout, true)? { stdout.write_all(b"\n\n")?; self.current_exercise_ind = pending_exercise_ind; @@ -525,6 +533,12 @@ impl AppState { // Write that the last exercise is done. self.write()?; + self.render_final_message(stdout)?; + + Ok(ExercisesProgress::AllDone) + } + + pub fn render_final_message(&self, stdout: &mut StdoutLock) -> Result<()> { clear_terminal(stdout)?; stdout.write_all(FENISH_LINE.as_bytes())?; @@ -534,12 +548,14 @@ impl AppState { stdout.write_all(b"\n")?; } - Ok(ExercisesProgress::AllDone) + Ok(()) } } const BAD_INDEX_ERR: &str = "The current exercise index is higher than the number of exercises"; const STATE_FILE_HEADER: &[u8] = b"DON'T EDIT THIS FILE!\n\n"; +const INTERMEDIATE_CHECK_MSG: &[u8] = b"Checking all exercises +"; const FINAL_CHECK_MSG: &[u8] = b"All exercises seem to be done. Recompiling and running all exercises to make sure that all of them are actually done. "; diff --git a/src/watch.rs b/src/watch.rs index 35533b0..b984675 100644 --- a/src/watch.rs +++ b/src/watch.rs @@ -103,6 +103,13 @@ fn run_watch( WatchEvent::Input(InputEvent::Run) => watch_state.run_current_exercise(&mut stdout)?, WatchEvent::Input(InputEvent::Hint) => watch_state.show_hint(&mut stdout)?, WatchEvent::Input(InputEvent::List) => return Ok(WatchExit::List), + WatchEvent::Input(InputEvent::CheckAll) => match watch_state + .check_all_exercises(&mut stdout)? + { + ExercisesProgress::AllDone => break, + ExercisesProgress::NewPending => watch_state.run_current_exercise(&mut stdout)?, + ExercisesProgress::CurrentPending => (), + }, WatchEvent::Input(InputEvent::Reset) => watch_state.reset_exercise(&mut stdout)?, WatchEvent::Input(InputEvent::Quit) => { stdout.write_all(QUIT_MSG)?; diff --git a/src/watch/state.rs b/src/watch/state.rs index 19910f0..67a6357 100644 --- a/src/watch/state.rs +++ b/src/watch/state.rs @@ -195,6 +195,11 @@ impl<'a> WatchState<'a> { stdout.queue(ResetColor)?; stdout.write_all(b":list / ")?; + stdout.queue(SetAttribute(Attribute::Bold))?; + stdout.write_all(b"c")?; + stdout.queue(ResetColor)?; + stdout.write_all(b":check all / ")?; + stdout.queue(SetAttribute(Attribute::Bold))?; stdout.write_all(b"x")?; stdout.queue(ResetColor)?; @@ -274,6 +279,23 @@ impl<'a> WatchState<'a> { Ok(()) } + pub fn check_all_exercises(&mut self, stdout: &mut StdoutLock) -> Result { + stdout.write_all(b"\n")?; + + if let Some(first_fail) = self.app_state.check_all_exercises(stdout, false)? { + // Only change exercise if the current one is done... + if self.app_state.current_exercise().done { + self.app_state.set_current_exercise_ind(first_fail)?; + } + // ...but always pretend it's a "new" anyway because that refreshes + // the display + Ok(ExercisesProgress::NewPending) + } else { + self.app_state.render_final_message(stdout)?; + Ok(ExercisesProgress::AllDone) + } + } + pub fn update_term_width(&mut self, width: u16, stdout: &mut StdoutLock) -> io::Result<()> { if self.term_width != width { self.term_width = width; diff --git a/src/watch/terminal_event.rs b/src/watch/terminal_event.rs index 1ed681d..48411db 100644 --- a/src/watch/terminal_event.rs +++ b/src/watch/terminal_event.rs @@ -11,6 +11,7 @@ pub enum InputEvent { Run, Hint, List, + CheckAll, Reset, Quit, } @@ -37,6 +38,7 @@ pub fn terminal_event_handler( KeyCode::Char('r') if manual_run => InputEvent::Run, KeyCode::Char('h') => InputEvent::Hint, KeyCode::Char('l') => break WatchEvent::Input(InputEvent::List), + KeyCode::Char('c') => InputEvent::CheckAll, KeyCode::Char('x') => { if sender.send(WatchEvent::Input(InputEvent::Reset)).is_err() { return;