mirror of
https://github.com/notohh/rustlings.git
synced 2024-11-25 14:57:32 -05:00
Add VerifyState
This commit is contained in:
parent
fdd7de00bd
commit
def8d2c569
2 changed files with 28 additions and 25 deletions
34
src/main.rs
34
src/main.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
Loading…
Reference in a new issue