Skip to content

Commit bc32a63

Browse files
committed
Auto merge of #234 - jrvidal:no-prompt-on-run, r=fmoko
fix(run): makes `run` never prompt `watch` and `verify` do prompt the user to actively move to the next exercise. This change fixes `run` to never prompt. Previously it was inconsistent between "test" and "compile" exercises. BREAKING CHANGE: we again change the behavior of the `run` command
2 parents bc56788 + 4b26546 commit bc32a63

File tree

8 files changed

+96
-20
lines changed

8 files changed

+96
-20
lines changed

Cargo.lock

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ path = "src/main.rs"
1919

2020
[dev-dependencies]
2121
assert_cmd = "0.11.0"
22+
predicates = "1.0.1"
2223
glob = "0.3.0"

src/run.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ use indicatif::ProgressBar;
55

66
pub fn run(exercise: &Exercise) -> Result<(), ()> {
77
match exercise.mode {
8-
Mode::Test => {
9-
test(exercise)?;
10-
}
8+
Mode::Test => test(exercise)?,
119
Mode::Compile => compile_and_run(exercise)?,
1210
}
1311
Ok(())

src/verify.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::exercise::{ContextLine, Exercise, Mode, State};
1+
use crate::exercise::{Exercise, Mode, State};
22
use console::{style, Emoji};
33
use indicatif::ProgressBar;
44

55
pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<(), ()> {
66
for exercise in start_at {
77
let is_done = match exercise.mode {
8-
Mode::Test => test(&exercise)?,
8+
Mode::Test => compile_and_test_interactively(&exercise)?,
99
Mode::Compile => compile_only(&exercise)?,
1010
};
1111
if !is_done {
@@ -15,6 +15,11 @@ pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<()
1515
Ok(())
1616
}
1717

18+
pub fn test(exercise: &Exercise) -> Result<(), ()> {
19+
compile_and_test(exercise, true)?;
20+
Ok(())
21+
}
22+
1823
fn compile_only(exercise: &Exercise) -> Result<bool, ()> {
1924
let progress_bar = ProgressBar::new_spinner();
2025
progress_bar.set_message(format!("Compiling {}...", exercise).as_str());
@@ -25,12 +30,7 @@ fn compile_only(exercise: &Exercise) -> Result<bool, ()> {
2530
let formatstr = format!("{} Successfully compiled {}!", Emoji("✅", "✓"), exercise);
2631
println!("{}", style(formatstr).green());
2732
exercise.clean();
28-
if let State::Pending(context) = exercise.state() {
29-
print_everything_looks_good(exercise.mode, context);
30-
Ok(false)
31-
} else {
32-
Ok(true)
33-
}
33+
Ok(prompt_for_completion(&exercise))
3434
} else {
3535
let formatstr = format!(
3636
"{} Compilation of {} failed! Compiler error message:\n",
@@ -44,7 +44,11 @@ fn compile_only(exercise: &Exercise) -> Result<bool, ()> {
4444
}
4545
}
4646

47-
pub fn test(exercise: &Exercise) -> Result<bool, ()> {
47+
fn compile_and_test_interactively(exercise: &Exercise) -> Result<bool, ()> {
48+
compile_and_test(exercise, false)
49+
}
50+
51+
fn compile_and_test(exercise: &Exercise, skip_prompt: bool) -> Result<bool, ()> {
4852
let progress_bar = ProgressBar::new_spinner();
4953
progress_bar.set_message(format!("Testing {}...", exercise).as_str());
5054
progress_bar.enable_steady_tick(100);
@@ -60,12 +64,7 @@ pub fn test(exercise: &Exercise) -> Result<bool, ()> {
6064
let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), exercise);
6165
println!("{}", style(formatstr).green());
6266
exercise.clean();
63-
if let State::Pending(context) = exercise.state() {
64-
print_everything_looks_good(exercise.mode, context);
65-
Ok(false)
66-
} else {
67-
Ok(true)
68-
}
67+
Ok(skip_prompt || prompt_for_completion(exercise))
6968
} else {
7069
let formatstr = format!(
7170
"{} Testing of {} failed! Please try again. Here's the output:",
@@ -91,8 +90,13 @@ pub fn test(exercise: &Exercise) -> Result<bool, ()> {
9190
}
9291
}
9392

94-
fn print_everything_looks_good(mode: Mode, context: Vec<ContextLine>) {
95-
let success_msg = match mode {
93+
fn prompt_for_completion(exercise: &Exercise) -> bool {
94+
let context = match exercise.state() {
95+
State::Done => return true,
96+
State::Pending(context) => context,
97+
};
98+
99+
let success_msg = match exercise.mode {
96100
Mode::Compile => "The code is compiling!",
97101
Mode::Test => "The code is compiling, and the tests pass!",
98102
};
@@ -120,4 +124,6 @@ fn print_everything_looks_good(mode: Mode, context: Vec<ContextLine>) {
120124
formatted_line
121125
);
122126
}
127+
128+
false
123129
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// fake_exercise
2+
3+
fn main() {
4+
5+
}

tests/fixture/state/info.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[[exercises]]
2+
name = "pending_exercise"
3+
path = "pending_exercise.rs"
4+
mode = "compile"
5+
hint = """"""
6+
7+
[[exercises]]
8+
name = "pending_test_exercise"
9+
path = "pending_test_exercise.rs"
10+
mode = "test"
11+
hint = """"""
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// I AM NOT DONE
2+
3+
#[test]
4+
fn it_works() {}

tests/integration_tests.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use assert_cmd::prelude::*;
22
use glob::glob;
3+
use predicates::boolean::PredicateBooleanExt;
34
use std::fs::File;
45
use std::io::Read;
56
use std::process::Command;
@@ -136,3 +137,25 @@ fn all_exercises_require_confirmation() {
136137
));
137138
}
138139
}
140+
141+
#[test]
142+
fn run_compile_exercise_does_not_prompt() {
143+
Command::cargo_bin("rustlings")
144+
.unwrap()
145+
.args(&["r", "pending_exercise"])
146+
.current_dir("tests/fixture/state")
147+
.assert()
148+
.code(0)
149+
.stdout(predicates::str::contains("I AM NOT DONE").not());
150+
}
151+
152+
#[test]
153+
fn run_test_exercise_does_not_prompt() {
154+
Command::cargo_bin("rustlings")
155+
.unwrap()
156+
.args(&["r", "pending_test_exercise"])
157+
.current_dir("tests/fixture/state")
158+
.assert()
159+
.code(0)
160+
.stdout(predicates::str::contains("I AM NOT DONE").not());
161+
}

0 commit comments

Comments
 (0)