Merge branch 'main' into chore/update-hints

This commit is contained in:
liv 2023-09-04 14:34:13 +02:00 committed by GitHub
commit 0aa9418736
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 763 additions and 370 deletions

View File

@ -2235,6 +2235,114 @@
"contributions": [ "contributions": [
"content" "content"
] ]
},
{
"login": "johnDeSilencio",
"name": "Nicholas R. Smith",
"avatar_url": "https://avatars.githubusercontent.com/u/20136554?v=4",
"profile": "https://johndesilencio.me",
"contributions": [
"code"
]
},
{
"login": "alexfertel",
"name": "Alexander González",
"avatar_url": "https://avatars.githubusercontent.com/u/22298999?v=4",
"profile": "https://alexfertel.me",
"contributions": [
"content"
]
},
{
"login": "softarn",
"name": "Marcus Höjvall",
"avatar_url": "https://avatars.githubusercontent.com/u/517619?v=4",
"profile": "https://github.com/softarn",
"contributions": [
"content"
]
},
{
"login": "barlevalon",
"name": "Alon Hearter",
"avatar_url": "https://avatars.githubusercontent.com/u/3397911?v=4",
"profile": "https://github.com/barlevalon",
"contributions": [
"content"
]
},
{
"login": "shirts",
"name": "shirts",
"avatar_url": "https://avatars.githubusercontent.com/u/4952151?v=4",
"profile": "https://github.com/shirts",
"contributions": [
"content"
]
},
{
"login": "eLVas",
"name": "Ivan Vasiunyk",
"avatar_url": "https://avatars.githubusercontent.com/u/6797156?v=4",
"profile": "https://github.com/eLVas",
"contributions": [
"content"
]
},
{
"login": "mo8it",
"name": "Mo",
"avatar_url": "https://avatars.githubusercontent.com/u/76752051?v=4",
"profile": "https://mo8it.com",
"contributions": [
"code"
]
},
{
"login": "x10an14",
"name": "x10an14",
"avatar_url": "https://avatars.githubusercontent.com/u/710608?v=4",
"profile": "https://github.com/x10an14",
"contributions": [
"infra"
]
},
{
"login": "gabay",
"name": "Roi Gabay",
"avatar_url": "https://avatars.githubusercontent.com/u/5773610?v=4",
"profile": "https://github.com/gabay",
"contributions": [
"content"
]
},
{
"login": "mkovaxx",
"name": "Máté Kovács",
"avatar_url": "https://avatars.githubusercontent.com/u/481354?v=4",
"profile": "https://github.com/mkovaxx",
"contributions": [
"content"
]
},
{
"login": "szabgab",
"name": "Gábor Szabó",
"avatar_url": "https://avatars.githubusercontent.com/u/48833?v=4",
"profile": "https://szabgab.com/",
"contributions": [
"content"
]
},
{
"login": "yamila-moreno",
"name": "Yamila Moreno",
"avatar_url": "https://avatars.githubusercontent.com/u/3340793?v=4",
"profile": "https://moduslaborandi.net",
"contributions": [
"content"
]
} }
], ],
"contributorsPerLine": 8, "contributorsPerLine": 8,

4
.envrc Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Automatically Load nix devShell w/dotenv
use flake

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ rust-project.json
*.iml *.iml
*.o *.o
public/ public/
.direnv/
# Local Netlify folder # Local Netlify folder
.netlify .netlify

View File

@ -316,6 +316,22 @@ authors.
<td align="center" valign="top" width="12.5%"><a href="https://anishchhetri.com.np"><img src="https://avatars.githubusercontent.com/u/98446102?v=4?s=100" width="100px;" alt="Anish"/><br /><sub><b>Anish</b></sub></a><br /><a href="#content-novanish" title="Content">🖋</a></td> <td align="center" valign="top" width="12.5%"><a href="https://anishchhetri.com.np"><img src="https://avatars.githubusercontent.com/u/98446102?v=4?s=100" width="100px;" alt="Anish"/><br /><sub><b>Anish</b></sub></a><br /><a href="#content-novanish" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/vnprc"><img src="https://avatars.githubusercontent.com/u/9425366?v=4?s=100" width="100px;" alt="vnprc"/><br /><sub><b>vnprc</b></sub></a><br /><a href="#content-vnprc" title="Content">🖋</a></td> <td align="center" valign="top" width="12.5%"><a href="https://github.com/vnprc"><img src="https://avatars.githubusercontent.com/u/9425366?v=4?s=100" width="100px;" alt="vnprc"/><br /><sub><b>vnprc</b></sub></a><br /><a href="#content-vnprc" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://androecia.net"><img src="https://avatars.githubusercontent.com/u/61999256?v=4?s=100" width="100px;" alt="Joshua Carlson"/><br /><sub><b>Joshua Carlson</b></sub></a><br /><a href="#content-jrcarl624" title="Content">🖋</a></td> <td align="center" valign="top" width="12.5%"><a href="http://androecia.net"><img src="https://avatars.githubusercontent.com/u/61999256?v=4?s=100" width="100px;" alt="Joshua Carlson"/><br /><sub><b>Joshua Carlson</b></sub></a><br /><a href="#content-jrcarl624" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://johndesilencio.me"><img src="https://avatars.githubusercontent.com/u/20136554?v=4?s=100" width="100px;" alt="Nicholas R. Smith"/><br /><sub><b>Nicholas R. Smith</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=johnDeSilencio" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://alexfertel.me"><img src="https://avatars.githubusercontent.com/u/22298999?v=4?s=100" width="100px;" alt="Alexander González"/><br /><sub><b>Alexander González</b></sub></a><br /><a href="#content-alexfertel" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/softarn"><img src="https://avatars.githubusercontent.com/u/517619?v=4?s=100" width="100px;" alt="Marcus Höjvall"/><br /><sub><b>Marcus Höjvall</b></sub></a><br /><a href="#content-softarn" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/barlevalon"><img src="https://avatars.githubusercontent.com/u/3397911?v=4?s=100" width="100px;" alt="Alon Hearter"/><br /><sub><b>Alon Hearter</b></sub></a><br /><a href="#content-barlevalon" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/shirts"><img src="https://avatars.githubusercontent.com/u/4952151?v=4?s=100" width="100px;" alt="shirts"/><br /><sub><b>shirts</b></sub></a><br /><a href="#content-shirts" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/eLVas"><img src="https://avatars.githubusercontent.com/u/6797156?v=4?s=100" width="100px;" alt="Ivan Vasiunyk"/><br /><sub><b>Ivan Vasiunyk</b></sub></a><br /><a href="#content-eLVas" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://mo8it.com"><img src="https://avatars.githubusercontent.com/u/76752051?v=4?s=100" width="100px;" alt="Mo"/><br /><sub><b>Mo</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=mo8it" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/x10an14"><img src="https://avatars.githubusercontent.com/u/710608?v=4?s=100" width="100px;" alt="x10an14"/><br /><sub><b>x10an14</b></sub></a><br /><a href="#infra-x10an14" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gabay"><img src="https://avatars.githubusercontent.com/u/5773610?v=4?s=100" width="100px;" alt="Roi Gabay"/><br /><sub><b>Roi Gabay</b></sub></a><br /><a href="#content-gabay" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/mkovaxx"><img src="https://avatars.githubusercontent.com/u/481354?v=4?s=100" width="100px;" alt="Máté Kovács"/><br /><sub><b>Máté Kovács</b></sub></a><br /><a href="#content-mkovaxx" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://szabgab.com/"><img src="https://avatars.githubusercontent.com/u/48833?v=4?s=100" width="100px;" alt="Gábor Szabó"/><br /><sub><b>Gábor Szabó</b></sub></a><br /><a href="#content-szabgab" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://moduslaborandi.net"><img src="https://avatars.githubusercontent.com/u/3340793?v=4?s=100" width="100px;" alt="Yamila Moreno"/><br /><sub><b>Yamila Moreno</b></sub></a><br /><a href="#content-yamila-moreno" title="Content">🖋</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

