mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-05-11 12:56:07 +02:00
Compare commits
19 Commits
177e2870c5
...
dc5c72bc19
Author | SHA1 | Date | |
---|---|---|---|
mo8it | dc5c72bc19 | ||
mo8it | 0ce5d9d4d7 | ||
mo8it | 37fcbeb596 | ||
mo8it | 2f071c97b0 | ||
mo8it | 9664f4357c | ||
mo8it | 74ae506603 | ||
mo8it | 2965867338 | ||
mo8it | e63e668d86 | ||
mo8it | b7289e59aa | ||
mo8it | be4dfe8be0 | ||
mo8it | e230ffcf03 | ||
mo8it | 0d7b036137 | ||
mo8it | 078142c43c | ||
mo8it | 5920a58e83 | ||
mo8it | aaea5b490f | ||
mo8it | 8d45cdb09d | ||
mo8it | a4e623ea94 | ||
mo8it | 5595e1c397 | ||
mo8it | ca41f9e2df |
|
@ -0,0 +1,7 @@
|
|||
[files]
|
||||
extend-exclude = [
|
||||
"CHANGELOG.md",
|
||||
]
|
||||
|
||||
[default.extend-words]
|
||||
"ratatui" = "ratatui"
|
147
CONTRIBUTING.md
147
CONTRIBUTING.md
|
@ -1,129 +1,56 @@
|
|||
## Contributing to Rustlings
|
||||
# Contributing to Rustlings
|
||||
|
||||
First off, thanks for taking the time to contribute!! ❤️
|
||||
First off, thanks for taking the time to contribute! ❤️
|
||||
|
||||
### Quick Reference
|
||||
## Quick Reference
|
||||
|
||||
I want to...
|
||||
I want to …
|
||||
|
||||
_add an exercise! ➡️ [read this](#addex) and then [open a Pull Request](#prs)_
|
||||
- _report a bug!_ ➡️ [open an issue](#issues)
|
||||
- _fix a bug!_ ➡️ [open a pull request](#pull-requests)
|
||||
- _implement a new feature!_ ➡️ [open an issue to discuss it first, then a pull request](#issues)
|
||||
- _add an exercise!_ ➡️ [read this](#adding-an-exercise)
|
||||
- _update an outdated exercise!_ ➡️ [open a pull request](#pull-requests)
|
||||
|
||||
_update an outdated exercise! ➡️ [open a Pull Request](#prs)_
|
||||
|
||||
_report a bug! ➡️ [open an Issue](#issues)_
|
||||
|
||||
_fix a bug! ➡️ [open a Pull Request](#prs)_
|
||||
|
||||
_implement a new feature! ➡️ [open an Issue to discuss it first, then a Pull Request](#issues)_
|
||||
|
||||
<a name="#src"></a>
|
||||
### Working on the source code
|
||||
|
||||
`rustlings` is basically a glorified `rustc` wrapper. Therefore the source code
|
||||
isn't really that complicated since the bulk of the work is done by `rustc`.
|
||||
|
||||
<a name="addex"></a>
|
||||
### Adding an exercise
|
||||
|
||||
The first step is to add the exercise! Name the file `exercises/yourTopic/yourTopicN.rs`, make sure to
|
||||
put in some helpful links, and link to sections of the book in `exercises/yourTopic/README.md`.
|
||||
|
||||
Next make sure it runs with `rustlings`. The exercise metadata is stored in `info.toml`, under the `exercises` array. The order of the `exercises` array determines the order the exercises are run by `rustlings verify` and `rustlings watch`.
|
||||
|
||||
Add the metadata for your exercise in the correct order in the `exercises` array. If you are unsure of the correct ordering, add it at the bottom and ask in your pull request. The exercise metadata should contain the following:
|
||||
```diff
|
||||
...
|
||||
+ [[exercises]]
|
||||
+ name = "yourTopicN"
|
||||
+ path = "exercises/yourTopic/yourTopicN.rs"
|
||||
+ mode = "compile"
|
||||
+ hint = """
|
||||
+ Some kind of useful hint for your exercise."""
|
||||
...
|
||||
```
|
||||
|
||||
The `mode` attribute decides whether Rustlings will only compile your exercise, or compile and test it. If you have tests to verify in your exercise, choose `test`, otherwise `compile`. If you're working on a Clippy exercise, use `mode = "clippy"`.
|
||||
|
||||
That's all! Feel free to put up a pull request.
|
||||
|
||||
<a name="issues"></a>
|
||||
### Issues
|
||||
## Issues
|
||||
|
||||
You can open an issue [here](https://github.com/rust-lang/rustlings/issues/new).
|
||||
If you're reporting a bug, please include the output of the following commands:
|
||||
|
||||
- `rustc --version`
|
||||
- `cargo --version`
|
||||
- `rustlings --version`
|
||||
- `ls -la`
|
||||
- Your OS name and version
|
||||
|
||||
<a name="prs"></a>
|
||||
### Pull Requests
|
||||
## Pull Requests
|
||||
|
||||
Opening a pull request is as easy as forking the repository and committing your
|
||||
changes. There's a couple of things to watch out for:
|
||||
You are welcome to open a pull request, but unless it is small and trivial, **please open an issue to discuss your idea first** 🙏🏼
|
||||
|
||||
#### Write correct commit messages
|
||||
Opening a pull request is as easy as forking the repository and committing your changes.
|
||||
If you need any help with it or face any Git related problems, don't hesitate to ask for help 🤗
|
||||
|
||||
We follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
specification.
|
||||
This means that you have to format your commit messages in a specific way. Say
|
||||
you're working on adding a new exercise called `foobar1.rs`. You could write
|
||||
the following commit message:
|
||||
It may take time to review your pull request.
|
||||
Please be patient 😇
|
||||
|
||||
```
|
||||
feat: add foobar1.rs exercise
|
||||
## Adding An Exercise
|
||||
|
||||
- Name the file `exercises/yourTopic/yourTopicN.rs`.
|
||||
- Make sure to put in some helpful links, and link to sections of the book in `exercises/yourTopic/README.md`.
|
||||
- Add a (possible) solution at `solutions/yourTopic/yourTopicN.rs` with comments and links explaining it.
|
||||
- Add the [metadata for your exercise](#exercise-metadata) in the `info.toml` file.
|
||||
- Make sure your exercise runs with `rustlings run yourTopicN`.
|
||||
- [Open a pull request](#pull-requests).
|
||||
|
||||
### Exercise Metadata
|
||||
|
||||
The exercise metadata should contain the following:
|
||||
|
||||
```toml
|
||||
[[exercises]]
|
||||
name = "yourTopicN"
|
||||
dir = "yourTopic"
|
||||
hint = """A useful (multi-line) hint for your exercise."""
|
||||
```
|
||||
|
||||
If you're just fixing a bug, please use the `fix` type:
|
||||
|
||||
```
|
||||
fix(verify): make sure verify doesn't self-destruct
|
||||
```
|
||||
|
||||
The scope within the brackets is optional, but should be any of these:
|
||||
|
||||
- `installation` (for the installation script)
|
||||
- `cli` (for general CLI changes)
|
||||
- `verify` (for the verification source file)
|
||||
- `watch` (for the watch functionality source)
|
||||
- `run` (for the run functionality source)
|
||||
- `EXERCISENAME` (if you're changing a specific exercise, or set of exercises,
|
||||
substitute them here)
|
||||
|
||||
When the commit also happens to close an existing issue, link it in the message
|
||||
body:
|
||||
|
||||
```
|
||||
fix: update foobar
|
||||
|
||||
closes #101029908
|
||||
```
|
||||
|
||||
If you're doing simple changes, like updating a book link, use `chore`:
|
||||
|
||||
```
|
||||
chore: update exercise1.rs book link
|
||||
```
|
||||
|
||||
If you're updating documentation, use `docs`:
|
||||
|
||||
```
|
||||
docs: add more information to Readme
|
||||
```
|
||||
|
||||
If, and only if, you're absolutely sure you want to make a breaking change
|
||||
(please discuss this beforehand!), add an exclamation mark to the type and
|
||||
explain the breaking change in the message body:
|
||||
|
||||
```
|
||||
fix!: completely change verification
|
||||
|
||||
BREAKING CHANGE: This has to be done because lorem ipsum dolor
|
||||
```
|
||||
|
||||
#### Pull Request Workflow
|
||||
|
||||
Once you open a Pull Request, it may be reviewed or labeled (or both) until
|
||||
the maintainers accept your change. Please be patient, it may take some time
|
||||
for this to happen!
|
||||
If your exercise doesn't contain any test, add `test = false` to the exercise metadata.
|
||||
But adding tests is recommended.
|
||||
|
|
|
@ -679,7 +679,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustlings"
|
||||
version = "6.0.0-beta.0"
|
||||
version = "6.0.0-beta.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
|
@ -698,7 +698,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustlings-macros"
|
||||
version = "6.0.0-beta.0"
|
||||
version = "6.0.0-beta.3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
|
|
18
Cargo.toml
18
Cargo.toml
|
@ -8,7 +8,7 @@ exclude = [
|
|||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "6.0.0-beta.0"
|
||||
version = "6.0.0-beta.3"
|
||||
authors = [
|
||||
"Liv <mokou@fastmail.com>",
|
||||
"Mo Bitar <mo8it@proton.me>",
|
||||
|
@ -37,11 +37,14 @@ keywords = [
|
|||
"learning",
|
||||
]
|
||||
include = [
|
||||
"/exercises/",
|
||||
"/info.toml",
|
||||
"/LICENSE",
|
||||
"/README.md",
|
||||
"/src/",
|
||||
"/exercises/",
|
||||
"/solutions/",
|
||||
"/info.toml",
|
||||
# A symlink to be able to include `dev/Cargo.toml` although `dev` is excluded.
|
||||
"/dev-Cargo.toml",
|
||||
"/README.md",
|
||||
"/LICENSE",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
@ -52,7 +55,7 @@ hashbrown = "0.14.3"
|
|||
notify-debouncer-mini = "0.4.1"
|
||||
os_pipe = "1.1.5"
|
||||
ratatui = "0.26.2"
|
||||
rustlings-macros = { path = "rustlings-macros", version = "6.0.0-beta.0" }
|
||||
rustlings-macros = { path = "rustlings-macros", version = "=6.0.0-beta.3" }
|
||||
serde.workspace = true
|
||||
toml_edit.workspace = true
|
||||
which = "6.0.1"
|
||||
|
@ -66,3 +69,6 @@ panic = "abort"
|
|||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[package.metadata.release]
|
||||
pre-release-hook = ["./release-hook.sh"]
|
||||
|
|
87
README.md
87
README.md
|
@ -21,18 +21,34 @@ Before installing Rustlings, you need to have _Rust installed_.
|
|||
Visit [www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install) for further instructions on installing Rust.
|
||||
This'll also install _Cargo_, Rust's package/project manager.
|
||||
|
||||
🐧 If you're on Linux, make sure you've installed `gcc` (for a linker). Deb: `sudo apt install build-essential gcc`. Dnf: `sudo dnf install gcc`.
|
||||
> 🐧 If you're on Linux, make sure you've installed `gcc` (for a linker).
|
||||
>
|
||||
> Deb: `sudo apt install gcc`.
|
||||
> Dnf: `sudo dnf install gcc`.
|
||||
|
||||
🍎 If you're on MacOS, make sure you've installed Xcode and its developer tools by typing `xcode-select --install`.
|
||||
> 🍎 If you're on MacOS, make sure you've installed Xcode and its developer tools by running `xcode-select --install`.
|
||||
|
||||
### Installing Rustlings
|
||||
|
||||
The following command will download and compile Rustlings:
|
||||
|
||||
<!-- TODO: Remove @6.0.0-beta.x -->
|
||||
|
||||
```bash
|
||||
cargo install rustlings --locked
|
||||
cargo install rustlings@6.0.0-beta.3
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><strong>If the installation fails…</strong> (<em>click to expand</em>)</summary>
|
||||
|
||||
<!-- TODO: Remove @6.0.0-beta.x -->
|
||||
|
||||
- Make sure you have the latest Rust version by running `rustup update`
|
||||
- Try adding the `--locked` flag: `cargo install rustlings@6.0.0-beta.3 --locked`
|
||||
- Otherwise, please [report the issue](https://github.com/rust-lang/rustlings/issues/new)
|
||||
|
||||
</details>
|
||||
|
||||
### Initialization
|
||||
|
||||
After installing Rustlings, run the following command to initialize the `rustlings/` directory:
|
||||
|
@ -41,7 +57,7 @@ After installing Rustlings, run the following command to initialize the `rustlin
|
|||
rustlings init
|
||||
```
|
||||
|
||||
Now, go into the newly initialized directory and run Rustlings for further instructions on getting started with the exercises:
|
||||
Now, go into the newly initialized directory and launch Rustlings for further instructions on getting started with the exercises:
|
||||
|
||||
```bash
|
||||
cd rustlings/
|
||||
|
@ -50,45 +66,40 @@ rustlings
|
|||
|
||||
## Doing exercises
|
||||
|
||||
The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/<topic>`.
|
||||
For every topic there is an additional README file with some resources to get you started on the topic.
|
||||
We really recommend that you have a look at them before you start.
|
||||
The exercises are sorted by topic and can be found in the subdirectory `exercises/<topic>`.
|
||||
For every topic, there is an additional `README.md` file with some resources to get you started on the topic.
|
||||
We highly recommend that you have a look at them before you start 📚️
|
||||
|
||||
The task is simple.
|
||||
Most exercises contain an error that keeps them from compiling, and it's up to you to fix it!
|
||||
Some exercises are also run as tests, but Rustlings handles them all the same.
|
||||
To run the exercises in the recommended order, execute:
|
||||
Some exercises contain tests that need to pass for the exercise to be done ✅
|
||||
|
||||
```bash
|
||||
rustlings
|
||||
```
|
||||
### Watch Mode
|
||||
|
||||
This will try to verify the completion of every exercise in a predetermined order (what we think is best for newcomers).
|
||||
It will also rerun automatically every time you change a file in the `exercises/` directory.
|
||||
After [initialization](#initialization), Rustlings can be launched by simply running the command `rustlings`.
|
||||
|
||||
In case you want to go by your own order, or want to only verify a single exercise, you can run:
|
||||
This will start the _watch mode_ which walks you through the exercises in a predefined order (what we think is best for newcomers).
|
||||
It will rerun the current exercise automatically every time you change the exercise's file in the `exercises/` directory.
|
||||
|
||||
```bash
|
||||
rustlings run EXERCISE_NAME
|
||||
```
|
||||
<details>
|
||||
<summary><strong>If detecting file changes in the <code>exercises/</code> directory fails…</strong> (<em>click to expand</em>)</summary>
|
||||
|
||||
Or simply use the following command to run the next pending exercise in the course:
|
||||
> You can add the **`--manual-run`** flag (`rustlings --manual-run`) to manually rerun the current exercise by entering `r` or `run` in the watch mode.
|
||||
>
|
||||
> Please [report the issue](https://github.com/rust-lang/rustlings/issues/new) with some information about your operating system and whether you run Rustlings in a container or virtual machine (e.g. WSL).
|
||||
|
||||
```bash
|
||||
rustlings run
|
||||
```
|
||||
</details>
|
||||
|
||||
In case you get stuck, you can run the following command to get a hint for your exercise:
|
||||
### Exercise List
|
||||
|
||||
```bash
|
||||
rustlings hint EXERCISE_NAME
|
||||
```
|
||||
In the [watch mode](#watch-mode) (after launching `rustlings`), you can enter `l` or `list` to open the interactive exercise list.
|
||||
|
||||
You can also get the hint for the next pending exercise with the following command:
|
||||
The list allows you to…
|
||||
|
||||
```bash
|
||||
rustlings hint
|
||||
```
|
||||
- See the status of all exercises (done or pending)
|
||||
- `c`: Continue at another exercise (temporarily skip some exercises or go back to a previous one)
|
||||
- `r`: Reset status and file of an exercise (you need to _reload/reopen_ its file in your editor afterwards)
|
||||
|
||||
See the footer of the list for all possible keys.
|
||||
|
||||
## Continuing On
|
||||
|
||||
|
@ -99,25 +110,15 @@ Continue practicing your Rust skills by building your own projects, contributing
|
|||
|
||||
## Uninstalling Rustlings
|
||||
|
||||
If you want to remove Rustlings from your system, there are two steps.
|
||||
|
||||
1️⃣ Remove the `rustlings` directory that was created by `rustlings init`:
|
||||
|
||||
```bash
|
||||
rm -r rustlings
|
||||
```
|
||||
|
||||
2️⃣ Run `cargo uninstall` to remove the `rustlings` binary:
|
||||
If you want to remove Rustlings from your system, run the following command:
|
||||
|
||||
```bash
|
||||
cargo uninstall rustlings
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md).
|
||||
See [CONTRIBUTING.md](https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md) 🔗
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
dev/Cargo.toml
|
|
@ -16,7 +16,7 @@ bin = [
|
|||
{ name = "if1", path = "../exercises/03_if/if1.rs" },
|
||||
{ name = "if2", path = "../exercises/03_if/if2.rs" },
|
||||
{ name = "if3", path = "../exercises/03_if/if3.rs" },
|
||||
{ name = "quiz1", path = "../exercises/quiz1.rs" },
|
||||
{ name = "quiz1", path = "../exercises/quizzes/quiz1.rs" },
|
||||
{ name = "primitive_types1", path = "../exercises/04_primitive_types/primitive_types1.rs" },
|
||||
{ name = "primitive_types2", path = "../exercises/04_primitive_types/primitive_types2.rs" },
|
||||
{ name = "primitive_types3", path = "../exercises/04_primitive_types/primitive_types3.rs" },
|
||||
|
@ -47,7 +47,7 @@ bin = [
|
|||
{ name = "hashmaps1", path = "../exercises/11_hashmaps/hashmaps1.rs" },
|
||||
{ name = "hashmaps2", path = "../exercises/11_hashmaps/hashmaps2.rs" },
|
||||
{ name = "hashmaps3", path = "../exercises/11_hashmaps/hashmaps3.rs" },
|
||||
{ name = "quiz2", path = "../exercises/quiz2.rs" },
|
||||
{ name = "quiz2", path = "../exercises/quizzes/quiz2.rs" },
|
||||
{ name = "options1", path = "../exercises/12_options/options1.rs" },
|
||||
{ name = "options2", path = "../exercises/12_options/options2.rs" },
|
||||
{ name = "options3", path = "../exercises/12_options/options3.rs" },
|
||||
|
@ -64,7 +64,7 @@ bin = [
|
|||
{ name = "traits3", path = "../exercises/15_traits/traits3.rs" },
|
||||
{ name = "traits4", path = "../exercises/15_traits/traits4.rs" },
|
||||
{ name = "traits5", path = "../exercises/15_traits/traits5.rs" },
|
||||
{ name = "quiz3", path = "../exercises/quiz3.rs" },
|
||||
{ name = "quiz3", path = "../exercises/quizzes/quiz3.rs" },
|
||||
{ name = "lifetimes1", path = "../exercises/16_lifetimes/lifetimes1.rs" },
|
||||
{ name = "lifetimes2", path = "../exercises/16_lifetimes/lifetimes2.rs" },
|
||||
{ name = "lifetimes3", path = "../exercises/16_lifetimes/lifetimes3.rs" },
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Error out if any command fails
|
||||
set -e
|
||||
|
||||
cargo run -- dev check
|
||||
typos
|
||||
cargo outdated -w --exit-code 1
|
||||
cargo test --workspace --all-targets
|
|
@ -6,6 +6,10 @@ authors.workspace = true
|
|||
repository.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
include = [
|
||||
"/src/",
|
||||
"/info.toml",
|
||||
]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../info.toml
|
|
@ -15,7 +15,7 @@ struct InfoFile {
|
|||
|
||||
#[proc_macro]
|
||||
pub fn include_files(_: TokenStream) -> TokenStream {
|
||||
let exercises = toml_edit::de::from_str::<InfoFile>(include_str!("../../info.toml"))
|
||||
let exercises = toml_edit::de::from_str::<InfoFile>(include_str!("../info.toml"))
|
||||
.expect("Failed to parse `info.toml`")
|
||||
.exercises;
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ pub fn check() -> Result<()> {
|
|||
if DEBUG_PROFILE {
|
||||
check_cargo_toml(
|
||||
&info_file.exercises,
|
||||
include_str!("../../dev/Cargo.toml"),
|
||||
include_str!("../../dev-Cargo.toml"),
|
||||
b"../",
|
||||
)?;
|
||||
} else {
|
||||
|
|
|
@ -29,7 +29,7 @@ pub fn update() -> Result<()> {
|
|||
if DEBUG_PROFILE {
|
||||
update_cargo_toml(
|
||||
&info_file.exercises,
|
||||
include_str!("../../dev/Cargo.toml"),
|
||||
include_str!("../../dev-Cargo.toml"),
|
||||
b"../",
|
||||
"dev/Cargo.toml",
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ pub fn init() -> Result<()> {
|
|||
.init_exercises_dir(&info_file.exercises)
|
||||
.context("Failed to initialize the `rustlings/exercises` directory")?;
|
||||
|
||||
let current_cargo_toml = include_str!("../dev/Cargo.toml");
|
||||
let current_cargo_toml = include_str!("../dev-Cargo.toml");
|
||||
// Skip the first line (comment).
|
||||
let newline_ind = current_cargo_toml
|
||||
.as_bytes()
|
||||
|
|
Loading…
Reference in New Issue