1
0
mirror of https://github.com/rust-lang/rustlings.git synced 2024-11-08 09:09:17 +01:00

Add solutions to bins

This commit is contained in:
mo8it 2024-05-25 18:19:30 +02:00
parent 990c68efcb
commit beb7b24e8e
5 changed files with 75 additions and 13 deletions

@ -1,2 +1,5 @@
// The exercise `intro1` only requires entering `n` in the terminal to go to the next exercise. fn main() {
// It is just an introduction to how Rustlings works. // Congratulations, you finished the first exercise 🎉
// As an introduction to Rustlings, the first exercise only required
// entering `n` in the terminal to go to the next exercise.
}

@ -1,4 +1,5 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::path::Path;
use crate::info_file::ExerciseInfo; use crate::info_file::ExerciseInfo;
@ -40,6 +41,24 @@ pub fn append_bins(
} }
buf.extend_from_slice(exercise_info.name.as_bytes()); buf.extend_from_slice(exercise_info.name.as_bytes());
buf.extend_from_slice(b".rs\" },\n"); buf.extend_from_slice(b".rs\" },\n");
let sol_path = exercise_info.sol_path();
if !Path::new(&sol_path).exists() {
continue;
}
buf.extend_from_slice(b" { name = \"");
buf.extend_from_slice(exercise_info.name.as_bytes());
buf.extend_from_slice(b"_sol");
buf.extend_from_slice(b"\", path = \"");
buf.extend_from_slice(exercise_path_prefix);
buf.extend_from_slice(b"solutions/");
if let Some(dir) = &exercise_info.dir {
buf.extend_from_slice(dir.as_bytes());
buf.push(b'/');
}
buf.extend_from_slice(exercise_info.name.as_bytes());
buf.extend_from_slice(b".rs\" },\n");
} }
} }

@ -1,6 +1,6 @@
use anyhow::{Context, Error, Result}; use anyhow::{Context, Error, Result};
use std::{ use std::{
fs::{create_dir, create_dir_all, OpenOptions}, fs::{create_dir, OpenOptions},
io::{self, Write}, io::{self, Write},
}; };
@ -43,8 +43,8 @@ struct ExerciseFiles {
} }
// A directory in the `exercises/` directory. // A directory in the `exercises/` directory.
struct ExerciseDir { pub struct ExerciseDir {
name: &'static str, pub name: &'static str,
readme: &'static [u8], readme: &'static [u8],
} }
@ -78,7 +78,7 @@ pub struct EmbeddedFiles {
/// The content of the `info.toml` file. /// The content of the `info.toml` file.
pub info_file: &'static str, pub info_file: &'static str,
exercise_files: &'static [ExerciseFiles], exercise_files: &'static [ExerciseFiles],
exercise_dirs: &'static [ExerciseDir], pub exercise_dirs: &'static [ExerciseDir],
} }
impl EmbeddedFiles { impl EmbeddedFiles {
@ -121,13 +121,9 @@ impl EmbeddedFiles {
// 14 = 10 + 1 + 3 // 14 = 10 + 1 + 3
// solutions/ + / + .rs // solutions/ + / + .rs
let mut dir_path = String::with_capacity(14 + dir.name.len() + exercise_name.len()); let mut solution_path = String::with_capacity(14 + dir.name.len() + exercise_name.len());
dir_path.push_str("solutions/"); solution_path.push_str("solutions/");
dir_path.push_str(dir.name); solution_path.push_str(dir.name);
create_dir_all(&dir_path)
.with_context(|| format!("Failed to create the directory {dir_path}"))?;
let mut solution_path = dir_path;
solution_path.push('/'); solution_path.push('/');
solution_path.push_str(exercise_name); solution_path.push_str(exercise_name);
solution_path.push_str(".rs"); solution_path.push_str(".rs");

@ -49,6 +49,30 @@ impl ExerciseInfo {
path path
} }
/// Path to the solution file starting with the `solutions/` directory.
pub fn sol_path(&self) -> String {
let mut path = if let Some(dir) = &self.dir {
// 14 = 10 + 1 + 3
// solutions/ + / + .rs
let mut path = String::with_capacity(14 + dir.len() + self.name.len());
path.push_str("solutions/");
path.push_str(dir);
path.push('/');
path
} else {
// 13 = 10 + 3
// solutions/ + .rs
let mut path = String::with_capacity(13 + self.name.len());
path.push_str("solutions/");
path
};
path.push_str(&self.name);
path.push_str(".rs");
path
}
} }
/// The deserialized `info.toml` file. /// The deserialized `info.toml` file.

@ -34,6 +34,20 @@ pub fn init() -> Result<()> {
.init_exercises_dir(&info_file.exercises) .init_exercises_dir(&info_file.exercises)
.context("Failed to initialize the `rustlings/exercises` directory")?; .context("Failed to initialize the `rustlings/exercises` directory")?;
create_dir("solutions").context("Failed to create the `solutions/` directory")?;
for dir in EMBEDDED_FILES.exercise_dirs {
let mut dir_path = String::with_capacity(10 + dir.name.len());
dir_path.push_str("solutions/");
dir_path.push_str(dir.name);
create_dir(&dir_path)
.with_context(|| format!("Failed to create the directory {dir_path}"))?;
}
for exercise_info in &info_file.exercises {
let solution_path = exercise_info.sol_path();
fs::write(&solution_path, INIT_SOLUTION_FILE)
.with_context(|| format!("Failed to create the file {solution_path}"))?;
}
let current_cargo_toml = include_str!("../dev-Cargo.toml"); let current_cargo_toml = include_str!("../dev-Cargo.toml");
// Skip the first line (comment). // Skip the first line (comment).
let newline_ind = current_cargo_toml let newline_ind = current_cargo_toml
@ -72,6 +86,12 @@ pub fn init() -> Result<()> {
Ok(()) Ok(())
} }
const INIT_SOLUTION_FILE: &[u8] = b"fn main() {
// DON'T EDIT THIS SOLUTION FILE!
// It will be automatically filled after you finish the exercise.
}
";
const GITIGNORE: &[u8] = b".rustlings-state.txt const GITIGNORE: &[u8] = b".rustlings-state.txt
solutions solutions
Cargo.lock Cargo.lock