summaryrefslogtreecommitdiff
path: root/src/run.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/run.rs')
-rw-r--r--src/run.rs114
1 files changed, 45 insertions, 69 deletions
diff --git a/src/run.rs b/src/run.rs
index 6dd0388..899d0a9 100644
--- a/src/run.rs
+++ b/src/run.rs
@@ -1,75 +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")
- .arg("stash")
- .arg("--")
- .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(())
}