Skip to content

Commit 6f44cb1

Browse files
committed
feat: Add reset command, given a filename
1 parent d0c7b06 commit 6f44cb1

File tree

2 files changed

+74
-19
lines changed

2 files changed

+74
-19
lines changed

src/main.rs

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
use crate::exercise::{Exercise, ExerciseList};
21
use crate::project::RustAnalyzerProject;
32
use crate::run::run;
43
use crate::verify::verify;
4+
use crate::{
5+
exercise::{Exercise, ExerciseList},
6+
run::reset,
7+
};
58
use argh::FromArgs;
69
use console::Emoji;
710
use notify::DebouncedEvent;
@@ -47,6 +50,7 @@ enum Subcommands {
4750
Verify(VerifyArgs),
4851
Watch(WatchArgs),
4952
Run(RunArgs),
53+
Reset(ResetArgs),
5054
Hint(HintArgs),
5155
List(ListArgs),
5256
Lsp(LspArgs),
@@ -71,6 +75,15 @@ struct RunArgs {
7175
name: String,
7276
}
7377

78+
#[derive(FromArgs, PartialEq, Debug)]
79+
#[argh(subcommand, name = "reset")]
80+
/// Resets a single exercise
81+
struct ResetArgs {
82+
#[argh(positional)]
83+
/// the name of the exercise
84+
name: String,
85+
}
86+
7487
#[derive(FromArgs, PartialEq, Debug)]
7588
#[argh(subcommand, name = "hint")]
7689
/// Returns a hint for the given exercise
@@ -85,7 +98,6 @@ struct HintArgs {
8598
/// Enable rust-analyzer for exercises
8699
struct LspArgs {}
87100

88-
89101
#[derive(FromArgs, PartialEq, Debug)]
90102
#[argh(subcommand, name = "list")]
91103
/// Lists the exercises available in Rustlings
@@ -164,7 +176,9 @@ fn main() {
164176
"Pending"
165177
};
166178
let solve_cond = {
167-
(e.looks_done() && subargs.solved) || (!e.looks_done() && subargs.unsolved) || (!subargs.solved && !subargs.unsolved)
179+
(e.looks_done() && subargs.solved)
180+
|| (!e.looks_done() && subargs.unsolved)
181+
|| (!subargs.solved && !subargs.unsolved)
168182
};
169183
if solve_cond && (filter_cond || subargs.filter.is_none()) {
170184
let line = if subargs.paths {
@@ -205,14 +219,21 @@ fn main() {
205219
run(exercise, verbose).unwrap_or_else(|_| std::process::exit(1));
206220
}
207221

222+
Subcommands::Reset(subargs) => {
223+
let exercise = find_exercise(&subargs.name, &exercises);
224+
225+
reset(exercise).unwrap_or_else(|_| std::process::exit(1));
226+
}
227+
208228
Subcommands::Hint(subargs) => {
209229
let exercise = find_exercise(&subargs.name, &exercises);
210230

211231
println!("{}", exercise.hint);
212232
}
213233

214234
Subcommands::Verify(_subargs) => {
215-
verify(&exercises, (0, exercises.len()), verbose).unwrap_or_else(|_| std::process::exit(1));
235+
verify(&exercises, (0, exercises.len()), verbose)
236+
.unwrap_or_else(|_| std::process::exit(1));
216237
}
217238

218239
Subcommands::Lsp(_subargs) => {
@@ -236,12 +257,18 @@ fn main() {
236257

237258
Subcommands::Watch(_subargs) => match watch(&exercises, verbose) {
238259
Err(e) => {
239-
println!("Error: Could not watch your progress. Error message was {:?}.", e);
260+
println!(
261+
"Error: Could not watch your progress. Error message was {:?}.",
262+
e
263+
);
240264
println!("Most likely you've run out of disk space or your 'inotify limit' has been reached.");
241265
std::process::exit(1);
242266
}
243267
Ok(WatchStatus::Finished) => {
244-
println!("{emoji} All exercises completed! {emoji}", emoji = Emoji("🎉", "★"));
268+
println!(
269+
"{emoji} All exercises completed! {emoji}",
270+
emoji = Emoji("🎉", "★")
271+
);
245272
println!("\n{}\n", FENISH_LINE);
246273
}
247274
Ok(WatchStatus::Unfinished) => {
@@ -252,8 +279,10 @@ fn main() {
252279
}
253280
}
254281

255-
256-
fn spawn_watch_shell(failed_exercise_hint: &Arc<Mutex<Option<String>>>, should_quit: Arc<AtomicBool>) {
282+
fn spawn_watch_shell(
283+
failed_exercise_hint: &Arc<Mutex<Option<String>>>,
284+
should_quit: Arc<AtomicBool>,
285+
) {
257286
let failed_exercise_hint = Arc::clone(failed_exercise_hint);
258287
println!("Welcome to watch mode! You can type 'help' to get an overview of the commands you can use here.");
259288
thread::spawn(move || loop {
@@ -290,16 +319,22 @@ fn spawn_watch_shell(failed_exercise_hint: &Arc<Mutex<Option<String>>>, should_q
290319

291320
fn find_exercise<'a>(name: &str, exercises: &'a [Exercise]) -> &'a Exercise {
292321
if name.eq("next") {
293-
exercises.iter().find(|e| !e.looks_done()).unwrap_or_else(|| {
294-
println!("🎉 Congratulations! You have done all the exercises!");
295-
println!("🔚 There are no more exercises to do next!");
296-
std::process::exit(1)
297-
})
322+
exercises
323+
.iter()
324+
.find(|e| !e.looks_done())
325+
.unwrap_or_else(|| {
326+
println!("🎉 Congratulations! You have done all the exercises!");
327+
println!("🔚 There are no more exercises to do next!");
328+
std::process::exit(1)
329+
})
298330
} else {
299-
exercises.iter().find(|e| e.name == name).unwrap_or_else(|| {
300-
println!("No exercise found for '{}'!", name);
301-
std::process::exit(1)
302-
})
331+
exercises
332+
.iter()
333+
.find(|e| e.name == name)
334+
.unwrap_or_else(|| {
335+
println!("No exercise found for '{}'!", name);
336+
std::process::exit(1)
337+
})
303338
}
304339
}
305340

@@ -337,8 +372,13 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result<WatchStatus> {
337372
let filepath = b.as_path().canonicalize().unwrap();
338373
let pending_exercises = exercises
339374
.iter()
340-
.find(|e| filepath.ends_with(&e.path)).into_iter()
341-
.chain(exercises.iter().filter(|e| !e.looks_done() && !filepath.ends_with(&e.path)));
375+
.find(|e| filepath.ends_with(&e.path))
376+
.into_iter()
377+
.chain(
378+
exercises
379+
.iter()
380+
.filter(|e| !e.looks_done() && !filepath.ends_with(&e.path)),
381+
);
342382
let num_done = exercises.iter().filter(|e| e.looks_done()).count();
343383
clear_screen();
344384
match verify(pending_exercises, (num_done, exercises.len()), verbose) {

src/run.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::process::Command;
2+
13
use crate::exercise::{Exercise, Mode};
24
use crate::verify::test;
35
use indicatif::ProgressBar;
@@ -15,6 +17,19 @@ pub fn run(exercise: &Exercise, verbose: bool) -> Result<(), ()> {
1517
Ok(())
1618
}
1719

20+
// Resets the exercise by stashing the changes.
21+
pub fn reset(exercise: &Exercise) -> Result<(), ()> {
22+
let command = Command::new("git")
23+
.args(["stash", "--"])
24+
.arg(&exercise.path)
25+
.spawn();
26+
27+
match command {
28+
Ok(_) => Ok(()),
29+
Err(_) => Err(()),
30+
}
31+
}
32+
1833
// Invoke the rust compiler on the path of the given exercise
1934
// and run the ensuing binary.
2035
// This is strictly for non-test binaries, so output is displayed

0 commit comments

Comments
 (0)