mirror of
https://github.com/notohh/rustlings.git
synced 2024-12-17 22:58:08 -05:00
Add command to check all the exercises
This allows for skipping repeating "next" when multiple exercises are done at once, or when earlier exercises have been updated/changed (and thus must be redone) while still working of the whole set (i.e. the final check_all is not yet available to flag those undone exercises)
This commit is contained in:
parent
26fd97a209
commit
c52867eb8b
4 changed files with 51 additions and 4 deletions
|
@ -396,8 +396,16 @@ impl AppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the exercise index of the first pending exercise found.
|
// Return the exercise index of the first pending exercise found.
|
||||||
fn check_all_exercises(&mut self, stdout: &mut StdoutLock) -> Result<Option<usize>> {
|
pub fn check_all_exercises(
|
||||||
stdout.write_all(FINAL_CHECK_MSG)?;
|
&mut self,
|
||||||
|
stdout: &mut StdoutLock,
|
||||||
|
final_check: bool,
|
||||||
|
) -> Result<Option<usize>> {
|
||||||
|
if !final_check {
|
||||||
|
stdout.write_all(INTERMEDIATE_CHECK_MSG)?;
|
||||||
|
} else {
|
||||||
|
stdout.write_all(FINAL_CHECK_MSG)?;
|
||||||
|
}
|
||||||
let n_exercises = self.exercises.len();
|
let n_exercises = self.exercises.len();
|
||||||
|
|
||||||
let (mut checked_count, mut results) = thread::scope(|s| {
|
let (mut checked_count, mut results) = thread::scope(|s| {
|
||||||
|
@ -513,7 +521,7 @@ impl AppState {
|
||||||
stdout.write_all(b"\n")?;
|
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")?;
|
stdout.write_all(b"\n\n")?;
|
||||||
|
|
||||||
self.current_exercise_ind = pending_exercise_ind;
|
self.current_exercise_ind = pending_exercise_ind;
|
||||||
|
@ -525,6 +533,12 @@ impl AppState {
|
||||||
// Write that the last exercise is done.
|
// Write that the last exercise is done.
|
||||||
self.write()?;
|
self.write()?;
|
||||||
|
|
||||||
|
self.render_final_message(stdout)?;
|
||||||
|
|
||||||
|
Ok(ExercisesProgress::AllDone)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_final_message(&self, stdout: &mut StdoutLock) -> Result<()> {
|
||||||
clear_terminal(stdout)?;
|
clear_terminal(stdout)?;
|
||||||
stdout.write_all(FENISH_LINE.as_bytes())?;
|
stdout.write_all(FENISH_LINE.as_bytes())?;
|
||||||
|
|
||||||
|
@ -534,12 +548,14 @@ impl AppState {
|
||||||
stdout.write_all(b"\n")?;
|
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 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 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.
|
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.
|
Recompiling and running all exercises to make sure that all of them are actually done.
|
||||||
";
|
";
|
||||||
|
|
|
@ -103,6 +103,13 @@ fn run_watch(
|
||||||
WatchEvent::Input(InputEvent::Run) => watch_state.run_current_exercise(&mut stdout)?,
|
WatchEvent::Input(InputEvent::Run) => watch_state.run_current_exercise(&mut stdout)?,
|
||||||
WatchEvent::Input(InputEvent::Hint) => watch_state.show_hint(&mut stdout)?,
|
WatchEvent::Input(InputEvent::Hint) => watch_state.show_hint(&mut stdout)?,
|
||||||
WatchEvent::Input(InputEvent::List) => return Ok(WatchExit::List),
|
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::Reset) => watch_state.reset_exercise(&mut stdout)?,
|
||||||
WatchEvent::Input(InputEvent::Quit) => {
|
WatchEvent::Input(InputEvent::Quit) => {
|
||||||
stdout.write_all(QUIT_MSG)?;
|
stdout.write_all(QUIT_MSG)?;
|
||||||
|
|
|
@ -195,6 +195,11 @@ impl<'a> WatchState<'a> {
|
||||||
stdout.queue(ResetColor)?;
|
stdout.queue(ResetColor)?;
|
||||||
stdout.write_all(b":list / ")?;
|
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.queue(SetAttribute(Attribute::Bold))?;
|
||||||
stdout.write_all(b"x")?;
|
stdout.write_all(b"x")?;
|
||||||
stdout.queue(ResetColor)?;
|
stdout.queue(ResetColor)?;
|
||||||
|
@ -274,6 +279,23 @@ impl<'a> WatchState<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_all_exercises(&mut self, stdout: &mut StdoutLock) -> Result<ExercisesProgress> {
|
||||||
|
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<()> {
|
pub fn update_term_width(&mut self, width: u16, stdout: &mut StdoutLock) -> io::Result<()> {
|
||||||
if self.term_width != width {
|
if self.term_width != width {
|
||||||
self.term_width = width;
|
self.term_width = width;
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub enum InputEvent {
|
||||||
Run,
|
Run,
|
||||||
Hint,
|
Hint,
|
||||||
List,
|
List,
|
||||||
|
CheckAll,
|
||||||
Reset,
|
Reset,
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
@ -37,6 +38,7 @@ pub fn terminal_event_handler(
|
||||||
KeyCode::Char('r') if manual_run => InputEvent::Run,
|
KeyCode::Char('r') if manual_run => InputEvent::Run,
|
||||||
KeyCode::Char('h') => InputEvent::Hint,
|
KeyCode::Char('h') => InputEvent::Hint,
|
||||||
KeyCode::Char('l') => break WatchEvent::Input(InputEvent::List),
|
KeyCode::Char('l') => break WatchEvent::Input(InputEvent::List),
|
||||||
|
KeyCode::Char('c') => InputEvent::CheckAll,
|
||||||
KeyCode::Char('x') => {
|
KeyCode::Char('x') => {
|
||||||
if sender.send(WatchEvent::Input(InputEvent::Reset)).is_err() {
|
if sender.send(WatchEvent::Input(InputEvent::Reset)).is_err() {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue