1
0
mirror of https://github.com/rust-lang/rustlings.git synced 2025-12-26 00:11:49 +02:00

Compare commits

..

28 Commits
2.2.1 ... 3.0.0

Author SHA1 Message Date
mokou
2ff3f7ae13 3.0.0 2020-04-12 00:01:08 +02:00
fmoko
2b80f6ed41 chore: Remove duplicate option1 exercise 2020-04-11 17:27:10 +02:00
Rohan Jain
3ab084a421 fix(run): compile clippy exercise files
Additionally to running clippy, also compile the exercise file so that
`rustling run clippy1` works after a successful completion of the
exercise.

closes #291

Signed-off-by: Rohan Jain <crodjer@gmail.com>
2020-04-11 08:58:23 +02:00
mokou
495174ff7c chore: remove travis ci
And add a buildkite build status badge
2020-04-08 12:27:28 +02:00
mokou
b049fa2c84 feat(ci): add buildkite config 2020-04-08 12:08:37 +02:00
fmoko
052f0aa7d4 Merge pull request #292 from Tuxified/patch-1
Remove duplicate not done comment
2020-04-08 11:23:49 +02:00
Tonći Galić
60393999b8 remove bottom comment instead of top 2020-04-08 11:00:11 +02:00
Roberto Vidal
b3a3351e8e fix: revert primitive_types4 (#296) 2020-04-08 10:42:35 +02:00
Sanjay K
86b5c08b9b feat: Add Option2 exercise (#290)
* added option2

* changed up the exercise, modified the help section

* Update exercises/option/option2.rs

Co-Authored-By: fmoko <mokou@posteo.net>

* Update exercises/option/option2.rs

Co-Authored-By: fmoko <mokou@posteo.net>

* Update exercises/option/option2.rs

Co-Authored-By: fmoko <mokou@posteo.net>

Co-authored-by: fmoko <mokou@posteo.net>
2020-04-07 20:16:10 +02:00
Tonći Galić
dab90f7b91 Remove duplicate not done comment
As indicated in #259 , I found it confusing to have 2 comments as the code wouldn't compile unless I solved both issues (I used the script from #281 to remove a comment and use `:wn` to go to next exercise, hence this tripped me).
2020-04-07 17:00:45 +02:00
fmoko
71d31256a6 Merge pull request #278 from jrvidal/output-mode
feature: adds "output" mode, resolves #270
2020-04-07 11:26:48 +02:00
Roberto Vidal
3b6d5c3aaa feature: makes "compile" exercise print output, resolves #270
When running "compile"-mode exercises in interactive `verify` mode,
we print their output when we prompt the learner if they want to
continue. This improves the "experimentation" experience, since
trying different things does produce a visible change.
2020-04-06 16:17:14 +02:00
fmoko
7ce42941ea Merge pull request #282 from sanjaykdragon/master
feat: added option exercise
2020-04-05 15:58:09 +02:00
Sanjay K
3f8171475c updated info.toml 2020-04-05 09:45:07 -04:00
fmoko
b135b589e0 Merge pull request #280 from sjmann/generics-exercises
feat: added generics exercises
2020-04-05 14:40:34 +02:00
Sanjay K
05ca3d77f7 Merge branch 'master' of https://github.com/sanjaykdragon/rustlings 2020-04-02 08:41:14 -04:00
Sanjay K
6deee7e3e9 fixed spacing 2020-04-02 08:40:59 -04:00
fmoko
9dc404077a Merge pull request #288 from vjousse/fix-traits-doc
chore(TRAITS1): don't hardcode documentation version
2020-03-26 21:16:52 +01:00
Vincent Jousse
30e6af6069 Don't hardcode documentation version for traits 2020-03-26 15:22:22 +01:00
Sanjay K
9788496a85 Update option1.rs 2020-03-11 13:44:41 -04:00
Sanjay K
6d3a412d47 Update option1.rs 2020-03-11 13:44:10 -04:00
bors
700b236f4d Auto merge of #284 - sl4m:update-from-into-ex, r=fmoko
Adds additional test to meet exercise rules

This PR adds an additional test to meet this exercise [rule](https://github.com/rust-lang/rustlings/blob/master/exercises/conversions/from_into.rs#L33).
2020-03-11 15:06:23 +00:00
skim
bc22ec382f adds additional test to meet exercise rules 2020-03-11 07:58:04 -07:00
Sanjay K
135e5d47a7 feat: added excercise for option 2020-03-05 15:52:54 -05:00
sjmann
0f8001ea44 add I AM NOT DONE comments 2020-02-28 00:31:55 +00:00
sjmann
5b6e23c323 removed artifact from manual testing 2020-02-28 00:29:30 +00:00
sjmann
29b30ec946 Merge branch 'master' of https://github.com/sjmann/rustlings into generics-exercises 2020-02-28 00:19:45 +00:00
sjmann
76be5e4e99 feat: added new exercises for generics 2020-02-28 00:09:08 +00:00
19 changed files with 325 additions and 59 deletions

View File

@@ -1,11 +0,0 @@
language: rust
rust:
- stable
- beta
- nightly
script: cargo test --verbose
matrix:
allow_failures:
- rust: nightly
fast_finish: true
cache: cargo

View File

@@ -1,3 +1,26 @@
<a name="3.0.0"></a>
## 3.0.0 (2020-04-11)
#### Breaking Changes
* make "compile" exercises print output (#278) ([3b6d5c](https://github.com/fmoko/rustlings/commit/3b6d5c3aaa27a242a832799eb66e96897d26fde3))
#### Bug Fixes
* **primitive_types:** revert primitive_types4 (#296) ([b3a3351e](https://github.com/rust-lang/rustlings/commit/b3a3351e8e6a0bdee07077d7b0382953821649ae))
* **run:** compile clippy exercise files (#295) ([3ab084a4](https://github.com/rust-lang/rustlings/commit/3ab084a421c0f140ae83bf1fc3f47b39342e7373))
* **conversions:**
* add additional test to meet exercise rules (#284) ([bc22ec3](https://github.com/fmoko/rustlings/commit/bc22ec382f843347333ef1301fc1bad773657f38))
* remove duplicate not done comment (#292) ([dab90f](https://github.com/fmoko/rustlings/commit/dab90f7b91a6000fe874e3d664f244048e5fa342))
* don't hardcode documentation version for traits (#288) ([30e6af](https://github.com/fmoko/rustlings/commit/30e6af60690c326fb5d3a9b7335f35c69c09137d))
#### Features
* add Option2 exercise (#290) ([86b5c08b](https://github.com/rust-lang/rustlings/commit/86b5c08b9bea1576127a7c5f599f5752072c087d))
* add excercise for option (#282) ([135e5d47](https://github.com/rust-lang/rustlings/commit/135e5d47a7c395aece6f6022117fb20c82f2d3d4))
* add new exercises for generics (#280) ([76be5e4e](https://github.com/rust-lang/rustlings/commit/76be5e4e991160f5fd9093f03ee2ba260e8f7229))
* **ci:** add buildkite config ([b049fa2c](https://github.com/rust-lang/rustlings/commit/b049fa2c84dba0f0c8906ac44e28fd45fba51a71))
<a name="2.2.1"></a>
### 2.2.1 (2020-02-27)

2
Cargo.lock generated
View File

@@ -592,7 +592,7 @@ dependencies = [
[[package]]
name = "rustlings"
version = "2.2.0"
version = "2.2.1"
dependencies = [
"assert_cmd 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,7 +1,7 @@
[package]
name = "rustlings"
version = "2.2.1"
authors = ["Marisa <mokou@posteo.de>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com"]
version = "3.0.0"
authors = ["Marisa <mokou@posteo.de>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com>"]
edition = "2018"
[dependencies]

View File

@@ -1,6 +1,6 @@
![crab pet](https://i.imgur.com/LbZJgmm.gif)
# rustlings 🦀❤️
# rustlings 🦀❤️ [![Build status](https://badge.buildkite.com/7af93d81dc522c67a1ec8e33ff5705861b1cb36360b774807f.svg)](https://buildkite.com/mokou/rustlings)
Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages!
@@ -54,7 +54,7 @@ Basically: Clone the repository, checkout to the latest tag, run `cargo install`
```bash
git clone https://github.com/rust-lang/rustlings
cd rustlings
git checkout tags/2.2.1 # or whatever the latest version is (find out at https://github.com/rust-lang/rustlings/releases/latest)
git checkout tags/3.0.0 # or whatever the latest version is (find out at https://github.com/rust-lang/rustlings/releases/latest)
cargo install --force --path .
```

5
buildkite.yml Normal file
View File

@@ -0,0 +1,5 @@
steps:
- label: "Test with stable"
command: rustup run stable cargo test
- label: "Test with beta"
command: rustup run beta cargo test

View File

@@ -9,7 +9,6 @@ fn byte_counter<T>(arg: T) -> usize {
arg.as_ref().as_bytes().len()
}
// I AM NOT DONE
// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T>(arg: T) -> usize {

View File

@@ -70,4 +70,11 @@ mod tests {
assert_eq!(p.name, "Mark");
assert_eq!(p.age, 20);
}
#[test]
fn test_bad_age() {
// Test that "Mark.twenty" will return the default person due to an error in parsing age
let p = Person::from("Mark,twenty");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
}

View File

@@ -0,0 +1,7 @@
### Generics
In this section you'll learn about saving yourself many lines of code with generics!
### Book Sections
- [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html)

View File

@@ -0,0 +1,10 @@
// This shopping list program isn't compiling!
// Use your knowledge of generics to fix it.
// I AM NOT DONE
fn main() {
let mut shopping_list: Vec<?> = Vec::new();
shopping_list.push("milk");
}

View File

@@ -0,0 +1,30 @@
// This powerful wrapper provides the ability to store a positive integer value.
// Rewrite it using generics so that it supports wrapping ANY type.
// I AM NOT DONE
struct Wrapper<u32> {
value: u32
}
impl<u32> Wrapper<u32> {
pub fn new(value: u32) -> Self {
Wrapper { value }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_u32_in_wrapper() {
assert_eq!(Wrapper::new(42).value, 42);
}
#[test]
fn store_str_in_wrapper() {
// TODO: Delete this assert and uncomment the one below once you have finished the exercise.
assert!(false);
// assert_eq!(Wrapper::new("Foo").value, "Foo");
}
}

View File

@@ -0,0 +1,46 @@
// An imaginary magical school has a new report card generation system written in rust!
// Currently the system only supports creating report cards where the student's grade
// is represented numerically (e.g. 1.0 -> 5.5). However, the school also issues alphabetical grades
// (A+ -> F-) and needs to be able to print both types of report card!
// Make the necessary code changes to support alphabetical report cards, thereby making the second
// test pass.
// I AM NOT DONE
pub struct ReportCard {
pub grade: f32,
pub student_name: String,
pub student_age: u8,
}
impl ReportCard {
pub fn print(&self) -> String {
format!("{} ({}) - achieved a grade of {}", &self.student_name, &self.student_age, &self.grade)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generate_numeric_report_card() {
let report_card = ReportCard {
grade: 2.1,
student_name: "Tom Wriggle".to_string(),
student_age: 12,
};
assert_eq!(report_card.print(), "Tom Wriggle (12) - achieved a grade of 2.1");
}
#[test]
fn generate_alphabetic_report_card() {
// TODO: Make sure to change the grade here after you finish the exercise.
let report_card = ReportCard {
grade: 2.1,
student_name: "Gary Plotter".to_string(),
student_age: 11,
};
assert_eq!(report_card.print(), "Gary Plotter (11) - achieved a grade of A+");
}
}

View File

@@ -0,0 +1,9 @@
### Option
#### Book Sections
To learn about Option<T>, check out these links:
- [Option Enum Format](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-enum-definitions)
- [Option Module Documentation](https://doc.rust-lang.org/std/option/)
- [Option Enum Documentation](https://doc.rust-lang.org/std/option/enum.Option.html)

View File

@@ -0,0 +1,23 @@
// option1.rs
// Make me compile! Execute `rustlings hint option1` for hints
// I AM NOT DONE
// you can modify anything EXCEPT for this function's sig
fn print_number(maybe_number: Option<u16>) {
println!("printing: {}", maybe_number.unwrap());
}
fn main() {
print_number(13);
print_number(99);
let mut numbers: [Option<u16>; 5];
for iter in 0..5 {
let number_to_add: u16 = {
((iter * 5) + 2) / (4 * 16)
};
numbers[iter] = number_to_add;
}
}

View File

@@ -0,0 +1,25 @@
// option2.rs
// Make me compile! Execute `rustlings hint option2` for hints
// I AM NOT DONE
fn main() {
let optional_value = Some(String::from("rustlings"));
// Make this an if let statement whose value is "Some" type
value = optional_value {
println!("the value of optional value is: {}", value);
} else {
println!("The optional value doesn't contain anything!");
}
let mut optional_values_vec: Vec<Option<i8>> = Vec::new();
for x in 1..10 {
optional_values_vec.push(Some(x));
}
// make this a while let statement - remember that vector.pop also adds another layer of Option<T>
// You can stack `Option<T>`'s into while let and if let
value = optional_values_vec.pop() {
println!("current value: {}", value);
}
}

View File

@@ -511,14 +511,32 @@ https://doc.rust-lang.org/std/result/#results-must-be-used"""
[[exercises]]
name = "option1"
path = "exercises/error_handling/option1.rs"
mode = "test"
path = "exercises/option/option1.rs"
mode = "compile"
hint = """
Try using a `match` statement where the arms are `Some(thing)` and `None`.
Or set a default value to print out if you get `None` by using the
function `unwrap_or`.
Or use an `if let` statement on the result of `pop()` to both destructure
a `Some` value and only print out something if we have a value!"""
Check out some functions of Option:
is_some
is_none
unwrap
and:
pattern matching
"""
[[exercises]]
name = "option2"
path = "exercises/option/option2.rs"
mode = "compile"
hint = """
check out:
https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html
https://doc.rust-lang.org/rust-by-example/flow_control/while_let.html
Remember that Options can be stacked in if let and while let.
For example: Some(Some(variable)) = variable2
"""
[[exercises]]
name = "result1"
@@ -610,7 +628,7 @@ path = "exercises/traits/traits1.rs"
mode = "test"
hint = """
A discussion about Traits in Rust can be found at:
https://doc.rust-lang.org/1.30.0/book/second-edition/ch10-02-traits.html
https://doc.rust-lang.org/book/ch10-02-traits.html
"""
[[exercises]]
@@ -624,6 +642,38 @@ Try mutating the incoming string vector.
Vectors provide suitable methods for adding an element at the end. See
the documentation at: https://doc.rust-lang.org/std/vec/struct.Vec.html"""
# Generics
[[exercises]]
name = "generics1"
path = "exercises/generics/generics1.rs"
mode = "compile"
hint = """
Vectors in rust make use of generics to create dynamically sized arrays of any type.
You need to tell the compiler what type we are pushing onto this vector."""
[[exercises]]
name = "generics2"
path = "exercises/generics/generics2.rs"
mode = "test"
hint = """
Think carefully about what we need to do here. Currently we are wrapping only values of
type 'u32'. Maybe we need to update the explicit references to this data type somehow?
"""
[[exercises]]
name = "generics3"
path = "exercises/generics/generics3.rs"
mode = "test"
hint = """
To find the best solution to this challenge you're going to need to think back to your
knowledge of traits, specifically Trait Bound Syntax - you may also need this: "use std::fmt::Display;"
This is definitely harder than the last two exercises! You need to think about not only making the
ReportCard struct generic, but also the correct property - you will need to change the implementation
of the struct slightly too...you can do it!
"""
# THREADS
[[exercises]]
@@ -701,4 +751,4 @@ path = "exercises/conversions/from_str.rs"
mode = "test"
hint = """
If you've already solved try_from_into.rs, then this is almost a copy-paste.
Otherwise, go ahead and solve try_from_into.rs first."""
Otherwise, go ahead and solve try_from_into.rs first."""

View File

@@ -98,6 +98,15 @@ path = "{}.rs""#,
);
fs::write(CLIPPY_CARGO_TOML_PATH, cargo_toml)
.expect("Failed to write 📎 Clippy 📎 Cargo.toml file.");
// To support the ability to run the clipy exercises, build
// an executable, in addition to running clippy. With a
// compilation failure, this would silently fail. But we expect
// clippy to reflect the same failure while compiling later.
Command::new("rustc")
.args(&[self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS)
.output()
.expect("Failed to compile!");
// Due to an issue with Clippy, a cargo clean is required to catch all lints.
// See https://github.com/rust-lang/rust-clippy/issues/2604
// This is already fixed on master branch. See this issue to track merging into Cargo:

View File

@@ -1,4 +1,4 @@
use crate::exercise::{Exercise, Mode, State};
use crate::exercise::{CompiledExercise, Exercise, Mode, State};
use console::style;
use indicatif::ProgressBar;
@@ -6,7 +6,7 @@ pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<()
for exercise in start_at {
let compile_result = match exercise.mode {
Mode::Test => compile_and_test(&exercise, RunMode::Interactive),
Mode::Compile => compile_only(&exercise),
Mode::Compile => compile_and_run_interactively(&exercise),
Mode::Clippy => compile_only(&exercise),
};
if !compile_result.unwrap_or(false) {
@@ -30,23 +30,37 @@ fn compile_only(exercise: &Exercise) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {}...", exercise).as_str());
progress_bar.enable_steady_tick(100);
let compilation_result = exercise.compile();
let _ = compile(&exercise, &progress_bar)?;
progress_bar.finish_and_clear();
match compilation_result {
Ok(_) => {
success!("Successfully compiled {}!", exercise);
Ok(prompt_for_completion(&exercise))
}
success!("Successfully compiled {}!", exercise);
Ok(prompt_for_completion(&exercise, None))
}
fn compile_and_run_interactively(exercise: &Exercise) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {}...", exercise).as_str());
progress_bar.enable_steady_tick(100);
let compilation = compile(&exercise, &progress_bar)?;
progress_bar.set_message(format!("Running {}...", exercise).as_str());
let result = compilation.run();
progress_bar.finish_and_clear();
let output = match result {
Ok(output) => output,
Err(output) => {
warn!(
"Compilation of {} failed! Compiler error message:\n",
exercise
);
println!("{}", output.stderr);
Err(())
warn!("Ran {} with errors", exercise);
println!("{}", output.stdout);
return Err(());
}
}
};
success!("Successfully ran {}!", exercise);
Ok(prompt_for_completion(&exercise, Some(output.stdout)))
}
fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result<bool, ()> {
@@ -54,28 +68,15 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result<bool, ()>
progress_bar.set_message(format!("Testing {}...", exercise).as_str());
progress_bar.enable_steady_tick(100);
let compilation_result = exercise.compile();
let compilation = match compilation_result {
Ok(compilation) => compilation,
Err(output) => {
progress_bar.finish_and_clear();
warn!(
"Compiling of {} failed! Please try again. Here's the output:",
exercise
);
println!("{}", output.stderr);
return Err(());
}
};
let compilation = compile(exercise, &progress_bar)?;
let result = compilation.run();
progress_bar.finish_and_clear();
match result {
Ok(_) => {
success!("Successfully tested {}", &exercise);
if let RunMode::Interactive = run_mode {
Ok(prompt_for_completion(&exercise))
Ok(prompt_for_completion(&exercise, None))
} else {
Ok(true)
}
@@ -91,7 +92,27 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result<bool, ()>
}
}
fn prompt_for_completion(exercise: &Exercise) -> bool {
fn compile<'a, 'b>(
exercise: &'a Exercise,
progress_bar: &'b ProgressBar,
) -> Result<CompiledExercise<'a>, ()> {
let compilation_result = exercise.compile();
match compilation_result {
Ok(compilation) => Ok(compilation),
Err(output) => {
progress_bar.finish_and_clear();
warn!(
"Compiling of {} failed! Please try again. Here's the output:",
exercise
);
println!("{}", output.stderr);
Err(())
}
}
}
fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) -> bool {
let context = match exercise.state() {
State::Done => return true,
State::Pending(context) => context,
@@ -106,6 +127,15 @@ fn prompt_for_completion(exercise: &Exercise) -> bool {
println!("");
println!("🎉 🎉 {} 🎉 🎉", success_msg);
println!("");
if let Some(output) = prompt_output {
println!("Output:");
println!("{}", separator());
println!("{}", output);
println!("{}", separator());
println!("");
}
println!("You can keep working on this exercise,");
println!(
"or jump into the next one by removing the {} comment:",
@@ -129,3 +159,7 @@ fn prompt_for_completion(exercise: &Exercise) -> bool {
false
}
fn separator() -> console::StyledObject<&'static str> {
style("====================").bold()
}

View File

@@ -31,7 +31,7 @@ fn verify_all_success() {
}
#[test]
fn verify_all_failure() {
fn verify_fails_if_some_fails() {
Command::cargo_bin("rustlings")
.unwrap()
.arg("v")