524
Cargo.lock generated
View File

@ -4,18 +4,66 @@ version = 3
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.20" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]] [[package]]
name = "argh" name = "anstream"
version = "0.1.10" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab257697eb9496bf75526f0217b5ed64636a9cfafa78b8365c71bd283fcef93e" checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea"
[[package]]
name = "anstyle-parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "anstyle-wincon"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
]
[[package]]
name = "argh"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
dependencies = [ dependencies = [
"argh_derive", "argh_derive",
"argh_shared", "argh_shared",
@ -23,32 +71,38 @@ dependencies = [
[[package]] [[package]]
name = "argh_derive" name = "argh_derive"
version = "0.1.10" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b382dbd3288e053331f03399e1db106c9fb0d8562ad62cb04859ae926f324fa6" checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
dependencies = [ dependencies = [
"argh_shared", "argh_shared",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn",
] ]
[[package]] [[package]]
name = "argh_shared" name = "argh_shared"
version = "0.1.10" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f" checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "assert_cmd" name = "assert_cmd"
version = "0.11.1" version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dc477793bd82ec39799b6f6b3df64938532fdf2ab0d49ef817eac65856a5a1e" checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6"
dependencies = [ dependencies = [
"escargot", "anstyle",
"bstr",
"doc-comment",
"predicates", "predicates",
"predicates-core", "predicates-core",
"predicates-tree", "predicates-tree",
"wait-timeout",
] ]
[[package]] [[package]]
@ -63,6 +117,17 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a"
dependencies = [
"memchr",
"regex-automata",
"serde",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.10" version = "0.1.10"
@ -76,23 +141,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "console" name = "clap"
version = "0.15.5" version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "console"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
dependencies = [ dependencies = [
"encode_unicode", "encode_unicode",
"lazy_static", "lazy_static",
"libc", "libc",
"unicode-width", "unicode-width",
"windows-sys 0.42.0", "windows-sys 0.45.0",
] ]
[[package]] [[package]]
name = "difference" name = "difflib"
version = "2.0.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]] [[package]]
name = "encode_unicode" name = "encode_unicode"
@ -101,34 +224,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "escargot" name = "equivalent"
version = "0.4.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ceb9adbf9874d5d028b5e4c5739d22b71988252b25c9c98fe7cf9738bee84597" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
dependencies = [
"lazy_static",
"log",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.20" version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall", "redox_syscall",
"windows-sys 0.45.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
name = "float-cmp" name = "float-cmp"
version = "0.8.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [ dependencies = [
"num-traits", "num-traits",
] ]
@ -175,24 +292,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]] [[package]]
name = "home" name = "hashbrown"
version = "0.5.4" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "home"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
dependencies = [ dependencies = [
"winapi 0.3.9", "windows-sys 0.48.0",
]
[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
"hashbrown",
] ]
[[package]] [[package]]
name = "indicatif" name = "indicatif"
version = "0.16.2" version = "0.17.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730"
dependencies = [ dependencies = [
"console", "console",
"lazy_static", "instant",
"number_prefix", "number_prefix",
"regex", "portable-atomic",
"unicode-width",
] ]
[[package]] [[package]]
@ -215,6 +355,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "iovec" name = "iovec"
version = "0.1.4" version = "0.1.4"
@ -225,10 +374,19 @@ dependencies = [
] ]
[[package]] [[package]]
name = "itoa" name = "itertools"
version = "1.0.6" version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "kernel32-sys" name = "kernel32-sys"
@ -254,24 +412,21 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.140" version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]] [[package]]
name = "mio" name = "mio"
@ -318,9 +473,9 @@ dependencies = [
[[package]] [[package]]
name = "net2" name = "net2"
version = "0.2.38" version = "0.2.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 0.1.10",
"libc", "libc",
@ -353,9 +508,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -367,13 +522,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]] [[package]]
name = "predicates" name = "portable-atomic"
version = "1.0.8" version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df" checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b"
[[package]]
name = "predicates"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9"
dependencies = [ dependencies = [
"difference", "anstyle",
"difflib",
"float-cmp", "float-cmp",
"itertools",
"normalize-line-endings", "normalize-line-endings",
"predicates-core", "predicates-core",
"regex", "regex",
@ -397,36 +560,48 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.53" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.26" version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.16" version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [ dependencies = [
"bitflags", "bitflags",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.7.2" version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c" checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -435,9 +610,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.29" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]] [[package]]
name = "rustlings" name = "rustlings"
@ -445,6 +620,7 @@ version = "5.5.1"
dependencies = [ dependencies = [
"argh", "argh",
"assert_cmd", "assert_cmd",
"clap",
"console", "console",
"glob", "glob",
"home", "home",
@ -459,9 +635,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.13" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -474,29 +650,29 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.158" version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.158" version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.8", "syn",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.94" version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -504,30 +680,34 @@ dependencies = [
] ]
[[package]] [[package]]
name = "slab" name = "serde_spanned"
version = "0.4.8" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
dependencies = [
"serde",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]] [[package]]
name = "syn" name = "strsim"
version = "1.0.109" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.8" version = "2.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -542,18 +722,43 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "unicode-ident" name = "toml_edit"
version = "1.0.8" version = "0.19.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
name = "unicode-ident"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@ -561,6 +766,21 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.3.3" version = "2.3.3"
@ -614,28 +834,22 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [ dependencies = [
"windows-targets", "windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -644,13 +858,28 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc", "windows_aarch64_msvc 0.42.2",
"windows_i686_gnu", "windows_i686_gnu 0.42.2",
"windows_i686_msvc", "windows_i686_msvc 0.42.2",
"windows_x86_64_gnu", "windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm", "windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc", "windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
] ]
[[package]] [[package]]
@ -659,42 +888,93 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "winnow"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "ws2_32-sys" name = "ws2_32-sys"
version = "0.2.1" version = "0.2.1"

View File

@ -10,21 +10,22 @@ edition = "2021"
[dependencies] [dependencies]
argh = "0.1" argh = "0.1"
indicatif = "0.16" indicatif = "0.17.6"
console = "0.15" console = "0.15"
notify = "4.0" notify = "4.0"
toml = "0.5" toml = "0.7.6"
regex = "1.5" regex = "1.5"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.81" serde_json = "1.0.81"
home = "0.5.3" home = "0.5.3"
glob = "0.3.0" glob = "0.3.0"
clap = { version = "4.4.0", features = ["derive"] }
[[bin]] [[bin]]
name = "rustlings" name = "rustlings"
path = "src/main.rs" path = "src/main.rs"
[dev-dependencies] [dev-dependencies]
assert_cmd = "0.11.0" assert_cmd = "2.0.12"
predicates = "1.0.1" predicates = "3.0.3"
glob = "0.3.0" glob = "0.3.0"

View File

@ -127,14 +127,14 @@ mod tests {
#[test] #[test]
fn test_trailing_comma() { fn test_trailing_comma() {
let p: Person = Person::from("Mike,32,"); let p: Person = Person::from("Mike,32,");
assert_eq!(p.name, "John"); assert_eq!(p.name, "Mike");
assert_eq!(p.age, 30); assert_eq!(p.age, 32);
} }
#[test] #[test]
fn test_trailing_comma_and_some_string() { fn test_trailing_comma_and_some_string() {
let p: Person = Person::from("Mike,32,man"); let p: Person = Person::from("Mike,32,man");
assert_eq!(p.name, "John"); assert_eq!(p.name, "Mike");
assert_eq!(p.age, 30); assert_eq!(p.age, 32);
} }
} }

