rustlings/src/verify.rs

88 lines
2.7 KiB
Rust
Raw Normal View History

2024-04-04 15:06:11 -04:00
use anyhow::Result;
2024-04-04 21:04:53 -04:00
use crossterm::style::{Attribute, ContentStyle, Stylize};
2024-04-04 15:06:11 -04:00
use std::io::{stdout, Write};
2024-03-31 10:55:33 -04:00
use crate::exercise::{Exercise, Mode, State};
2019-01-09 14:33:43 -05:00
2024-04-01 12:38:01 -04:00
pub enum VerifyState<'a> {
AllExercisesDone,
Failed(&'a Exercise),
}
// Verify that the provided container of Exercise objects
// can be compiled and run without any failures.
// Any such failures will be reported to the end user.
// If the Exercise being verified is a test, the verbose boolean
// determines whether or not the test harness outputs are displayed.
pub fn verify<'a>(
2024-04-01 12:21:56 -04:00
pending_exercises: impl IntoIterator<Item = &'a Exercise>,
progress: (usize, usize),
2024-04-01 12:38:01 -04:00
) -> Result<VerifyState<'a>> {
2024-04-04 15:06:11 -04:00
let (mut num_done, total) = progress;
println!(
"Progress: {num_done}/{total} ({:.1}%)\n",
num_done as f32 / total as f32 * 100.0,
);
2024-04-01 12:21:56 -04:00
for exercise in pending_exercises {
2024-04-04 15:06:11 -04:00
let output = exercise.run()?;
2019-01-09 14:33:43 -05:00
2024-03-31 10:55:33 -04:00
{
let mut stdout = stdout().lock();
stdout.write_all(&output.stdout)?;
stdout.write_all(&output.stderr)?;
stdout.flush()?;
}
2024-04-04 15:06:11 -04:00
if !output.status.success() {
return Ok(VerifyState::Failed(exercise));
}
2024-04-04 15:06:11 -04:00
println!();
2024-04-04 18:49:22 -04:00
// TODO: Color
2024-04-04 15:06:11 -04:00
match exercise.mode {
2024-04-04 18:49:22 -04:00
Mode::Compile => println!("Successfully ran {exercise}!"),
Mode::Test => println!("Successfully tested {exercise}!"),
Mode::Clippy => println!("Successfully checked {exercise}!"),
2024-04-04 15:06:11 -04:00
}
2024-04-04 15:06:11 -04:00
if let State::Pending(context) = exercise.state()? {
println!(
"\nYou can keep working on this exercise,
or jump into the next one by removing the {} comment:\n",
2024-04-04 21:04:53 -04:00
"`I AM NOT DONE`".bold()
2024-04-04 15:06:11 -04:00
);
for context_line in context {
let formatted_line = if context_line.important {
2024-04-04 21:04:53 -04:00
format!("{}", context_line.line.bold())
2024-04-04 15:06:11 -04:00
} else {
context_line.line
};
println!(
"{:>2} {} {}",
2024-04-04 21:04:53 -04:00
ContentStyle {
foreground_color: Some(crossterm::style::Color::Blue),
background_color: None,
underline_color: None,
attributes: Attribute::Bold.into()
}
.apply(context_line.number),
"|".blue(),
2024-04-04 15:06:11 -04:00
formatted_line,
);
}
return Ok(VerifyState::Failed(exercise));
}
2024-04-04 15:06:11 -04:00
num_done += 1;
println!(
2024-04-04 15:06:11 -04:00
"Progress: {num_done}/{total} ({:.1}%)\n",
num_done as f32 / total as f32 * 100.0,
);
}
2024-04-04 15:06:11 -04:00
Ok(VerifyState::AllExercisesDone)
}