2024-04-06 19:17:53 -04:00
|
|
|
use crate::consts::WELCOME;
|
2024-03-31 14:08:23 -04:00
|
|
|
use crate::embedded::{WriteStrategy, EMBEDDED_FILES};
|
2022-08-18 06:47:26 -04:00
|
|
|
use crate::exercise::{Exercise, ExerciseList};
|
2024-03-31 14:08:23 -04:00
|
|
|
use crate::run::run;
|
2019-01-09 14:33:58 -05:00
|
|
|
use crate::verify::verify;
|
2024-04-01 12:38:01 -04:00
|
|
|
use anyhow::{bail, Context, Result};
|
2023-08-25 17:18:01 -04:00
|
|
|
use clap::{Parser, Subcommand};
|
2024-04-06 19:17:53 -04:00
|
|
|
use state::State;
|
2019-03-16 22:15:09 -04:00
|
|
|
use std::path::Path;
|
2024-04-04 15:06:11 -04:00
|
|
|
use std::process::exit;
|
2024-04-01 12:38:01 -04:00
|
|
|
use verify::VerifyState;
|
2019-01-09 14:33:43 -05:00
|
|
|
|
2024-04-04 21:04:53 -04:00
|
|
|
mod consts;
|
2024-03-28 16:06:36 -04:00
|
|
|
mod embedded;
|
2019-04-11 16:41:24 -04:00
|
|
|
mod exercise;
|
2024-03-28 20:29:41 -04:00
|
|
|
mod init;
|
2024-04-06 21:03:37 -04:00
|
|
|
mod list;
|
2019-01-09 14:33:43 -05:00
|
|
|
mod run;
|
2024-04-04 21:05:07 -04:00
|
|
|
mod state;
|
2019-01-09 14:33:58 -05:00
|
|
|
mod verify;
|
2024-04-06 19:17:53 -04:00
|
|
|
mod watch;
|
2018-05-14 12:41:58 -04:00
|
|
|
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
/// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
|
2023-08-25 17:18:01 -04:00
|
|
|
#[derive(Parser)]
|
|
|
|
#[command(version)]
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
struct Args {
|
2023-08-25 17:18:01 -04:00
|
|
|
#[command(subcommand)]
|
|
|
|
command: Option<Subcommands>,
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
}
|
|
|
|
|
2023-08-25 17:18:01 -04:00
|
|
|
#[derive(Subcommand)]
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
enum Subcommands {
|
2024-03-28 20:29:41 -04:00
|
|
|
/// Initialize Rustlings
|
|
|
|
Init,
|
2023-08-25 17:18:01 -04:00
|
|
|
/// Verify all exercises according to the recommended order
|
|
|
|
Verify,
|
2024-04-04 21:04:53 -04:00
|
|
|
/// Same as just running `rustlings` without a subcommand.
|
2024-04-04 15:06:11 -04:00
|
|
|
Watch,
|
2023-08-25 17:18:01 -04:00
|
|
|
/// Run/Test a single exercise
|
|
|
|
Run {
|
|
|
|
/// The name of the exercise
|
|
|
|
name: String,
|
|
|
|
},
|
2024-03-28 17:11:16 -04:00
|
|
|
/// Reset a single exercise
|
2023-08-25 17:18:01 -04:00
|
|
|
Reset {
|
|
|
|
/// The name of the exercise
|
|
|
|
name: String,
|
|
|
|
},
|
|
|
|
/// Return a hint for the given exercise
|
|
|
|
Hint {
|
|
|
|
/// The name of the exercise
|
|
|
|
name: String,
|
|
|
|
},
|
|
|
|
/// List the exercises available in Rustlings
|
2024-04-06 21:03:37 -04:00
|
|
|
List,
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
}
|
|
|
|
|
2024-03-24 22:46:56 -04:00
|
|
|
fn main() -> Result<()> {
|
2023-08-25 17:18:01 -04:00
|
|
|
let args = Args::parse();
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
|
2024-03-31 12:25:54 -04:00
|
|
|
which::which("cargo").context(
|
|
|
|
"Failed to find `cargo`.
|
2024-03-31 10:55:33 -04:00
|
|
|
Did you already install Rust?
|
2024-03-31 12:25:54 -04:00
|
|
|
Try running `cargo --version` to diagnose the problem.",
|
|
|
|
)?;
|
2019-11-11 11:15:14 -05:00
|
|
|
|
2024-03-31 10:55:33 -04:00
|
|
|
let exercises = ExerciseList::parse()?.exercises;
|
2019-04-11 16:41:24 -04:00
|
|
|
|
2024-03-28 20:29:41 -04:00
|
|
|
if matches!(args.command, Some(Subcommands::Init)) {
|
|
|
|
init::init_rustlings(&exercises).context("Initialization failed")?;
|
2024-03-28 20:52:05 -04:00
|
|
|
println!(
|
|
|
|
"\nDone initialization!\n
|
|
|
|
Run `cd rustlings` to go into the generated directory.
|
|
|
|
Then run `rustlings` for further instructions on getting started."
|
|
|
|
);
|
2024-03-28 20:29:41 -04:00
|
|
|
return Ok(());
|
|
|
|
} else if !Path::new("exercises").is_dir() {
|
|
|
|
println!(
|
2024-04-06 19:17:53 -04:00
|
|
|
"
|
|
|
|
{WELCOME}
|
|
|
|
|
|
|
|
The `exercises` directory wasn't found in the current directory.
|
2024-03-28 20:52:05 -04:00
|
|
|
If you are just starting with Rustlings, run the command `rustlings init` to initialize it."
|
2024-03-28 20:29:41 -04:00
|
|
|
);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2024-04-06 19:17:53 -04:00
|
|
|
let state = State::read_or_default(&exercises);
|
|
|
|
|
2024-04-04 21:04:53 -04:00
|
|
|
match args.command {
|
|
|
|
None | Some(Subcommands::Watch) => {
|
2024-04-06 19:17:53 -04:00
|
|
|
watch::watch(&state, &exercises)?;
|
2024-04-04 21:04:53 -04:00
|
|
|
}
|
2024-03-28 20:29:41 -04:00
|
|
|
// `Init` is handled above.
|
2024-04-04 21:04:53 -04:00
|
|
|
Some(Subcommands::Init) => (),
|
2024-04-06 21:03:37 -04:00
|
|
|
Some(Subcommands::List) => {
|
|
|
|
list::list(&state, &exercises)?;
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
}
|
2024-04-04 21:04:53 -04:00
|
|
|
Some(Subcommands::Run { name }) => {
|
2024-03-31 12:25:54 -04:00
|
|
|
let exercise = find_exercise(&name, &exercises)?;
|
2024-04-04 15:06:11 -04:00
|
|
|
run(exercise).unwrap_or_else(|_| exit(1));
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
}
|
2024-04-04 21:04:53 -04:00
|
|
|
Some(Subcommands::Reset { name }) => {
|
2024-03-31 12:25:54 -04:00
|
|
|
let exercise = find_exercise(&name, &exercises)?;
|
2024-03-31 14:08:23 -04:00
|
|
|
EMBEDDED_FILES
|
|
|
|
.write_exercise_to_disk(&exercise.path, WriteStrategy::Overwrite)
|
|
|
|
.with_context(|| format!("Failed to reset the exercise {exercise}"))?;
|
2024-03-30 16:13:28 -04:00
|
|
|
println!("The file {} has been reset!", exercise.path.display());
|
2022-08-17 10:31:53 -04:00
|
|
|
}
|
2024-04-04 21:04:53 -04:00
|
|
|
Some(Subcommands::Hint { name }) => {
|
2024-03-31 12:25:54 -04:00
|
|
|
let exercise = find_exercise(&name, &exercises)?;
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
println!("{}", exercise.hint);
|
|
|
|
}
|
2024-04-06 19:17:53 -04:00
|
|
|
Some(Subcommands::Verify) => match verify(&exercises, 0)? {
|
2024-04-01 12:38:01 -04:00
|
|
|
VerifyState::AllExercisesDone => println!("All exercises done!"),
|
|
|
|
VerifyState::Failed(exercise) => bail!("Exercise {exercise} failed"),
|
|
|
|
},
|
2018-11-26 05:10:38 -05:00
|
|
|
}
|
2024-03-24 22:46:56 -04:00
|
|
|
|
|
|
|
Ok(())
|
2018-05-06 12:59:50 -04:00
|
|
|
}
|
|
|
|
|
2024-03-31 12:25:54 -04:00
|
|
|
fn find_exercise<'a>(name: &str, exercises: &'a [Exercise]) -> Result<&'a Exercise> {
|
2024-03-26 12:49:55 -04:00
|
|
|
if name == "next" {
|
2024-03-31 12:25:54 -04:00
|
|
|
for exercise in exercises {
|
|
|
|
if !exercise.looks_done()? {
|
|
|
|
return Ok(exercise);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("🎉 Congratulations! You have done all the exercises!");
|
|
|
|
println!("🔚 There are no more exercises to do next!");
|
|
|
|
exit(0);
|
2021-06-30 06:05:49 -04:00
|
|
|
}
|
2024-03-31 12:25:54 -04:00
|
|
|
|
|
|
|
exercises
|
|
|
|
.iter()
|
|
|
|
.find(|e| e.name == name)
|
|
|
|
.with_context(|| format!("No exercise found for '{name}'!"))
|
feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.
I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-20 06:46:49 -04:00
|
|
|
}
|