Add VerifyState

This commit is contained in:
mo8it 2024-04-01 18:38:01 +02:00
parent fdd7de00bd
commit def8d2c569
2 changed files with 28 additions and 25 deletions

View file

@ -2,10 +2,10 @@ use crate::embedded::{WriteStrategy, EMBEDDED_FILES};
use crate::exercise::{Exercise, ExerciseList}; use crate::exercise::{Exercise, ExerciseList};
use crate::run::run; use crate::run::run;
use crate::verify::verify; use crate::verify::verify;
use anyhow::{Context, Result}; use anyhow::{bail, Context, Result};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use console::Emoji; use console::Emoji;
use notify_debouncer_mini::notify::{self, RecursiveMode}; use notify_debouncer_mini::notify::RecursiveMode;
use notify_debouncer_mini::{new_debouncer, DebouncedEventKind}; use notify_debouncer_mini::{new_debouncer, DebouncedEventKind};
use shlex::Shlex; use shlex::Shlex;
use std::io::{BufRead, Write}; use std::io::{BufRead, Write};
@ -16,6 +16,7 @@ use std::sync::mpsc::{channel, RecvTimeoutError};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use verify::VerifyState;
#[macro_use] #[macro_use]
mod ui; mod ui;
@ -218,9 +219,10 @@ If you are just starting with Rustlings, run the command `rustlings init` to ini
println!("{}", exercise.hint); println!("{}", exercise.hint);
} }
Subcommands::Verify => { Subcommands::Verify => match verify(&exercises, (0, exercises.len()), verbose, false)? {
verify(&exercises, (0, exercises.len()), verbose, false).unwrap_or_else(|_| exit(1)); VerifyState::AllExercisesDone => println!("All exercises done!"),
} VerifyState::Failed(exercise) => bail!("Exercise {exercise} failed"),
},
Subcommands::Watch { success_hints } => match watch(&exercises, verbose, success_hints) { Subcommands::Watch { success_hints } => match watch(&exercises, verbose, success_hints) {
Err(e) => { Err(e) => {
@ -317,11 +319,7 @@ enum WatchStatus {
Unfinished, Unfinished,
} }
fn watch( fn watch(exercises: &[Exercise], verbose: bool, success_hints: bool) -> Result<WatchStatus> {
exercises: &[Exercise],
verbose: bool,
success_hints: bool,
) -> notify::Result<WatchStatus> {
/* Clears the terminal with an ANSI escape code. /* Clears the terminal with an ANSI escape code.
Works in UNIX and newer Windows terminals. */ Works in UNIX and newer Windows terminals. */
fn clear_screen() { fn clear_screen() {
@ -338,11 +336,11 @@ fn watch(
clear_screen(); clear_screen();
let failed_exercise_hint = match verify(exercises, (0, exercises.len()), verbose, success_hints) let failed_exercise_hint =
{ match verify(exercises, (0, exercises.len()), verbose, success_hints)? {
Ok(_) => return Ok(WatchStatus::Finished), VerifyState::AllExercisesDone => return Ok(WatchStatus::Finished),
Err(exercise) => Arc::new(Mutex::new(Some(exercise.hint.clone()))), VerifyState::Failed(exercise) => Arc::new(Mutex::new(Some(exercise.hint.clone()))),
}; };
spawn_watch_shell(Arc::clone(&failed_exercise_hint), Arc::clone(&should_quit)); spawn_watch_shell(Arc::clone(&failed_exercise_hint), Arc::clone(&should_quit));
@ -368,9 +366,9 @@ fn watch(
(num_done, exercises.len()), (num_done, exercises.len()),
verbose, verbose,
success_hints, success_hints,
) { )? {
Ok(_) => return Ok(WatchStatus::Finished), VerifyState::AllExercisesDone => return Ok(WatchStatus::Finished),
Err(exercise) => { VerifyState::Failed(exercise) => {
let hint = exercise.hint.clone(); let hint = exercise.hint.clone();
*failed_exercise_hint.lock().unwrap() = Some(hint); *failed_exercise_hint.lock().unwrap() = Some(hint);
} }

View file

@ -10,6 +10,11 @@ use std::{
use crate::exercise::{Exercise, Mode, State}; use crate::exercise::{Exercise, Mode, State};
pub enum VerifyState<'a> {
AllExercisesDone,
Failed(&'a Exercise),
}
// Verify that the provided container of Exercise objects // Verify that the provided container of Exercise objects
// can be compiled and run without any failures. // can be compiled and run without any failures.
// Any such failures will be reported to the end user. // Any such failures will be reported to the end user.
@ -20,7 +25,7 @@ pub fn verify<'a>(
progress: (usize, usize), progress: (usize, usize),
verbose: bool, verbose: bool,
success_hints: bool, success_hints: bool,
) -> Result<(), &'a Exercise> { ) -> Result<VerifyState<'a>> {
let (num_done, total) = progress; let (num_done, total) = progress;
let bar = ProgressBar::new(total as u64); let bar = ProgressBar::new(total as u64);
let mut percentage = num_done as f32 / total as f32 * 100.0; let mut percentage = num_done as f32 / total as f32 * 100.0;
@ -35,12 +40,12 @@ pub fn verify<'a>(
for exercise in pending_exercises { for exercise in pending_exercises {
let compile_result = match exercise.mode { let compile_result = match exercise.mode {
Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose, success_hints), Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose, success_hints)?,
Mode::Compile => compile_and_run_interactively(exercise, success_hints), Mode::Compile => compile_and_run_interactively(exercise, success_hints)?,
Mode::Clippy => compile_only(exercise, success_hints), Mode::Clippy => compile_only(exercise, success_hints)?,
}; };
if !compile_result.unwrap_or(false) { if !compile_result {
return Err(exercise); return Ok(VerifyState::Failed(exercise));
} }
percentage += 100.0 / total as f32; percentage += 100.0 / total as f32;
bar.inc(1); bar.inc(1);
@ -50,7 +55,7 @@ pub fn verify<'a>(
bar.finish(); bar.finish();
println!("You completed all exercises!"); println!("You completed all exercises!");
Ok(()) Ok(VerifyState::AllExercisesDone)
} }
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]