Skip to content

Commit 326169a

Browse files
committed
Improve check-all command
1 parent 685e069 commit 326169a

File tree

4 files changed

+38
-31
lines changed

4 files changed

+38
-31
lines changed

clippy.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ disallowed-methods = [
1313
# Use `thread::Builder::spawn` instead and handle the error.
1414
"std::thread::spawn",
1515
"std::thread::Scope::spawn",
16+
# Return `ExitCode` instead.
17+
"std::process::exit",
1618
]

src/app_state.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ impl AppState {
211211
self.n_done
212212
}
213213

214+
#[inline]
215+
pub fn n_pending(&self) -> u16 {
216+
self.exercises.len() as u16 - self.n_done
217+
}
218+
214219
#[inline]
215220
pub fn current_exercise(&self) -> &Exercise {
216221
&self.exercises[self.current_exercise_ind]

src/main.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crossterm::{
88
use std::{
99
io::{self, IsTerminal, Write},
1010
path::Path,
11-
process::exit,
11+
process::ExitCode,
1212
};
1313
use term::{clear_terminal, press_enter_prompt};
1414

@@ -51,8 +51,8 @@ enum Subcommands {
5151
/// The name of the exercise
5252
name: Option<String>,
5353
},
54-
/// Run all the exercises, marking them as done or pending accordingly.
55-
RunAll,
54+
/// Check all the exercises, marking them as done or pending accordingly.
55+
CheckAll,
5656
/// Reset a single exercise
5757
Reset {
5858
/// The name of the exercise
@@ -68,22 +68,26 @@ enum Subcommands {
6868
Dev(DevCommands),
6969
}
7070

71-
fn main() -> Result<()> {
71+
fn main() -> Result<ExitCode> {
7272
let args = Args::parse();
7373

7474
if cfg!(not(debug_assertions)) && Path::new("dev/rustlings-repo.txt").exists() {
7575
bail!("{OLD_METHOD_ERR}");
7676
}
7777

78-
match args.command {
79-
Some(Subcommands::Init) => return init::init().context("Initialization failed"),
80-
Some(Subcommands::Dev(dev_command)) => return dev_command.run(),
81-
_ => (),
78+
'priority_cmd: {
79+
match args.command {
80+
Some(Subcommands::Init) => init::init().context("Initialization failed")?,
81+
Some(Subcommands::Dev(dev_command)) => dev_command.run()?,
82+
_ => break 'priority_cmd,
83+
}
84+
85+
return Ok(ExitCode::SUCCESS);
8286
}
8387

8488
if !Path::new("exercises").is_dir() {
8589
println!("{PRE_INIT_MSG}");
86-
exit(1);
90+
return Ok(ExitCode::FAILURE);
8791
}
8892

8993
let info_file = InfoFile::parse()?;
@@ -142,33 +146,29 @@ fn main() -> Result<()> {
142146
if let Some(name) = name {
143147
app_state.set_current_exercise_by_name(&name)?;
144148
}
145-
run::run(&mut app_state)?;
149+
return run::run(&mut app_state);
146150
}
147-
Some(Subcommands::RunAll) => {
151+
Some(Subcommands::CheckAll) => {
148152
let mut stdout = io::stdout().lock();
149-
if let Some(first_fail) = app_state.check_all_exercises(&mut stdout)? {
150-
let pending = app_state
151-
.exercises()
152-
.iter()
153-
.filter(|exercise| !exercise.done)
154-
.count();
153+
if let Some(first_pending_exercise_ind) = app_state.check_all_exercises(&mut stdout)? {
155154
if app_state.current_exercise().done {
156-
app_state.set_current_exercise_ind(first_fail)?;
155+
app_state.set_current_exercise_ind(first_pending_exercise_ind)?;
157156
}
158-
stdout
159-
.queue(SetForegroundColor(Color::Red))?
160-
.queue(Print(format!("{pending}")))?
161-
.queue(ResetColor)?;
157+
158+
let pending = app_state.n_pending();
162159
if pending == 1 {
163-
stdout.queue(Print(" exercise has some errors: "))?;
160+
stdout.queue(Print("One exercise pending: "))?;
164161
} else {
165-
stdout.queue(Print(" exercises have errors, including "))?;
162+
stdout.queue(SetForegroundColor(Color::Red))?;
163+
write!(stdout, "{pending}")?;
164+
stdout.queue(ResetColor)?;
165+
stdout.queue(Print(" exercises are pending. The first: "))?;
166166
}
167167
app_state
168168
.current_exercise()
169169
.terminal_file_link(&mut stdout)?;
170-
stdout.write_all(b".\n")?;
171-
exit(1);
170+
stdout.write_all(b"\n")?;
171+
return Ok(ExitCode::FAILURE);
172172
} else {
173173
app_state.render_final_message(&mut stdout)?;
174174
}
@@ -188,7 +188,7 @@ fn main() -> Result<()> {
188188
Some(Subcommands::Init | Subcommands::Dev(_)) => (),
189189
}
190190

191-
Ok(())
191+
Ok(ExitCode::SUCCESS)
192192
}
193193

194194
const OLD_METHOD_ERR: &str =

src/run.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ use crossterm::{
55
};
66
use std::{
77
io::{self, Write},
8-
process::exit,
8+
process::ExitCode,
99
};
1010

1111
use crate::{
1212
app_state::{AppState, ExercisesProgress},
1313
exercise::{solution_link_line, RunnableExercise, OUTPUT_CAPACITY},
1414
};
1515

16-
pub fn run(app_state: &mut AppState) -> Result<()> {
16+
pub fn run(app_state: &mut AppState) -> Result<ExitCode> {
1717
let exercise = app_state.current_exercise();
1818
let mut output = Vec::with_capacity(OUTPUT_CAPACITY);
1919
let success = exercise.run_exercise(Some(&mut output), app_state.cmd_runner())?;
@@ -29,7 +29,7 @@ pub fn run(app_state: &mut AppState) -> Result<()> {
2929
.current_exercise()
3030
.terminal_file_link(&mut stdout)?;
3131
stdout.write_all(b" with errors\n")?;
32-
exit(1);
32+
return Ok(ExitCode::FAILURE);
3333
}
3434

3535
stdout.queue(SetForegroundColor(Color::Green))?;
@@ -55,5 +55,5 @@ pub fn run(app_state: &mut AppState) -> Result<()> {
5555
ExercisesProgress::AllDone => (),
5656
}
5757

58-
Ok(())
58+
Ok(ExitCode::SUCCESS)
5959
}

0 commit comments

Comments
 (0)