Skip to content

Commit b076801

Browse files
authored
Merge pull request #1504 from rb5014/success-hints-feature
feat(main, verify): Show hint(s) after exercise completion
2 parents d45ec21 + c44e302 commit b076801

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

src/main.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ struct VerifyArgs {}
6161
#[derive(FromArgs, PartialEq, Debug)]
6262
#[argh(subcommand, name = "watch")]
6363
/// Reruns `verify` when files were edited
64-
struct WatchArgs {}
64+
struct WatchArgs {
65+
/// show hints on success
66+
#[argh(switch)]
67+
success_hints: bool,
68+
}
6569

6670
#[derive(FromArgs, PartialEq, Debug)]
6771
#[argh(subcommand, name = "run")]
@@ -229,7 +233,7 @@ fn main() {
229233
}
230234

231235
Subcommands::Verify(_subargs) => {
232-
verify(&exercises, (0, exercises.len()), verbose)
236+
verify(&exercises, (0, exercises.len()), verbose, false)
233237
.unwrap_or_else(|_| std::process::exit(1));
234238
}
235239

@@ -252,7 +256,7 @@ fn main() {
252256
}
253257
}
254258

255-
Subcommands::Watch(_subargs) => match watch(&exercises, verbose) {
259+
Subcommands::Watch(_subargs) => match watch(&exercises, verbose, _subargs.success_hints) {
256260
Err(e) => {
257261
println!(
258262
"Error: Could not watch your progress. Error message was {:?}.",
@@ -348,7 +352,7 @@ enum WatchStatus {
348352
Unfinished,
349353
}
350354

351-
fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result<WatchStatus> {
355+
fn watch(exercises: &[Exercise], verbose: bool, success_hints: bool) -> notify::Result<WatchStatus> {
352356
/* Clears the terminal with an ANSI escape code.
353357
Works in UNIX and newer Windows terminals. */
354358
fn clear_screen() {
@@ -364,7 +368,7 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result<WatchStatus> {
364368
clear_screen();
365369

366370
let to_owned_hint = |t: &Exercise| t.hint.to_owned();
367-
let failed_exercise_hint = match verify(exercises.iter(), (0, exercises.len()), verbose) {
371+
let failed_exercise_hint = match verify(exercises.iter(), (0, exercises.len()), verbose, success_hints) {
368372
Ok(_) => return Ok(WatchStatus::Finished),
369373
Err(exercise) => Arc::new(Mutex::new(Some(to_owned_hint(exercise)))),
370374
};
@@ -386,7 +390,7 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result<WatchStatus> {
386390
);
387391
let num_done = exercises.iter().filter(|e| e.looks_done()).count();
388392
clear_screen();
389-
match verify(pending_exercises, (num_done, exercises.len()), verbose) {
393+
match verify(pending_exercises, (num_done, exercises.len()), verbose, success_hints) {
390394
Ok(_) => return Ok(WatchStatus::Finished),
391395
Err(exercise) => {
392396
let mut failed_exercise_hint = failed_exercise_hint.lock().unwrap();

src/verify.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub fn verify<'a>(
1212
exercises: impl IntoIterator<Item = &'a Exercise>,
1313
progress: (usize, usize),
1414
verbose: bool,
15+
success_hints: bool,
1516
) -> Result<(), &'a Exercise> {
1617
let (num_done, total) = progress;
1718
let bar = ProgressBar::new(total as u64);
@@ -25,9 +26,9 @@ pub fn verify<'a>(
2526

2627
for exercise in exercises {
2728
let compile_result = match exercise.mode {
28-
Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose),
29-
Mode::Compile => compile_and_run_interactively(exercise),
30-
Mode::Clippy => compile_only(exercise),
29+
Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose, success_hints),
30+
Mode::Compile => compile_and_run_interactively(exercise, success_hints),
31+
Mode::Clippy => compile_only(exercise, success_hints),
3132
};
3233
if !compile_result.unwrap_or(false) {
3334
return Err(exercise);
@@ -46,24 +47,24 @@ enum RunMode {
4647

4748
// Compile and run the resulting test harness of the given Exercise
4849
pub fn test(exercise: &Exercise, verbose: bool) -> Result<(), ()> {
49-
compile_and_test(exercise, RunMode::NonInteractive, verbose)?;
50+
compile_and_test(exercise, RunMode::NonInteractive, verbose, false)?;
5051
Ok(())
5152
}
5253

5354
// Invoke the rust compiler without running the resulting binary
54-
fn compile_only(exercise: &Exercise) -> Result<bool, ()> {
55+
fn compile_only(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> {
5556
let progress_bar = ProgressBar::new_spinner();
5657
progress_bar.set_message(format!("Compiling {exercise}..."));
5758
progress_bar.enable_steady_tick(100);
5859

5960
let _ = compile(exercise, &progress_bar)?;
6061
progress_bar.finish_and_clear();
6162

62-
Ok(prompt_for_completion(exercise, None))
63+
Ok(prompt_for_completion(exercise, None, success_hints))
6364
}
6465

6566
// Compile the given Exercise and run the resulting binary in an interactive mode
66-
fn compile_and_run_interactively(exercise: &Exercise) -> Result<bool, ()> {
67+
fn compile_and_run_interactively(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> {
6768
let progress_bar = ProgressBar::new_spinner();
6869
progress_bar.set_message(format!("Compiling {exercise}..."));
6970
progress_bar.enable_steady_tick(100);
@@ -84,12 +85,12 @@ fn compile_and_run_interactively(exercise: &Exercise) -> Result<bool, ()> {
8485
}
8586
};
8687

87-
Ok(prompt_for_completion(exercise, Some(output.stdout)))
88+
Ok(prompt_for_completion(exercise, Some(output.stdout), success_hints))
8889
}
8990

9091
// Compile the given Exercise as a test harness and display
9192
// the output if verbose is set to true
92-
fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool) -> Result<bool, ()> {
93+
fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool, success_hints: bool) -> Result<bool, ()> {
9394
let progress_bar = ProgressBar::new_spinner();
9495
progress_bar.set_message(format!("Testing {exercise}..."));
9596
progress_bar.enable_steady_tick(100);
@@ -104,7 +105,7 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool) -> Re
104105
println!("{}", output.stdout);
105106
}
106107
if let RunMode::Interactive = run_mode {
107-
Ok(prompt_for_completion(exercise, None))
108+
Ok(prompt_for_completion(exercise, None, success_hints))
108109
} else {
109110
Ok(true)
110111
}
@@ -142,12 +143,11 @@ fn compile<'a, 'b>(
142143
}
143144
}
144145

145-
fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) -> bool {
146+
fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>, success_hints: bool) -> bool {
146147
let context = match exercise.state() {
147148
State::Done => return true,
148149
State::Pending(context) => context,
149150
};
150-
151151
match exercise.mode {
152152
Mode::Compile => success!("Successfully ran {}!", exercise),
153153
Mode::Test => success!("Successfully tested {}!", exercise),
@@ -167,7 +167,6 @@ fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) ->
167167
Mode::Test => "The code is compiling, and the tests pass!",
168168
Mode::Clippy => clippy_success_msg,
169169
};
170-
171170
println!();
172171
if no_emoji {
173172
println!("~*~ {success_msg} ~*~")
@@ -183,6 +182,13 @@ fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) ->
183182
println!("{}", separator());
184183
println!();
185184
}
185+
if success_hints {
186+
println!("Hints:");
187+
println!("{}", separator());
188+
println!("{}", exercise.hint);
189+
println!("{}", separator());
190+
println!();
191+
}
186192

187193
println!("You can keep working on this exercise,");
188194
println!(

0 commit comments

Comments
 (0)