mirror of
https://github.com/rust-lang/rustlings.git
synced 2025-01-13 00:00:03 +03:00
Deal with long strings
This commit is contained in:
parent
1e3745ccdf
commit
2a95a3e966
32
info.toml
32
info.toml
|
@ -1,3 +1,35 @@
|
||||||
|
welcome_message = """Is this your first time? Don't worry, Rustlings was made for beginners! We are
|
||||||
|
going to teach you a lot of things about Rust, but before we can get
|
||||||
|
started, here's a couple of notes about how Rustlings operates:
|
||||||
|
|
||||||
|
1. The central concept behind Rustlings is that you solve exercises. These
|
||||||
|
exercises usually have some sort of syntax error in them, which will cause
|
||||||
|
them to fail compilation or testing. Sometimes there's a logic error instead
|
||||||
|
of a syntax error. No matter what error, it's your job to find it and fix it!
|
||||||
|
You'll know when you fixed it because then, the exercise will compile and
|
||||||
|
Rustlings will be able to move on to the next exercise.
|
||||||
|
2. If you run Rustlings in watch mode (which we recommend), it'll automatically
|
||||||
|
start with the first exercise. Don't get confused by an error message popping
|
||||||
|
up as soon as you run Rustlings! This is part of the exercise that you're
|
||||||
|
supposed to solve, so open the exercise file in an editor and start your
|
||||||
|
detective work!
|
||||||
|
3. If you're stuck on an exercise, there is a helpful hint you can view by typing
|
||||||
|
'hint' (in watch mode), or running `rustlings hint exercise_name`.
|
||||||
|
4. If an exercise doesn't make sense to you, feel free to open an issue on GitHub!
|
||||||
|
(https://github.com/rust-lang/rustlings/issues/new). We look at every issue,
|
||||||
|
and sometimes, other learners do too so you can help each other out!
|
||||||
|
|
||||||
|
Got all that? Great! To get started, run `rustlings watch` in order to get the first exercise.
|
||||||
|
Make sure to have your editor open in the `rustlings` directory!"""
|
||||||
|
|
||||||
|
final_message = """We hope you enjoyed learning about the various aspects of Rust!
|
||||||
|
If you noticed any issues, please don't hesitate to report them to our repo.
|
||||||
|
You can also contribute your own exercises to help the greater community!
|
||||||
|
|
||||||
|
Before reporting an issue or contributing, please read our guidelines:
|
||||||
|
https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md
|
||||||
|
"""
|
||||||
|
|
||||||
# INTRO
|
# INTRO
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
pub const WELCOME: &str = r" welcome to...
|
|
||||||
_ _ _
|
|
||||||
_ __ _ _ ___| |_| (_)_ __ __ _ ___
|
|
||||||
| '__| | | / __| __| | | '_ \ / _` / __|
|
|
||||||
| | | |_| \__ \ |_| | | | | | (_| \__ \
|
|
||||||
|_| \__,_|___/\__|_|_|_| |_|\__, |___/
|
|
||||||
|___/";
|
|
||||||
|
|
||||||
pub const DEFAULT_OUT: &str =
|
|
||||||
"Is this your first time? Don't worry, Rustlings was made for beginners! We are
|
|
||||||
going to teach you a lot of things about Rust, but before we can get
|
|
||||||
started, here's a couple of notes about how Rustlings operates:
|
|
||||||
|
|
||||||
1. The central concept behind Rustlings is that you solve exercises. These
|
|
||||||
exercises usually have some sort of syntax error in them, which will cause
|
|
||||||
them to fail compilation or testing. Sometimes there's a logic error instead
|
|
||||||
of a syntax error. No matter what error, it's your job to find it and fix it!
|
|
||||||
You'll know when you fixed it because then, the exercise will compile and
|
|
||||||
Rustlings will be able to move on to the next exercise.
|
|
||||||
2. If you run Rustlings in watch mode (which we recommend), it'll automatically
|
|
||||||
start with the first exercise. Don't get confused by an error message popping
|
|
||||||
up as soon as you run Rustlings! This is part of the exercise that you're
|
|
||||||
supposed to solve, so open the exercise file in an editor and start your
|
|
||||||
detective work!
|
|
||||||
3. If you're stuck on an exercise, there is a helpful hint you can view by typing
|
|
||||||
'hint' (in watch mode), or running `rustlings hint exercise_name`.
|
|
||||||
4. If an exercise doesn't make sense to you, feel free to open an issue on GitHub!
|
|
||||||
(https://github.com/rust-lang/rustlings/issues/new). We look at every issue,
|
|
||||||
and sometimes, other learners do too so you can help each other out!
|
|
||||||
|
|
||||||
Got all that? Great! To get started, run `rustlings watch` in order to get the first exercise.
|
|
||||||
Make sure to have your editor open in the `rustlings` directory!";
|
|
||||||
|
|
||||||
pub const FENISH_LINE: &str = "+----------------------------------------------------+
|
|
||||||
| You made it to the Fe-nish line! |
|
|
||||||
+-------------------------- ------------------------+
|
|
||||||
\\/\x1b[31m
|
|
||||||
▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒
|
|
||||||
▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒
|
|
||||||
▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒
|
|
||||||
░░▒▒▒▒░░▒▒ ▒▒ ▒▒ ▒▒ ▒▒░░▒▒▒▒
|
|
||||||
▓▓▓▓▓▓▓▓ ▓▓ ▓▓██ ▓▓ ▓▓██ ▓▓ ▓▓▓▓▓▓▓▓
|
|
||||||
▒▒▒▒ ▒▒ ████ ▒▒ ████ ▒▒░░ ▒▒▒▒
|
|
||||||
▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒
|
|
||||||
▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓▓▒▒▓▓▒▒▒▒▒▒▒▒
|
|
||||||
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
|
|
||||||
▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒
|
|
||||||
▒▒ ▒▒▒▒▒▒▒▒▒▒██████▒▒▒▒▒▒▒▒▒▒ ▒▒
|
|
||||||
▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒
|
|
||||||
▒▒ ▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒ ▒▒
|
|
||||||
▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒
|
|
||||||
▒▒ ▒▒ ▒▒ ▒▒\x1b[0m
|
|
||||||
|
|
||||||
We hope you enjoyed learning about the various aspects of Rust!
|
|
||||||
If you noticed any issues, please don't hesitate to report them to our repo.
|
|
||||||
You can also contribute your own exercises to help the greater community!
|
|
||||||
|
|
||||||
Before reporting an issue or contributing, please read our guidelines:
|
|
||||||
https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md";
|
|
|
@ -24,6 +24,10 @@ pub enum Mode {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct InfoFile {
|
pub struct InfoFile {
|
||||||
|
// TODO
|
||||||
|
pub welcome_message: Option<String>,
|
||||||
|
// TODO
|
||||||
|
pub final_message: Option<String>,
|
||||||
pub exercises: Vec<Exercise>,
|
pub exercises: Vec<Exercise>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +43,7 @@ impl InfoFile {
|
||||||
.context("Failed to parse `info.toml`")?;
|
.context("Failed to parse `info.toml`")?;
|
||||||
|
|
||||||
if slf.exercises.is_empty() {
|
if slf.exercises.is_empty() {
|
||||||
panic!(
|
panic!("{NO_EXERCISES_ERR}");
|
||||||
"There are no exercises yet!
|
|
||||||
If you are developing third-party exercises, add at least one exercise before testing."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(slf)
|
Ok(slf)
|
||||||
|
@ -119,3 +120,6 @@ impl Display for Exercise {
|
||||||
self.path.fmt(f)
|
self.path.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NO_EXERCISES_ERR: &str = "There are no exercises yet!
|
||||||
|
If you are developing third-party exercises, add at least one exercise before testing.";
|
||||||
|
|
40
src/init.rs
40
src/init.rs
|
@ -36,47 +36,33 @@ publish = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_gitignore() -> io::Result<()> {
|
fn create_gitignore() -> io::Result<()> {
|
||||||
let gitignore = b"/target
|
|
||||||
/.rustlings-state.json";
|
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
.create_new(true)
|
.create_new(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(".gitignore")?
|
.open(".gitignore")?
|
||||||
.write_all(gitignore)
|
.write_all(GITIGNORE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_vscode_dir() -> Result<()> {
|
fn create_vscode_dir() -> Result<()> {
|
||||||
create_dir(".vscode").context("Failed to create the directory `.vscode`")?;
|
create_dir(".vscode").context("Failed to create the directory `.vscode`")?;
|
||||||
let vs_code_extensions_json = br#"{"recommendations":["rust-lang.rust-analyzer"]}"#;
|
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
.create_new(true)
|
.create_new(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(".vscode/extensions.json")?
|
.open(".vscode/extensions.json")?
|
||||||
.write_all(vs_code_extensions_json)?;
|
.write_all(VS_CODE_EXTENSIONS_JSON)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(exercises: &[Exercise]) -> Result<()> {
|
pub fn init(exercises: &[Exercise]) -> Result<()> {
|
||||||
if Path::new("exercises").is_dir() && Path::new("Cargo.toml").is_file() {
|
if Path::new("exercises").is_dir() && Path::new("Cargo.toml").is_file() {
|
||||||
bail!(
|
bail!(PROBABLY_IN_RUSTLINGS_DIR_ERR);
|
||||||
"A directory with the name `exercises` and a file with the name `Cargo.toml` already exist
|
|
||||||
in the current directory. It looks like Rustlings was already initialized here.
|
|
||||||
Run `rustlings` for instructions on getting started with the exercises.
|
|
||||||
|
|
||||||
If you didn't already initialize Rustlings, please initialize it in another directory."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let rustlings_path = Path::new("rustlings");
|
let rustlings_path = Path::new("rustlings");
|
||||||
if let Err(e) = create_dir(rustlings_path) {
|
if let Err(e) = create_dir(rustlings_path) {
|
||||||
if e.kind() == ErrorKind::AlreadyExists {
|
if e.kind() == ErrorKind::AlreadyExists {
|
||||||
bail!(
|
bail!(RUSTLINGS_DIR_ALREADY_EXISTS_ERR);
|
||||||
"A directory with the name `rustlings` already exists in the current directory.
|
|
||||||
You probably already initialized Rustlings.
|
|
||||||
Run `cd rustlings`
|
|
||||||
Then run `rustlings` again"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
|
@ -96,3 +82,21 @@ Then run `rustlings` again"
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GITIGNORE: &[u8] = b"/target
|
||||||
|
/.rustlings-state.json";
|
||||||
|
|
||||||
|
const VS_CODE_EXTENSIONS_JSON: &[u8] = br#"{"recommendations":["rust-lang.rust-analyzer"]}"#;
|
||||||
|
|
||||||
|
const PROBABLY_IN_RUSTLINGS_DIR_ERR: &str =
|
||||||
|
"A directory with the name `exercises` and a file with the name `Cargo.toml` already exist
|
||||||
|
in the current directory. It looks like Rustlings was already initialized here.
|
||||||
|
Run `rustlings` for instructions on getting started with the exercises.
|
||||||
|
|
||||||
|
If you didn't already initialize Rustlings, please initialize it in another directory.";
|
||||||
|
|
||||||
|
const RUSTLINGS_DIR_ALREADY_EXISTS_ERR: &str =
|
||||||
|
"A directory with the name `rustlings` already exists in the current directory.
|
||||||
|
You probably already initialized Rustlings.
|
||||||
|
Run `cd rustlings`
|
||||||
|
Then run `rustlings` again";
|
||||||
|
|
65
src/main.rs
65
src/main.rs
|
@ -3,7 +3,6 @@ use clap::{Parser, Subcommand};
|
||||||
use std::{path::Path, process::exit};
|
use std::{path::Path, process::exit};
|
||||||
|
|
||||||
mod app_state;
|
mod app_state;
|
||||||
mod consts;
|
|
||||||
mod embedded;
|
mod embedded;
|
||||||
mod exercise;
|
mod exercise;
|
||||||
mod init;
|
mod init;
|
||||||
|
@ -14,7 +13,6 @@ mod watch;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
app_state::AppState,
|
app_state::AppState,
|
||||||
consts::WELCOME,
|
|
||||||
exercise::InfoFile,
|
exercise::InfoFile,
|
||||||
init::init,
|
init::init,
|
||||||
list::list,
|
list::list,
|
||||||
|
@ -54,11 +52,7 @@ enum Subcommands {
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
which::which("cargo").context(
|
which::which("cargo").context(CARGO_NOT_FOUND_ERR)?;
|
||||||
"Failed to find `cargo`.
|
|
||||||
Did you already install Rust?
|
|
||||||
Try running `cargo --version` to diagnose the problem.",
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut info_file = InfoFile::parse()?;
|
let mut info_file = InfoFile::parse()?;
|
||||||
info_file.exercises.shrink_to_fit();
|
info_file.exercises.shrink_to_fit();
|
||||||
|
@ -66,20 +60,11 @@ Try running `cargo --version` to diagnose the problem.",
|
||||||
|
|
||||||
if matches!(args.command, Some(Subcommands::Init)) {
|
if matches!(args.command, Some(Subcommands::Init)) {
|
||||||
init(&exercises).context("Initialization failed")?;
|
init(&exercises).context("Initialization failed")?;
|
||||||
println!(
|
|
||||||
"\nDone initialization!\n
|
println!("{POST_INIT_MSG}");
|
||||||
Run `cd rustlings` to go into the generated directory.
|
|
||||||
Then run `rustlings` for further instructions on getting started."
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if !Path::new("exercises").is_dir() {
|
} else if !Path::new("exercises").is_dir() {
|
||||||
println!(
|
println!("{PRE_INIT_MSG}");
|
||||||
"
|
|
||||||
{WELCOME}
|
|
||||||
|
|
||||||
The `exercises` directory wasn't found in the current directory.
|
|
||||||
If you are just starting with Rustlings, run the command `rustlings init` to initialize it."
|
|
||||||
);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,3 +103,45 @@ If you are just starting with Rustlings, run the command `rustlings init` to ini
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CARGO_NOT_FOUND_ERR: &str = "Failed to find `cargo`.
|
||||||
|
Did you already install Rust?
|
||||||
|
Try running `cargo --version` to diagnose the problem.";
|
||||||
|
|
||||||
|
const PRE_INIT_MSG: &str = r"
|
||||||
|
welcome to...
|
||||||
|
_ _ _
|
||||||
|
_ __ _ _ ___| |_| (_)_ __ __ _ ___
|
||||||
|
| '__| | | / __| __| | | '_ \ / _` / __|
|
||||||
|
| | | |_| \__ \ |_| | | | | | (_| \__ \
|
||||||
|
|_| \__,_|___/\__|_|_|_| |_|\__, |___/
|
||||||
|
|___/
|
||||||
|
|
||||||
|
The `exercises` directory wasn't found in the current directory.
|
||||||
|
If you are just starting with Rustlings, run the command `rustlings init` to initialize it.";
|
||||||
|
|
||||||
|
const POST_INIT_MSG: &str = "
|
||||||
|
Done initialization!
|
||||||
|
|
||||||
|
Run `cd rustlings` to go into the generated directory.
|
||||||
|
Then run `rustlings` for further instructions on getting started.";
|
||||||
|
|
||||||
|
const FENISH_LINE: &str = "+----------------------------------------------------+
|
||||||
|
| You made it to the Fe-nish line! |
|
||||||
|
+-------------------------- ------------------------+
|
||||||
|
\\/\x1b[31m
|
||||||
|
▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒
|
||||||
|
▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒
|
||||||
|
▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒
|
||||||
|
░░▒▒▒▒░░▒▒ ▒▒ ▒▒ ▒▒ ▒▒░░▒▒▒▒
|
||||||
|
▓▓▓▓▓▓▓▓ ▓▓ ▓▓██ ▓▓ ▓▓██ ▓▓ ▓▓▓▓▓▓▓▓
|
||||||
|
▒▒▒▒ ▒▒ ████ ▒▒ ████ ▒▒░░ ▒▒▒▒
|
||||||
|
▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒
|
||||||
|
▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓▓▓▓▓▓▒▒▒▒▒▒▒▒
|
||||||
|
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
|
||||||
|
▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒
|
||||||
|
▒▒ ▒▒▒▒▒▒▒▒▒▒██████▒▒▒▒▒▒▒▒▒▒ ▒▒
|
||||||
|
▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒
|
||||||
|
▒▒ ▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒ ▒▒
|
||||||
|
▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒
|
||||||
|
▒▒ ▒▒ ▒▒ ▒▒\x1b[0m";
|
||||||
|
|
10
src/watch.rs
10
src/watch.rs
|
@ -89,10 +89,12 @@ pub fn watch(app_state: &mut AppState) -> Result<WatchExit> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_state.into_writer().write_all(b"
|
watch_state.into_writer().write_all(QUIT_MSG)?;
|
||||||
We hope you're enjoying learning Rust!
|
|
||||||
If you want to continue working on the exercises at a later point, you can simply run `rustlings` again.
|
|
||||||
")?;
|
|
||||||
|
|
||||||
Ok(WatchExit::Shutdown)
|
Ok(WatchExit::Shutdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QUIT_MSG: &[u8] = b"
|
||||||
|
We hope you're enjoying learning Rust!
|
||||||
|
If you want to continue working on the exercises at a later point, you can simply run `rustlings` again.
|
||||||
|
";
|
||||||
|
|
Loading…
Reference in a new issue