diff options
Diffstat (limited to 'src/run.rs')
| -rw-r--r-- | src/run.rs | 113 |
1 files changed, 45 insertions, 68 deletions
@@ -1,74 +1,51 @@ -use std::process::Command; -use std::time::Duration; - -use crate::exercise::{Exercise, Mode}; -use crate::verify::test; -use indicatif::ProgressBar; - -// Invoke the rust compiler on the path of the given exercise, -// and run the ensuing binary. -// The verbose argument helps determine whether or not to show -// the output from the test harnesses (if the mode of the exercise is test) -pub fn run(exercise: &Exercise, verbose: bool) -> Result<(), ()> { - match exercise.mode { - Mode::Test => test(exercise, verbose)?, - Mode::Compile => compile_and_run(exercise)?, - Mode::Clippy => compile_and_run(exercise)?, +use anyhow::{bail, Result}; +use crossterm::style::{style, Stylize}; +use std::io::{self, Write}; + +use crate::{ + app_state::{AppState, ExercisesProgress}, + exercise::{RunnableExercise, OUTPUT_CAPACITY}, + terminal_link::TerminalFileLink, +}; + +pub fn run(app_state: &mut AppState) -> Result<()> { + let exercise = app_state.current_exercise(); + let mut output = Vec::with_capacity(OUTPUT_CAPACITY); + let success = exercise.run_exercise(&mut output, app_state.target_dir())?; + + let mut stdout = io::stdout().lock(); + stdout.write_all(&output)?; + + if !success { + app_state.set_pending(app_state.current_exercise_ind())?; + + bail!( + "Ran {} with errors", + app_state.current_exercise().terminal_link(), + ); } - Ok(()) -} - -// Resets the exercise by stashing the changes. -pub fn reset(exercise: &Exercise) -> Result<(), ()> { - let command = Command::new("git") - .args(["stash", "--"]) - .arg(&exercise.path) - .spawn(); - match command { - Ok(_) => Ok(()), - Err(_) => Err(()), + writeln!( + stdout, + "{}{}", + "✓ Successfully ran ".green(), + exercise.path.green(), + )?; + + if let Some(solution_path) = app_state.current_solution_path()? { + println!( + "\nA solution file can be found at {}\n", + style(TerminalFileLink(&solution_path)).underlined().green(), + ); } -} -// Invoke the rust compiler on the path of the given exercise -// and run the ensuing binary. -// This is strictly for non-test binaries, so output is displayed -fn compile_and_run(exercise: &Exercise) -> Result<(), ()> { - let progress_bar = ProgressBar::new_spinner(); - progress_bar.set_message(format!("Compiling {exercise}...")); - progress_bar.enable_steady_tick(Duration::from_millis(100)); - - let compilation_result = exercise.compile(); - let compilation = match compilation_result { - Ok(compilation) => compilation, - Err(output) => { - progress_bar.finish_and_clear(); - warn!( - "Compilation of {} failed!, Compiler error message:\n", - exercise - ); - println!("{}", output.stderr); - return Err(()); - } - }; - - progress_bar.set_message(format!("Running {exercise}...")); - let result = compilation.run(); - progress_bar.finish_and_clear(); - - match result { - Ok(output) => { - println!("{}", output.stdout); - success!("Successfully ran {}", exercise); - Ok(()) - } - Err(output) => { - println!("{}", output.stdout); - println!("{}", output.stderr); - - warn!("Ran {} with errors", exercise); - Err(()) - } + match app_state.done_current_exercise(&mut stdout)? { + ExercisesProgress::AllDone => (), + ExercisesProgress::CurrentPending | ExercisesProgress::NewPending => println!( + "Next exercise: {}", + app_state.current_exercise().terminal_link(), + ), } + + Ok(()) } |