View File

@ -3,7 +3,7 @@
// This function refuses to generate text to be printed on a nametag if you pass // This function refuses to generate text to be printed on a nametag if you pass
// it an empty string. It'd be nicer if it explained what the problem was, // it an empty string. It'd be nicer if it explained what the problem was,
// instead of just sometimes returning `None`. Thankfully, Rust has a similar // instead of just sometimes returning `None`. Thankfully, Rust has a similar
// construct to `Result` that can be used to express error conditions. Let's use // construct to `Option` that can be used to express error conditions. Let's use
// it! // it!
// //
// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a // Execute `rustlings hint errors1` or use the `hint` watch subcommand for a

View File

@ -9,9 +9,9 @@
// //
// Right now, this function isn't handling the error case at all (and isn't // Right now, this function isn't handling the error case at all (and isn't
// handling the success case properly either). What we want to do is: if we call // handling the success case properly either). What we want to do is: if we call
// the `parse` function on a string that is not a number, that function will // the `total_cost` function on a string that is not a number, that function
// return a `ParseIntError`, and in that case, we want to immediately return // will return a `ParseIntError`, and in that case, we want to immediately
// that error from our function and not try to multiply and add. // return that error from our function and not try to multiply and add.
// //
// There are at least two ways to implement this that are both correct-- but one // There are at least two ways to implement this that are both correct-- but one
// is a lot shorter! // is a lot shorter!

View File

@ -16,7 +16,7 @@ enum CreationError {
impl PositiveNonzeroInteger { impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
// Hmm...? Why is this only returning an Ok value? // Hmm... Why is this always returning an Ok value?
Ok(PositiveNonzeroInteger(value as u64)) Ok(PositiveNonzeroInteger(value as u64))
} }
} }

View File

@ -25,4 +25,9 @@ mod tests {
fn fortytwo_is_bigger_than_thirtytwo() { fn fortytwo_is_bigger_than_thirtytwo() {
assert_eq!(42, bigger(32, 42)); assert_eq!(42, bigger(32, 42));
} }
#[test]
fn equal_numbers() {
assert_eq!(42, bigger(42, 42));
}
} }

View File

@ -29,6 +29,7 @@ pub fn animal_habitat(animal: &str) -> &'static str {
habitat habitat
} }
// No test changes needed.
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -5,24 +5,19 @@
// I AM NOT DONE // I AM NOT DONE
#[test]
fn main() { fn main() {
let vec0 = Vec::new(); let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0); let vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); assert_eq!(vec1, vec![22, 44, 66, 88]);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
} }
fn fill_vec(vec: Vec<i32>) -> Vec<i32> { fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec; let vec = vec;
vec.push(22); vec.push(88);
vec.push(44);
vec.push(66);
vec vec
} }

View File

@ -1,32 +1,26 @@
// move_semantics2.rs // move_semantics2.rs
// //
// Expected output: // Make the test pass by finding a way to keep both Vecs separate!
// vec0 has length 3, with contents `[22, 44, 66]`
// vec1 has length 4, with contents `[22, 44, 66, 88]`
// //
// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand // Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand
// for a hint. // for a hint.
// I AM NOT DONE // I AM NOT DONE
#[test]
fn main() { fn main() {
let vec0 = Vec::new(); let vec0 = vec![22, 44, 66];
let mut vec1 = fill_vec(vec0); let mut vec1 = fill_vec(vec0);
println!("{} has length {}, with contents: `{:?}`", "vec0", vec0.len(), vec0); assert_eq!(vec0, vec![22, 44, 66]);
assert_eq!(vec1, vec![22, 44, 66, 88]);
vec1.push(88);
println!("{} has length {}, with contents `{:?}`", "vec1", vec1.len(), vec1);
} }
fn fill_vec(vec: Vec<i32>) -> Vec<i32> { fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec; let mut vec = vec;
vec.push(22); vec.push(88);
vec.push(44);
vec.push(66);
vec vec
} }

View File

@ -8,22 +8,17 @@
// I AM NOT DONE // I AM NOT DONE
#[test]
fn main() { fn main() {
let vec0 = Vec::new(); let vec0 = vec![22, 44, 66];
let mut vec1 = fill_vec(vec0); let mut vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); assert_eq!(vec1, vec![22, 44, 66, 88]);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
} }
fn fill_vec(vec: Vec<i32>) -> Vec<i32> { fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec.push(22); vec.push(88);
vec.push(44);
vec.push(66);
vec vec
} }

View File

@ -9,25 +9,21 @@
// I AM NOT DONE // I AM NOT DONE
#[test]
fn main() { fn main() {
let vec0 = Vec::new(); let vec0 = vec![22, 44, 66];
let mut vec1 = fill_vec(vec0); let mut vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); assert_eq!(vec1, vec![22, 44, 66, 88]);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
} }
// `fill_vec()` no longer takes `vec: Vec<i32>` as argument // `fill_vec()` no longer takes `vec: Vec<i32>` as argument - don't change this!
fn fill_vec() -> Vec<i32> { fn fill_vec() -> Vec<i32> {
// Instead, let's create and fill the Vec in here - how do you do that?
let mut vec = vec; let mut vec = vec;
vec.push(22); vec.push(88);
vec.push(44);
vec.push(66);
vec vec
} }

View File

@ -9,7 +9,7 @@
// - An apple costs 2 rustbucks. // - An apple costs 2 rustbucks.
// - If Mary buys more than 40 apples, each apple only costs 1 rustbuck! // - If Mary buys more than 40 apples, each apple only costs 1 rustbuck!
// Write a function that calculates the price of an order of apples given the // Write a function that calculates the price of an order of apples given the
// quantity bought. No hints this time! // quantity bought.
// //
// No hints this time ;) // No hints this time ;)

View File

