summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormo8it <mo8it@proton.me>2024-05-25 18:19:30 +0200
committermo8it <mo8it@proton.me>2024-05-25 18:19:30 +0200
commitbeb7b24e8e9fe05cbcfaaf4676d52f63351fad16 (patch)
tree782637ddff0e58c6fddcab257e0619768396b50f /src
parent990c68efcba8e1e2b7f2d8c5b6c16885d3920010 (diff)
Add solutions to bins
Diffstat (limited to 'src')
-rw-r--r--src/cargo_toml.rs19
-rw-r--r--src/embedded.rs18
-rw-r--r--src/info_file.rs24
-rw-r--r--src/init.rs20
4 files changed, 70 insertions, 11 deletions
diff --git a/src/cargo_toml.rs b/src/cargo_toml.rs
index b7951f6..cf17acd 100644
--- a/src/cargo_toml.rs
+++ b/src/cargo_toml.rs
@@ -1,4 +1,5 @@
use anyhow::{Context, Result};
+use std::path::Path;
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(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");
}
}
diff --git a/src/embedded.rs b/src/embedded.rs
index e710a4e..1dce46c 100644
--- a/src/embedded.rs
+++ b/src/embedded.rs
@@ -1,6 +1,6 @@
use anyhow::{Context, Error, Result};
use std::{
- fs::{create_dir, create_dir_all, OpenOptions},
+ fs::{create_dir, OpenOptions},
io::{self, Write},
};
@@ -43,8 +43,8 @@ struct ExerciseFiles {
}
// A directory in the `exercises/` directory.
-struct ExerciseDir {
- name: &'static str,
+pub struct ExerciseDir {
+ pub name: &'static str,
readme: &'static [u8],
}
@@ -78,7 +78,7 @@ pub struct EmbeddedFiles {
/// The content of the `info.toml` file.
pub info_file: &'static str,
exercise_files: &'static [ExerciseFiles],
- exercise_dirs: &'static [ExerciseDir],
+ pub exercise_dirs: &'static [ExerciseDir],
}
impl EmbeddedFiles {
@@ -121,13 +121,9 @@ impl EmbeddedFiles {
// 14 = 10 + 1 + 3
// solutions/ + / + .rs
- let mut dir_path = String::with_capacity(14 + dir.name.len() + exercise_name.len());
- dir_path.push_str("solutions/");
- dir_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;
+ let mut solution_path = String::with_capacity(14 + dir.name.len() + exercise_name.len());
+ solution_path.push_str("solutions/");
+ solution_path.push_str(dir.name);
solution_path.push('/');
solution_path.push_str(exercise_name);
solution_path.push_str(".rs");
diff --git a/src/info_file.rs b/src/info_file.rs
index 0c45928..5ea487f 100644
--- a/src/info_file.rs
+++ b/src/info_file.rs
@@ -49,6 +49,30 @@ impl ExerciseInfo {
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.
diff --git a/src/init.rs b/src/init.rs
index 67d8a24..4063ca7 100644
--- a/src/init.rs
+++ b/src/init.rs
@@ -34,6 +34,20 @@ pub fn init() -> Result<()> {
.init_exercises_dir(&info_file.exercises)
.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");
// Skip the first line (comment).
let newline_ind = current_cargo_toml
@@ -72,6 +86,12 @@ pub fn init() -> Result<()> {
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
solutions
Cargo.lock