summaryrefslogtreecommitdiff
path: root/src/run.rs
blob: 09e53ec9e11018c546c3daed04824335f50e7fe9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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(Some(&mut output), app_state.cmd_runner())?;

    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(),
        );
    }

    writeln!(
        stdout,
        "{}{}",
        "✓ Successfully ran ".green(),
        exercise.path.green(),
    )?;

    if let Some(solution_path) = app_state.current_solution_path()? {
        writeln!(
            stdout,
            "\n{} for comparison: {}\n",
            "Solution".bold(),
            style(TerminalFileLink(&solution_path)).underlined().cyan(),
        )?;
    }

    match app_state.done_current_exercise(&mut stdout)? {
        ExercisesProgress::AllDone => (),
        ExercisesProgress::CurrentPending | ExercisesProgress::NewPending => writeln!(
            stdout,
            "Next exercise: {}",
            app_state.current_exercise().terminal_link(),
        )?,
    }

    Ok(())
}