From 3b6d5c3aaa27a242a832799eb66e96897d26fde3 Mon Sep 17 00:00:00 2001 From: Roberto Vidal Date: Wed, 26 Feb 2020 20:38:44 +0100 Subject: [PATCH] feature: makes "compile" exercise print output, resolves #270 When running "compile"-mode exercises in interactive `verify` mode, we print their output when we prompt the learner if they want to continue. This improves the "experimentation" experience, since trying different things does produce a visible change. --- exercises/primitive_types/primitive_types4.rs | 3 - src/verify.rs | 98 +++++++++++++------ tests/integration_tests.rs | 2 +- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs index 10b553e..d0c2336 100644 --- a/exercises/primitive_types/primitive_types4.rs +++ b/exercises/primitive_types/primitive_types4.rs @@ -8,7 +8,4 @@ fn slice_out_of_array() { let a = [1, 2, 3, 4, 5]; - let nice_slice = ??? - - assert_eq!([2, 3, 4], nice_slice) } diff --git a/src/verify.rs b/src/verify.rs index 229aa6d..c9a7b6b 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,4 +1,4 @@ -use crate::exercise::{Exercise, Mode, State}; +use crate::exercise::{CompiledExercise, Exercise, Mode, State}; use console::style; use indicatif::ProgressBar; @@ -6,7 +6,7 @@ pub fn verify<'a>(start_at: impl IntoIterator) -> Result<() for exercise in start_at { let compile_result = match exercise.mode { Mode::Test => compile_and_test(&exercise, RunMode::Interactive), - Mode::Compile => compile_only(&exercise), + Mode::Compile => compile_and_run_interactively(&exercise), Mode::Clippy => compile_only(&exercise), }; if !compile_result.unwrap_or(false) { @@ -30,23 +30,37 @@ fn compile_only(exercise: &Exercise) -> Result { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Compiling {}...", exercise).as_str()); progress_bar.enable_steady_tick(100); - let compilation_result = exercise.compile(); + + let _ = compile(&exercise, &progress_bar)?; progress_bar.finish_and_clear(); - match compilation_result { - Ok(_) => { - success!("Successfully compiled {}!", exercise); - Ok(prompt_for_completion(&exercise)) - } + success!("Successfully compiled {}!", exercise); + Ok(prompt_for_completion(&exercise, None)) +} + +fn compile_and_run_interactively(exercise: &Exercise) -> Result { + let progress_bar = ProgressBar::new_spinner(); + progress_bar.set_message(format!("Compiling {}...", exercise).as_str()); + progress_bar.enable_steady_tick(100); + + let compilation = compile(&exercise, &progress_bar)?; + + progress_bar.set_message(format!("Running {}...", exercise).as_str()); + let result = compilation.run(); + progress_bar.finish_and_clear(); + + let output = match result { + Ok(output) => output, Err(output) => { - warn!( - "Compilation of {} failed! Compiler error message:\n", - exercise - ); - println!("{}", output.stderr); - Err(()) + warn!("Ran {} with errors", exercise); + println!("{}", output.stdout); + return Err(()); } - } + }; + + success!("Successfully ran {}!", exercise); + + Ok(prompt_for_completion(&exercise, Some(output.stdout))) } fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result { @@ -54,28 +68,15 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result progress_bar.set_message(format!("Testing {}...", exercise).as_str()); progress_bar.enable_steady_tick(100); - let compilation_result = exercise.compile(); - - let compilation = match compilation_result { - Ok(compilation) => compilation, - Err(output) => { - progress_bar.finish_and_clear(); - warn!( - "Compiling of {} failed! Please try again. Here's the output:", - exercise - ); - println!("{}", output.stderr); - return Err(()); - } - }; - + let compilation = compile(exercise, &progress_bar)?; let result = compilation.run(); progress_bar.finish_and_clear(); match result { Ok(_) => { + success!("Successfully tested {}", &exercise); if let RunMode::Interactive = run_mode { - Ok(prompt_for_completion(&exercise)) + Ok(prompt_for_completion(&exercise, None)) } else { Ok(true) } @@ -91,7 +92,27 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result } } -fn prompt_for_completion(exercise: &Exercise) -> bool { +fn compile<'a, 'b>( + exercise: &'a Exercise, + progress_bar: &'b ProgressBar, +) -> Result, ()> { + let compilation_result = exercise.compile(); + + match compilation_result { + Ok(compilation) => Ok(compilation), + Err(output) => { + progress_bar.finish_and_clear(); + warn!( + "Compiling of {} failed! Please try again. Here's the output:", + exercise + ); + println!("{}", output.stderr); + Err(()) + } + } +} + +fn prompt_for_completion(exercise: &Exercise, prompt_output: Option) -> bool { let context = match exercise.state() { State::Done => return true, State::Pending(context) => context, @@ -106,6 +127,15 @@ fn prompt_for_completion(exercise: &Exercise) -> bool { println!(""); println!("🎉 🎉 {} 🎉 🎉", success_msg); println!(""); + + if let Some(output) = prompt_output { + println!("Output:"); + println!("{}", separator()); + println!("{}", output); + println!("{}", separator()); + println!(""); + } + println!("You can keep working on this exercise,"); println!( "or jump into the next one by removing the {} comment:", @@ -129,3 +159,7 @@ fn prompt_for_completion(exercise: &Exercise) -> bool { false } + +fn separator() -> console::StyledObject<&'static str> { + style("====================").bold() +} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 7131700..683e564 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -31,7 +31,7 @@ fn verify_all_success() { } #[test] -fn verify_all_failure() { +fn verify_fails_if_some_fails() { Command::cargo_bin("rustlings") .unwrap() .arg("v")