@ -70,7 +70,7 @@ mod tests {
// case the call to `to_mut()` returns a reference to the same data as // case the call to `to_mut()` returns a reference to the same data as
// before. // before.
let slice = vec![-1, 0, 1]; let slice = vec![-1, 0, 1];
let mut input = Cow::from(slice); let mut input = Cow::from(slice).to_mut();
match abs_all(&mut input) { match abs_all(&mut input) {
// TODO // TODO
} }

View File

@ -13,13 +13,15 @@
struct Package { struct Package {
sender_country: String, sender_country: String,
recipient_country: String, recipient_country: String,
weight_in_grams: i32, weight_in_grams: u32,
} }
impl Package { impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package { fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Package {
if weight_in_grams <= 0 { if weight_in_grams < 10 {
panic!("Can not ship a weightless package.") // This is not how you should handle errors in Rust,
// but we will learn about error handling later.
panic!("Can not ship a package with weight below 10 grams.")
} else { } else {
Package { Package {
sender_country, sender_country,
@ -33,7 +35,7 @@ impl Package {
// Something goes here... // Something goes here...
} }
fn get_fees(&self, cents_per_gram: i32) -> ??? { fn get_fees(&self, cents_per_gram: u32) -> ??? {
// Something goes here... // Something goes here...
} }
} }
@ -48,7 +50,7 @@ mod tests {
let sender_country = String::from("Spain"); let sender_country = String::from("Spain");
let recipient_country = String::from("Austria"); let recipient_country = String::from("Austria");
Package::new(sender_country, recipient_country, -2210); Package::new(sender_country, recipient_country, 5);
} }
#[test] #[test]

View File

@ -25,6 +25,7 @@
version = "5.5.1"; version = "5.5.1";
buildInputs = cargoBuildInputs; buildInputs = cargoBuildInputs;
nativeBuildInputs = [pkgs.git];
src = with pkgs.lib; cleanSourceWith { src = with pkgs.lib; cleanSourceWith {
src = self; src = self;
@ -60,5 +61,18 @@
clippy clippy
] ++ cargoBuildInputs; ] ++ cargoBuildInputs;
}; };
apps = let
rustlings-app = {
type = "app";
program = "${rustlings}/bin/rustlings";
};
in {
default = rustlings-app;
rustlings = rustlings-app;
};
packages = {
inherit rustlings;
default = rustlings;
};
}); });
} }

View File

