feat(watch): show hint while watching

This commit is contained in:
vyaslav 2019-11-18 18:11:22 +01:00
parent a40ad092e9
commit 8143d57b4e
2 changed files with 36 additions and 8 deletions

View File

@ -6,9 +6,12 @@ use notify::DebouncedEvent;
use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::io;
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration; use std::time::Duration;
mod exercise; mod exercise;
@ -108,6 +111,26 @@ fn main() {
} }
} }
fn spawn_watch_shell(failed_exercise_hint: &Arc<Mutex<Option<String>>>) {
let failed_exercise_hint = Arc::clone(failed_exercise_hint);
println!("Type 'hint' to get help");
thread::spawn(move || loop {
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(_) => {
if input.trim().eq("hint") {
if let Some(hint) = &*failed_exercise_hint.lock().unwrap() {
println!("{}", hint);
}
} else {
println!("unknown command: {}", input);
}
}
Err(error) => println!("error reading command: {}", error),
}
});
}
fn watch(exercises: &[Exercise]) -> notify::Result<()> { fn watch(exercises: &[Exercise]) -> notify::Result<()> {
/* 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. */
@ -121,8 +144,11 @@ fn watch(exercises: &[Exercise]) -> notify::Result<()> {
watcher.watch(Path::new("./exercises"), RecursiveMode::Recursive)?; watcher.watch(Path::new("./exercises"), RecursiveMode::Recursive)?;
clear_screen(); clear_screen();
let _ignored = verify(exercises.iter()); let verify_result = verify(exercises.iter());
let to_owned_hint = |t: &Exercise| t.hint.to_owned();
let failed_exercise_hint = Arc::new(Mutex::new(verify_result.map_err(to_owned_hint).err()));
spawn_watch_shell(&failed_exercise_hint);
loop { loop {
match rx.recv() { match rx.recv() {
Ok(event) => match event { Ok(event) => match event {
@ -133,7 +159,9 @@ fn watch(exercises: &[Exercise]) -> notify::Result<()> {
.iter() .iter()
.skip_while(|e| !filepath.ends_with(&e.path)); .skip_while(|e| !filepath.ends_with(&e.path));
clear_screen(); clear_screen();
let _ignored = verify(pending_exercises); let verify_result = verify(pending_exercises);
let mut failed_exercise_hint = failed_exercise_hint.lock().unwrap();
*failed_exercise_hint = verify_result.map_err(to_owned_hint).err();
} }
} }
_ => {} _ => {}

View File

@ -2,14 +2,14 @@ use crate::exercise::{Exercise, Mode, State};
use console::{style, Emoji}; use console::{style, Emoji};
use indicatif::ProgressBar; use indicatif::ProgressBar;
pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<(), ()> { pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<(), &'a Exercise> {
for exercise in start_at { for exercise in start_at {
let is_done = match exercise.mode { let compile_result = match exercise.mode {
Mode::Test => compile_and_test_interactively(&exercise)?, Mode::Test => compile_and_test_interactively(&exercise),
Mode::Compile => compile_only(&exercise)?, Mode::Compile => compile_only(&exercise),
}; };
if !is_done { if !compile_result.unwrap_or(false) {
return Err(()); return Err(exercise);
} }
} }
Ok(()) Ok(())