@ -22,8 +22,8 @@ name = "variables1"
path = "exercises/variables/variables1.rs" path = "exercises/variables/variables1.rs"
mode = "compile" mode = "compile"
hint = """ hint = """
The declaration on line 8 is missing a keyword that is needed in Rust The declaration in the first line in the main function is missing a keyword
to create a new variable binding.""" that is needed in Rust to create a new variable binding."""
[[exercises]] [[exercises]]
name = "variables2" name = "variables2"
@ -32,7 +32,7 @@ mode = "compile"
hint = """ hint = """
The compiler message is saying that Rust cannot infer the type that the The compiler message is saying that Rust cannot infer the type that the
variable binding `x` has with what is given here. variable binding `x` has with what is given here.
What happens if you annotate line 7 with a type annotation? What happens if you annotate the first line in the main function with a type annotation?
What if you give x a value? What if you give x a value?
What if you do both? What if you do both?
What type should x be, anyway? What type should x be, anyway?
@ -44,8 +44,9 @@ path = "exercises/variables/variables3.rs"
mode = "compile" mode = "compile"
hint = """ hint = """
Oops! In this exercise, we have a variable binding that we've created on Oops! In this exercise, we have a variable binding that we've created on
line 7, and we're trying to use it on line 8, but we haven't given it a in the first line in the main function, and we're trying to use it in the next line,
value. We can't print out something that isn't there; try giving x a value! but we haven't given it a value.
We can't print out something that isn't there; try giving x a value!
This is an error that can cause bugs that's very easy to make in any This is an error that can cause bugs that's very easy to make in any
programming language -- thankfully the Rust compiler has caught this for us!""" programming language -- thankfully the Rust compiler has caught this for us!"""
@ -123,8 +124,8 @@ name = "functions4"
path = "exercises/functions/functions4.rs" path = "exercises/functions/functions4.rs"
mode = "compile" mode = "compile"
hint = """ hint = """
The error message points to line 17 and says it expects a type after the The error message points to the function `sale_price` and says it expects a type
`->`. This is where the function's return type should be -- take a look at after the `->`. This is where the function's return type should be -- take a look at
the `is_even` function for an example! the `is_even` function for an example!
Also: Did you figure out that, technically, u32 would be the more fitting type Also: Did you figure out that, technically, u32 would be the more fitting type
@ -216,7 +217,7 @@ mode = "test"
hint = """ hint = """
Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book: Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book:
https://doc.rust-lang.org/book/ch04-03-slices.html https://doc.rust-lang.org/book/ch04-03-slices.html
and use the starting and ending indices of the items in the Array and use the starting and ending (plus one) indices of the items in the Array
that you want to end up in the slice. that you want to end up in the slice.
If you're curious why the first argument of `assert_eq!` does not If you're curious why the first argument of `assert_eq!` does not
@ -283,18 +284,19 @@ better. What do you think is the more commonly used pattern under Rust developer
[[exercises]] [[exercises]]
name = "move_semantics1" name = "move_semantics1"
path = "exercises/move_semantics/move_semantics1.rs" path = "exercises/move_semantics/move_semantics1.rs"
mode = "compile" mode = "test"
hint = """ hint = """
So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 13, So you've got the "cannot borrow immutable local variable `vec` as mutable" error on the line
right? The fix for this is going to be adding one keyword, and the addition is NOT on line 13 where we push an element to the vector, right?
where the error is. The fix for this is going to be adding one keyword, and the addition is NOT on the line where
we push to the vector (where the error is).
Also: Try accessing `vec0` after having called `fill_vec()`. See what happens!""" Also: Try accessing `vec0` after having called `fill_vec()`. See what happens!"""
[[exercises]] [[exercises]]
name = "move_semantics2" name = "move_semantics2"
path = "exercises/move_semantics/move_semantics2.rs" path = "exercises/move_semantics/move_semantics2.rs"
mode = "compile" mode = "test"
hint = """ hint = """
When running this exercise for the first time, you'll notice an error about When running this exercise for the first time, you'll notice an error about
"borrow of moved value". In Rust, when an argument is passed to a function and "borrow of moved value". In Rust, when an argument is passed to a function and
@ -307,16 +309,12 @@ Rust provides a couple of different ways to mitigate this issue, feel free to tr
2. Make `fill_vec` borrow its argument instead of taking ownership of it, 2. Make `fill_vec` borrow its argument instead of taking ownership of it,
and then copy the data within the function (`vec.clone()`) in order to return an owned and then copy the data within the function (`vec.clone()`) in order to return an owned
`Vec<i32>`. `Vec<i32>`.
3. Or, you could make `fill_vec` *mutably* borrow a reference to its argument (which will need to be
mutable), modify it directly, then not return anything. This means that `vec0` will change over the
course of the function, and makes `vec1` redundant (make sure to change the parameters of the `println!`
statements if you go this route)
""" """
[[exercises]] [[exercises]]
name = "move_semantics3" name = "move_semantics3"
path = "exercises/move_semantics/move_semantics3.rs" path = "exercises/move_semantics/move_semantics3.rs"
mode = "compile" mode = "test"
hint = """ hint = """
The difference between this one and the previous ones is that the first line The difference between this one and the previous ones is that the first line
of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can, of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can,
@ -326,7 +324,7 @@ an existing binding to be a mutable binding instead of an immutable one :)"""
[[exercises]] [[exercises]]
name = "move_semantics4" name = "move_semantics4"
path = "exercises/move_semantics/move_semantics4.rs" path = "exercises/move_semantics/move_semantics4.rs"
mode = "compile" mode = "test"
hint = """ hint = """
Stop reading whenever you feel like you have enough direction :) Or try Stop reading whenever you feel like you have enough direction :) Or try
doing one step and then fixing the compiler errors that result! doing one step and then fixing the compiler errors that result!
@ -335,7 +333,7 @@ So the end goal is to:
- so then `vec0` doesn't exist, so we can't pass it to `fill_vec` - so then `vec0` doesn't exist, so we can't pass it to `fill_vec`
- `fill_vec` has had its signature changed, which our call should reflect - `fill_vec` has had its signature changed, which our call should reflect
- since we're not creating a new vec in `main` anymore, we need to create - since we're not creating a new vec in `main` anymore, we need to create
a new vec in `fill_vec`, similarly to the way we did in `main`""" a new vec in `fill_vec`, and fill it with the expected values"""
[[exercises]] [[exercises]]
name = "move_semantics5" name = "move_semantics5"
@ -825,7 +823,6 @@ To handle that you need to add a special attribute to the test function.
You can refer to the docs: You can refer to the docs:
https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic""" https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic"""
# STANDARD LIBRARY TYPES # STANDARD LIBRARY TYPES
[[exercises]] [[exercises]]
@ -1009,7 +1006,7 @@ and keep reading if you'd like more hints :)
Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like:
`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` `let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));`
Similar to the code in the example in the book that happens after the text Similar to the code in the example in the book that happens after the text
that says "We can use Arc<T> to fix this.". If not, give that a try! If you that says "Sharing a Mutex<T> Between Multiple Threads". If not, give that a try! If you
do and would like more hints, keep reading!! do and would like more hints, keep reading!!

View File

@ -110,12 +110,12 @@ impl Exercise {
pub fn compile(&self) -> Result<CompiledExercise, ExerciseOutput> { pub fn compile(&self) -> Result<CompiledExercise, ExerciseOutput> {
let cmd = match self.mode { let cmd = match self.mode {
Mode::Compile => Command::new("rustc") Mode::Compile => Command::new("rustc")
.args(&[self.path.to_str().unwrap(), "-o", &temp_file()]) .args([self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS) .args(RUSTC_COLOR_ARGS)
.args(RUSTC_EDITION_ARGS) .args(RUSTC_EDITION_ARGS)
.output(), .output(),
Mode::Test => Command::new("rustc") Mode::Test => Command::new("rustc")
.args(&["--test", self.path.to_str().unwrap(), "-o", &temp_file()]) .args(["--test", self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS) .args(RUSTC_COLOR_ARGS)
.args(RUSTC_EDITION_ARGS) .args(RUSTC_EDITION_ARGS)
.output(), .output(),
@ -141,7 +141,7 @@ path = "{}.rs""#,
// compilation failure, this would silently fail. But we expect // compilation failure, this would silently fail. But we expect
// clippy to reflect the same failure while compiling later. // clippy to reflect the same failure while compiling later.
Command::new("rustc") Command::new("rustc")
.args(&[self.path.to_str().unwrap(), "-o", &temp_file()]) .args([self.path.to_str().unwrap(), "-o", &temp_file()])
.args(RUSTC_COLOR_ARGS) .args(RUSTC_COLOR_ARGS)
.args(RUSTC_EDITION_ARGS) .args(RUSTC_EDITION_ARGS)
.output() .output()
@ -151,14 +151,14 @@ path = "{}.rs""#,
// This is already fixed on Clippy's master branch. See this issue to track merging into Cargo: // This is already fixed on Clippy's master branch. See this issue to track merging into Cargo:
// https://github.com/rust-lang/rust-clippy/issues/3837 // https://github.com/rust-lang/rust-clippy/issues/3837
Command::new("cargo") Command::new("cargo")
.args(&["clean", "--manifest-path", CLIPPY_CARGO_TOML_PATH]) .args(["clean", "--manifest-path", CLIPPY_CARGO_TOML_PATH])
.args(RUSTC_COLOR_ARGS) .args(RUSTC_COLOR_ARGS)
.output() .output()
.expect("Failed to run 'cargo clean'"); .expect("Failed to run 'cargo clean'");
Command::new("cargo") Command::new("cargo")
.args(&["clippy", "--manifest-path", CLIPPY_CARGO_TOML_PATH]) .args(["clippy", "--manifest-path", CLIPPY_CARGO_TOML_PATH])
.args(RUSTC_COLOR_ARGS) .args(RUSTC_COLOR_ARGS)
.args(&["--", "-D", "warnings", "-D", "clippy::float_cmp"]) .args(["--", "-D", "warnings", "-D", "clippy::float_cmp"])
.output() .output()
} }
} }
@ -183,7 +183,7 @@ path = "{}.rs""#,
Mode::Test => "--show-output", Mode::Test => "--show-output",
_ => "", _ => "",
}; };
let cmd = Command::new(&temp_file()) let cmd = Command::new(temp_file())
.arg(arg) .arg(arg)
.output() .output()
.expect("Failed to run 'run' command"); .expect("Failed to run 'run' command");
@ -260,7 +260,7 @@ impl Display for Exercise {
#[inline] #[inline]
fn clean() { fn clean() {
let _ignored = remove_file(&temp_file()); let _ignored = remove_file(temp_file());
} }
#[cfg(test)] #[cfg(test)]
@ -270,7 +270,7 @@ mod test {
#[test] #[test]
fn test_clean() { fn test_clean() {
File::create(&temp_file()).unwrap(); File::create(temp_file()).unwrap();
let exercise = Exercise { let exercise = Exercise {
name: String::from("example"), name: String::from("example"),
path: PathBuf::from("tests/fixture/state/pending_exercise.rs"), path: PathBuf::from("tests/fixture/state/pending_exercise.rs"),

View File

@ -2,7 +2,7 @@ use crate::exercise::{Exercise, ExerciseList};
use crate::project::RustAnalyzerProject; use crate::project::RustAnalyzerProject;
use crate::run::{reset, run}; use crate::run::{reset, run};
use crate::verify::verify; use crate::verify::verify;
use argh::FromArgs; use clap::{Parser, Subcommand};
use console::Emoji; use console::Emoji;
use notify::DebouncedEvent; use notify::DebouncedEvent;
use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use notify::{RecommendedWatcher, RecursiveMode, Watcher};
@ -25,111 +25,69 @@ mod project;
mod run; mod run;
mod verify; mod verify;
// In sync with crate version
const VERSION: &str = "5.5.1";
#[derive(FromArgs, PartialEq, Debug)]
/// Rustlings is a collection of small exercises to get you used to writing and reading Rust code /// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
#[derive(Parser)]
#[command(version)]
struct Args { struct Args {
/// show outputs from the test exercises /// Show outputs from the test exercises
#[argh(switch)] #[arg(long)]
nocapture: bool, nocapture: bool,
/// show the executable version #[command(subcommand)]
#[argh(switch, short = 'v')] command: Option<Subcommands>,
version: bool,
#[argh(subcommand)]
nested: Option<Subcommands>,
} }
#[derive(FromArgs, PartialEq, Debug)] #[derive(Subcommand)]
#[argh(subcommand)]
enum Subcommands { enum Subcommands {
Verify(VerifyArgs), /// Verify all exercises according to the recommended order
Watch(WatchArgs), Verify,
Run(RunArgs), /// Rerun `verify` when files were edited
Reset(ResetArgs), Watch {
Hint(HintArgs), /// Show hints on success
List(ListArgs), #[arg(long)]
Lsp(LspArgs), success_hints: bool,
} },
/// Run/Test a single exercise
#[derive(FromArgs, PartialEq, Debug)] Run {
#[argh(subcommand, name = "verify")] /// The name of the exercise
/// Verifies all exercises according to the recommended order name: String,
struct VerifyArgs {} },
/// Reset a single exercise using "git stash -- <filename>"
#[derive(FromArgs, PartialEq, Debug)] Reset {
#[argh(subcommand, name = "watch")] /// The name of the exercise
/// Reruns `verify` when files were edited name: String,
struct WatchArgs { },
/// show hints on success /// Return a hint for the given exercise
#[argh(switch)] Hint {
success_hints: bool, /// The name of the exercise
} name: String,
},
#[derive(FromArgs, PartialEq, Debug)] /// List the exercises available in Rustlings
#[argh(subcommand, name = "run")] List {
/// Runs/Tests a single exercise /// Show only the paths of the exercises
struct RunArgs { #[arg(short, long)]
#[argh(positional)] paths: bool,
/// the name of the exercise /// Show only the names of the exercises
name: String, #[arg(short, long)]
} names: bool,
/// Provide a string to match exercise names.
#[derive(FromArgs, PartialEq, Debug)] /// Comma separated patterns are accepted
#[argh(subcommand, name = "reset")] #[arg(short, long)]
/// Resets a single exercise using "git stash -- <filename>" filter: Option<String>,
struct ResetArgs { /// Display only exercises not yet solved
#[argh(positional)] #[arg(short, long)]
/// the name of the exercise unsolved: bool,
name: String, /// Display only exercises that have been solved
} #[arg(short, long)]
solved: bool,
#[derive(FromArgs, PartialEq, Debug)] },
#[argh(subcommand, name = "hint")] /// Enable rust-analyzer for exercises
/// Returns a hint for the given exercise Lsp,
struct HintArgs {
#[argh(positional)]
/// the name of the exercise
name: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "lsp")]
/// Enable rust-analyzer for exercises
struct LspArgs {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "list")]
/// Lists the exercises available in Rustlings
struct ListArgs {
#[argh(switch, short = 'p')]
/// show only the paths of the exercises
paths: bool,
#[argh(switch, short = 'n')]
/// show only the names of the exercises
names: bool,
#[argh(option, short = 'f')]
/// provide a string to match exercise names
/// comma separated patterns are acceptable
filter: Option<String>,
#[argh(switch, short = 'u')]
/// display only exercises not yet solved
unsolved: bool,
#[argh(switch, short = 's')]
/// display only exercises that have been solved
solved: bool,
} }
fn main() { fn main() {
let args: Args = argh::from_env(); let args = Args::parse();
if args.version { if args.command.is_none() {
println!("v{VERSION}");
std::process::exit(0);
}
if args.nested.is_none() {
println!("\n{WELCOME}\n"); println!("\n{WELCOME}\n");
} }
@ -153,23 +111,30 @@ fn main() {
let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises; let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises;
let verbose = args.nocapture; let verbose = args.nocapture;
let command = args.nested.unwrap_or_else(|| { let command = args.command.unwrap_or_else(|| {
println!("{DEFAULT_OUT}\n"); println!("{DEFAULT_OUT}\n");
std::process::exit(0); std::process::exit(0);
}); });
match command { match command {
Subcommands::List(subargs) => { Subcommands::List {
if !subargs.paths && !subargs.names { paths,
names,
filter,
unsolved,
solved,
} => {
if !paths && !names {
println!("{:<17}\t{:<46}\t{:<7}", "Name", "Path", "Status"); println!("{:<17}\t{:<46}\t{:<7}", "Name", "Path", "Status");
} }
let mut exercises_done: u16 = 0; let mut exercises_done: u16 = 0;
let filters = subargs.filter.clone().unwrap_or_default().to_lowercase(); let filters = filter.clone().unwrap_or_default().to_lowercase();
exercises.iter().for_each(|e| { exercises.iter().for_each(|e| {
let fname = format!("{}", e.path.display()); let fname = format!("{}", e.path.display());
let filter_cond = filters let filter_cond = filters
.split(',') .split(',')
.filter(|f| !f.trim().is_empty()) .filter(|f| !f.trim().is_empty())
.any(|f| e.name.contains(&f) || fname.contains(&f)); .any(|f| e.name.contains(f) || fname.contains(f));
let status = if e.looks_done() { let status = if e.looks_done() {
exercises_done += 1; exercises_done += 1;
"Done" "Done"
@ -177,14 +142,14 @@ fn main() {
"Pending" "Pending"
}; };
let solve_cond = { let solve_cond = {
(e.looks_done() && subargs.solved) (e.looks_done() && solved)
|| (!e.looks_done() && subargs.unsolved) || (!e.looks_done() && unsolved)
|| (!subargs.solved && !subargs.unsolved) || (!solved && !unsolved)
}; };
if solve_cond && (filter_cond || subargs.filter.is_none()) { if solve_cond && (filter_cond || filter.is_none()) {
let line = if subargs.paths { let line = if paths {
format!("{fname}\n") format!("{fname}\n")
} else if subargs.names { } else if names {
format!("{}\n", e.name) format!("{}\n", e.name)
} else { } else {
format!("{:<17}\t{fname:<46}\t{status:<7}\n", e.name) format!("{:<17}\t{fname:<46}\t{status:<7}\n", e.name)
@ -214,30 +179,30 @@ fn main() {
std::process::exit(0); std::process::exit(0);
} }
Subcommands::Run(subargs) => { Subcommands::Run { name } => {
let exercise = find_exercise(&subargs.name, &exercises); let exercise = find_exercise(&name, &exercises);
run(exercise, verbose).unwrap_or_else(|_| std::process::exit(1)); run(exercise, verbose).unwrap_or_else(|_| std::process::exit(1));
} }
Subcommands::Reset(subargs) => { Subcommands::Reset { name } => {
let exercise = find_exercise(&subargs.name, &exercises); let exercise = find_exercise(&name, &exercises);
reset(exercise).unwrap_or_else(|_| std::process::exit(1)); reset(exercise).unwrap_or_else(|_| std::process::exit(1));
} }
Subcommands::Hint(subargs) => { Subcommands::Hint { name } => {
let exercise = find_exercise(&subargs.name, &exercises); let exercise = find_exercise(&name, &exercises);
println!("{}", exercise.hint); println!("{}", exercise.hint);
} }
Subcommands::Verify(_subargs) => { Subcommands::Verify => {
verify(&exercises, (0, exercises.len()), verbose, false) verify(&exercises, (0, exercises.len()), verbose, false)
.unwrap_or_else(|_| std::process::exit(1)); .unwrap_or_else(|_| std::process::exit(1));
} }
Subcommands::Lsp(_subargs) => { Subcommands::Lsp => {
let mut project = RustAnalyzerProject::new(); let mut project = RustAnalyzerProject::new();
project project
.get_sysroot_src() .get_sysroot_src()
@ -256,7 +221,7 @@ fn main() {
} }
} }
Subcommands::Watch(_subargs) => match watch(&exercises, verbose, _subargs.success_hints) { Subcommands::Watch { success_hints } => match watch(&exercises, verbose, success_hints) {
Err(e) => { Err(e) => {
println!( println!(
"Error: Could not watch your progress. Error message was {:?}.", "Error: Could not watch your progress. Error message was {:?}.",
@ -429,7 +394,7 @@ fn watch(
fn rustc_exists() -> bool { fn rustc_exists() -> bool {
Command::new("rustc") Command::new("rustc")
.args(&["--version"]) .args(["--version"])
.stdout(Stdio::null()) .stdout(Stdio::null())
.spawn() .spawn()
.and_then(|mut child| child.wait()) .and_then(|mut child| child.wait())
@ -465,7 +430,7 @@ started, here's a couple of notes about how Rustlings operates:
Got all that? Great! To get started, run `rustlings watch` in order to get the first Got all that? Great! To get started, run `rustlings watch` in order to get the first
exercise. Make sure to have your editor open!"#; exercise. Make sure to have your editor open!"#;
const FENISH_LINE: &str = r#"+----------------------------------------------------+ const FENISH_LINE: &str = r"+----------------------------------------------------+
| You made it to the Fe-nish line! | | You made it to the Fe-nish line! |
+-------------------------- ------------------------+ +-------------------------- ------------------------+
\\/ \\/
@ -490,12 +455,12 @@ 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! You can also contribute your own exercises to help the greater community!
Before reporting an issue or contributing, please read our guidelines: Before reporting an issue or contributing, please read our guidelines:
https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md"#; https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md";
const WELCOME: &str = r#" welcome to... const WELCOME: &str = r" welcome to...
_ _ _ _ _ _
_ __ _ _ ___| |_| (_)_ __ __ _ ___ _ __ _ _ ___| |_| (_)_ __ __ _ ___
| '__| | | / __| __| | | '_ \ / _` / __| | '__| | | / __| __| | | '_ \ / _` / __|
| | | |_| \__ \ |_| | | | | | (_| \__ \ | | | |_| \__ \ |_| | | | | | (_| \__ \
|_| \__,_|___/\__|_|_|_| |_|\__, |___/ |_| \__,_|___/\__|_|_|_| |_|\__, |___/
|___/"#; |___/";

View File

@ -86,7 +86,7 @@ impl RustAnalyzerProject {
println!("Determined toolchain: {}\n", &toolchain); println!("Determined toolchain: {}\n", &toolchain);
self.sysroot_src = (std::path::Path::new(&*toolchain) self.sysroot_src = (std::path::Path::new(toolchain)
.join("lib") .join("lib")
.join("rustlib") .join("rustlib")
.join("src") .join("src")

View File

@ -1,4 +1,5 @@
use std::process::Command; use std::process::Command;
use std::time::Duration;
use crate::exercise::{Exercise, Mode}; use crate::exercise::{Exercise, Mode};
use crate::verify::test; use crate::verify::test;
@ -36,7 +37,7 @@ pub fn reset(exercise: &Exercise) -> Result<(), ()> {
fn compile_and_run(exercise: &Exercise) -> Result<(), ()> { fn compile_and_run(exercise: &Exercise) -> Result<(), ()> {
let progress_bar = ProgressBar::new_spinner(); let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {exercise}...")); progress_bar.set_message(format!("Compiling {exercise}..."));
progress_bar.enable_steady_tick(100); progress_bar.enable_steady_tick(Duration::from_millis(100));
let compilation_result = exercise.compile(); let compilation_result = exercise.compile();
let compilation = match compilation_result { let compilation = match compilation_result {

View File

@ -1,7 +1,7 @@
use crate::exercise::{CompiledExercise, Exercise, Mode, State}; use crate::exercise::{CompiledExercise, Exercise, Mode, State};
use console::style; use console::style;
use indicatif::{ProgressBar, ProgressStyle}; use indicatif::{ProgressBar, ProgressStyle};
use std::env; use std::{env, time::Duration};
// Verify that the provided container of Exercise objects // Verify that the provided container of Exercise objects
// can be compiled and run without any failures. // can be compiled and run without any failures.
@ -17,9 +17,11 @@ pub fn verify<'a>(
let (num_done, total) = progress; let (num_done, total) = progress;
let bar = ProgressBar::new(total as u64); let bar = ProgressBar::new(total as u64);
let mut percentage = num_done as f32 / total as f32 * 100.0; let mut percentage = num_done as f32 / total as f32 * 100.0;
bar.set_style(ProgressStyle::default_bar() bar.set_style(
.template("Progress: [{bar:60.green/red}] {pos}/{len} {msg}") ProgressStyle::default_bar()
.progress_chars("#>-") .template("Progress: [{bar:60.green/red}] {pos}/{len} {msg}")
.expect("Progressbar template should be valid!")
.progress_chars("#>-"),
); );
bar.set_position(num_done as u64); bar.set_position(num_done as u64);
bar.set_message(format!("({:.1} %)", percentage)); bar.set_message(format!("({:.1} %)", percentage));
@ -55,7 +57,7 @@ pub fn test(exercise: &Exercise, verbose: bool) -> Result<(), ()> {
fn compile_only(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> { fn compile_only(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner(); let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {exercise}...")); progress_bar.set_message(format!("Compiling {exercise}..."));
progress_bar.enable_steady_tick(100); progress_bar.enable_steady_tick(Duration::from_millis(100));
let _ = compile(exercise, &progress_bar)?; let _ = compile(exercise, &progress_bar)?;
progress_bar.finish_and_clear(); progress_bar.finish_and_clear();
@ -67,7 +69,7 @@ fn compile_only(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> {
fn compile_and_run_interactively(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> { fn compile_and_run_interactively(exercise: &Exercise, success_hints: bool) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner(); let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {exercise}...")); progress_bar.set_message(format!("Compiling {exercise}..."));
progress_bar.enable_steady_tick(100); progress_bar.enable_steady_tick(Duration::from_millis(100));
let compilation = compile(exercise, &progress_bar)?; let compilation = compile(exercise, &progress_bar)?;
@ -85,15 +87,24 @@ fn compile_and_run_interactively(exercise: &Exercise, success_hints: bool) -> Re
} }
}; };
Ok(prompt_for_completion(exercise, Some(output.stdout), success_hints)) Ok(prompt_for_completion(
exercise,
Some(output.stdout),
success_hints,
))
} }
// Compile the given Exercise as a test harness and display // Compile the given Exercise as a test harness and display
// the output if verbose is set to true // the output if verbose is set to true
fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool, success_hints: bool) -> Result<bool, ()> { fn compile_and_test(
exercise: &Exercise,
run_mode: RunMode,
verbose: bool,
success_hints: bool,
) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner(); let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Testing {exercise}...")); progress_bar.set_message(format!("Testing {exercise}..."));
progress_bar.enable_steady_tick(100); progress_bar.enable_steady_tick(Duration::from_millis(100));
let compilation = compile(exercise, &progress_bar)?; let compilation = compile(exercise, &progress_bar)?;
let result = compilation.run(); let result = compilation.run();
@ -123,9 +134,9 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool, succe
// Compile the given Exercise and return an object with information // Compile the given Exercise and return an object with information
// about the state of the compilation // about the state of the compilation
fn compile<'a, 'b>( fn compile<'a>(
exercise: &'a Exercise, exercise: &'a Exercise,
progress_bar: &'b ProgressBar, progress_bar: &ProgressBar,
) -> Result<CompiledExercise<'a>, ()> { ) -> Result<CompiledExercise<'a>, ()> {
let compilation_result = exercise.compile(); let compilation_result = exercise.compile();
@ -143,7 +154,11 @@ fn compile<'a, 'b>(
} }
} }
fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>, success_hints: bool) -> bool { fn prompt_for_completion(
exercise: &Exercise,
prompt_output: Option<String>,
success_hints: bool,
) -> bool {
let context = match exercise.state() { let context = match exercise.state() {
State::Done => return true, State::Done => return true,
State::Pending(context) => context, State::Pending(context) => context,

View File

@ -44,7 +44,7 @@ fn verify_fails_if_some_fails() {
fn run_single_compile_success() { fn run_single_compile_success() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "compSuccess"]) .args(["run", "compSuccess"])
.current_dir("tests/fixture/success/") .current_dir("tests/fixture/success/")
.assert() .assert()
.success(); .success();
@ -54,7 +54,7 @@ fn run_single_compile_success() {
fn run_single_compile_failure() { fn run_single_compile_failure() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "compFailure"]) .args(["run", "compFailure"])
.current_dir("tests/fixture/failure/") .current_dir("tests/fixture/failure/")
.assert() .assert()
.code(1); .code(1);
@ -64,7 +64,7 @@ fn run_single_compile_failure() {
fn run_single_test_success() { fn run_single_test_success() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "testSuccess"]) .args(["run", "testSuccess"])
.current_dir("tests/fixture/success/") .current_dir("tests/fixture/success/")
.assert() .assert()
.success(); .success();
@ -74,7 +74,7 @@ fn run_single_test_success() {
fn run_single_test_failure() { fn run_single_test_failure() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "testFailure"]) .args(["run", "testFailure"])
.current_dir("tests/fixture/failure/") .current_dir("tests/fixture/failure/")
.assert() .assert()
.code(1); .code(1);
@ -84,7 +84,7 @@ fn run_single_test_failure() {
fn run_single_test_not_passed() { fn run_single_test_not_passed() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "testNotPassed.rs"]) .args(["run", "testNotPassed.rs"])
.current_dir("tests/fixture/failure/") .current_dir("tests/fixture/failure/")
.assert() .assert()
.code(1); .code(1);
@ -97,14 +97,17 @@ fn run_single_test_no_filename() {
.arg("run") .arg("run")
.current_dir("tests/fixture/") .current_dir("tests/fixture/")
.assert() .assert()
.code(1); .code(2)
.stderr(predicates::str::contains(
"required arguments were not provided",
));
} }
#[test] #[test]
fn run_single_test_no_exercise() { fn run_single_test_no_exercise() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "compNoExercise.rs"]) .args(["run", "compNoExercise.rs"])
.current_dir("tests/fixture/failure") .current_dir("tests/fixture/failure")
.assert() .assert()
.code(1); .code(1);
@ -114,7 +117,7 @@ fn run_single_test_no_exercise() {
fn reset_single_exercise() { fn reset_single_exercise() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["reset", "intro1"]) .args(["reset", "intro1"])
.assert() .assert()
.code(0); .code(0);
} }
@ -125,9 +128,9 @@ fn reset_no_exercise() {
.unwrap() .unwrap()
.arg("reset") .arg("reset")
.assert() .assert()
.code(1) .code(2)
.stderr(predicates::str::contains( .stderr(predicates::str::contains(
"positional arguments not provided", "required arguments were not provided",
)); ));
} }
@ -135,7 +138,7 @@ fn reset_no_exercise() {
fn get_hint_for_single_test() { fn get_hint_for_single_test() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["hint", "testFailure"]) .args(["hint", "testFailure"])
.current_dir("tests/fixture/failure") .current_dir("tests/fixture/failure")
.assert() .assert()
.code(0) .code(0)
@ -171,7 +174,7 @@ fn all_exercises_require_confirmation() {
fn run_compile_exercise_does_not_prompt() { fn run_compile_exercise_does_not_prompt() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "pending_exercise"]) .args(["run", "pending_exercise"])
.current_dir("tests/fixture/state") .current_dir("tests/fixture/state")
.assert() .assert()
.code(0) .code(0)
@ -182,7 +185,7 @@ fn run_compile_exercise_does_not_prompt() {
fn run_test_exercise_does_not_prompt() { fn run_test_exercise_does_not_prompt() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "pending_test_exercise"]) .args(["run", "pending_test_exercise"])
.current_dir("tests/fixture/state") .current_dir("tests/fixture/state")
.assert() .assert()
.code(0) .code(0)
@ -193,7 +196,7 @@ fn run_test_exercise_does_not_prompt() {
fn run_single_test_success_with_output() { fn run_single_test_success_with_output() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["--nocapture", "run", "testSuccess"]) .args(["--nocapture", "run", "testSuccess"])
.current_dir("tests/fixture/success/") .current_dir("tests/fixture/success/")
.assert() .assert()
.code(0) .code(0)
@ -204,7 +207,7 @@ fn run_single_test_success_with_output() {
fn run_single_test_success_without_output() { fn run_single_test_success_without_output() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["run", "testSuccess"]) .args(["run", "testSuccess"])
.current_dir("tests/fixture/success/") .current_dir("tests/fixture/success/")
.assert() .assert()
.code(0) .code(0)
@ -215,7 +218,7 @@ fn run_single_test_success_without_output() {
fn run_rustlings_list() { fn run_rustlings_list() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["list"]) .args(["list"])
.current_dir("tests/fixture/success") .current_dir("tests/fixture/success")
.assert() .assert()
.success(); .success();
@ -225,7 +228,7 @@ fn run_rustlings_list() {
fn run_rustlings_list_no_pending() { fn run_rustlings_list_no_pending() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["list"]) .args(["list"])
.current_dir("tests/fixture/success") .current_dir("tests/fixture/success")
.assert() .assert()
.success() .success()
@ -236,7 +239,7 @@ fn run_rustlings_list_no_pending() {
fn run_rustlings_list_both_done_and_pending() { fn run_rustlings_list_both_done_and_pending() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["list"]) .args(["list"])
.current_dir("tests/fixture/state") .current_dir("tests/fixture/state")
.assert() .assert()
.success() .success()
@ -247,7 +250,7 @@ fn run_rustlings_list_both_done_and_pending() {
fn run_rustlings_list_without_pending() { fn run_rustlings_list_without_pending() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["list", "--solved"]) .args(["list", "--solved"])
.current_dir("tests/fixture/state") .current_dir("tests/fixture/state")
.assert() .assert()
.success() .success()
@ -258,7 +261,7 @@ fn run_rustlings_list_without_pending() {
fn run_rustlings_list_without_done() { fn run_rustlings_list_without_done() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")
.unwrap() .unwrap()
.args(&["list", "--unsolved"]) .args(["list", "--unsolved"])
.current_dir("tests/fixture/state") .current_dir("tests/fixture/state")
.assert() .assert()
.success() .success()