mirror of
https://github.com/notohh/rustlings.git
synced 2024-11-25 14:57:32 -05:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
dd72429af4
26 changed files with 767 additions and 515 deletions
|
@ -2559,6 +2559,132 @@
|
||||||
"contributions": [
|
"contributions": [
|
||||||
"content"
|
"content"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "AnonimAnonim2245",
|
||||||
|
"name": "Luca Plian",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/98339220?v=4",
|
||||||
|
"profile": "https://github.com/AnonimAnonim2245",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "reifenrath-dev",
|
||||||
|
"name": "René Reifenrath",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/18126097?v=4",
|
||||||
|
"profile": "https://reifenrath.dev/",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "peterneave",
|
||||||
|
"name": "Peter Neave",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/7982708?v=4",
|
||||||
|
"profile": "https://github.com/peterneave",
|
||||||
|
"contributions": [
|
||||||
|
"infra"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "JanB1",
|
||||||
|
"name": "Jan",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/5552248?v=4",
|
||||||
|
"profile": "http://www.janb1.com",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "kylev",
|
||||||
|
"name": "Kyle VanderBeek",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/46888?v=4",
|
||||||
|
"profile": "http://www.kylev.com/",
|
||||||
|
"contributions": [
|
||||||
|
"infra"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "pavedroad",
|
||||||
|
"name": "pavedroad",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/138004431?v=4",
|
||||||
|
"profile": "https://github.com/pavedroad",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "hyphena",
|
||||||
|
"name": "luna",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/26529488?v=4",
|
||||||
|
"profile": "https://github.com/hyphena",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "evanmiller2112",
|
||||||
|
"name": "Evan Miller",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/28488957?v=4",
|
||||||
|
"profile": "https://github.com/evanmiller2112",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "luvchurchill",
|
||||||
|
"name": "luvchurchill",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/46406654?v=4",
|
||||||
|
"profile": "https://github.com/luvchurchill",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "LeverImmy",
|
||||||
|
"name": "Ze-en Xiong",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/47663913?v=4",
|
||||||
|
"profile": "https://leverimmy.top/",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "parnavh",
|
||||||
|
"name": "Parnav Harinathan",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/45985534?v=4",
|
||||||
|
"profile": "https://github.com/parnavh",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "0Ahmed-0",
|
||||||
|
"name": "0Ahmed-0",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/111569638?v=4",
|
||||||
|
"profile": "https://github.com/0Ahmed-0",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "guizo792",
|
||||||
|
"name": "guizo792",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/95940388?v=4",
|
||||||
|
"profile": "https://github.com/guizo792",
|
||||||
|
"contributions": [
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "kazu728",
|
||||||
|
"name": "Kazuki Matsuo",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/34614358?v=4",
|
||||||
|
"profile": "https://github.com/kazu728",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 8,
|
"contributorsPerLine": 8,
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
{
|
{
|
||||||
"image": "mcr.microsoft.com/devcontainers/universal:2-linux",
|
"image": "mcr.microsoft.com/devcontainers/rust:1",
|
||||||
"waitFor": "onCreateCommand",
|
"updateContentCommand": ["cargo", "build"],
|
||||||
"onCreateCommand": ".devcontainer/setup.sh",
|
"postAttachCommand": ["rustlings", "watch"],
|
||||||
"updateContentCommand": "cargo build",
|
"remoteEnv": {
|
||||||
"postCreateCommand": "",
|
"PATH": "${containerEnv:PATH}:${containerWorkspaceFolder}/target/debug"
|
||||||
"postAttachCommand": {
|
|
||||||
"server": "rustlings watch"
|
|
||||||
},
|
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": [
|
|
||||||
"rust-lang.rust-analyzer"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
|
||||||
|
|
||||||
# Update current shell environment variables after install to find rustup
|
|
||||||
. "$HOME/.cargo/env"
|
|
||||||
rustup install stable
|
|
||||||
bash install.sh
|
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
* text=auto
|
||||||
|
*.sh text eol=lf
|
16
AUTHORS.md
16
AUTHORS.md
|
@ -362,6 +362,22 @@ authors.
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gerases"><img src="https://avatars.githubusercontent.com/u/8953623?v=4?s=100" width="100px;" alt="gerases"/><br /><sub><b>gerases</b></sub></a><br /><a href="#content-gerases" title="Content">🖋</a></td>
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gerases"><img src="https://avatars.githubusercontent.com/u/8953623?v=4?s=100" width="100px;" alt="gerases"/><br /><sub><b>gerases</b></sub></a><br /><a href="#content-gerases" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/AnonimAnonim2245"><img src="https://avatars.githubusercontent.com/u/98339220?v=4?s=100" width="100px;" alt="Luca Plian"/><br /><sub><b>Luca Plian</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=AnonimAnonim2245" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://reifenrath.dev/"><img src="https://avatars.githubusercontent.com/u/18126097?v=4?s=100" width="100px;" alt="René Reifenrath"/><br /><sub><b>René Reifenrath</b></sub></a><br /><a href="#content-reifenrath-dev" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/peterneave"><img src="https://avatars.githubusercontent.com/u/7982708?v=4?s=100" width="100px;" alt="Peter Neave"/><br /><sub><b>Peter Neave</b></sub></a><br /><a href="#infra-peterneave" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="http://www.janb1.com"><img src="https://avatars.githubusercontent.com/u/5552248?v=4?s=100" width="100px;" alt="Jan"/><br /><sub><b>Jan</b></sub></a><br /><a href="#content-JanB1" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="http://www.kylev.com/"><img src="https://avatars.githubusercontent.com/u/46888?v=4?s=100" width="100px;" alt="Kyle VanderBeek"/><br /><sub><b>Kyle VanderBeek</b></sub></a><br /><a href="#infra-kylev" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/pavedroad"><img src="https://avatars.githubusercontent.com/u/138004431?v=4?s=100" width="100px;" alt="pavedroad"/><br /><sub><b>pavedroad</b></sub></a><br /><a href="#content-pavedroad" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/hyphena"><img src="https://avatars.githubusercontent.com/u/26529488?v=4?s=100" width="100px;" alt="luna"/><br /><sub><b>luna</b></sub></a><br /><a href="#content-hyphena" title="Content">🖋</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/evanmiller2112"><img src="https://avatars.githubusercontent.com/u/28488957?v=4?s=100" width="100px;" alt="Evan Miller"/><br /><sub><b>Evan Miller</b></sub></a><br /><a href="#content-evanmiller2112" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/luvchurchill"><img src="https://avatars.githubusercontent.com/u/46406654?v=4?s=100" width="100px;" alt="luvchurchill"/><br /><sub><b>luvchurchill</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=luvchurchill" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://leverimmy.top/"><img src="https://avatars.githubusercontent.com/u/47663913?v=4?s=100" width="100px;" alt="Ze-en Xiong"/><br /><sub><b>Ze-en Xiong</b></sub></a><br /><a href="#content-LeverImmy" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/parnavh"><img src="https://avatars.githubusercontent.com/u/45985534?v=4?s=100" width="100px;" alt="Parnav Harinathan"/><br /><sub><b>Parnav Harinathan</b></sub></a><br /><a href="#content-parnavh" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/0Ahmed-0"><img src="https://avatars.githubusercontent.com/u/111569638?v=4?s=100" width="100px;" alt="0Ahmed-0"/><br /><sub><b>0Ahmed-0</b></sub></a><br /><a href="#content-0Ahmed-0" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/guizo792"><img src="https://avatars.githubusercontent.com/u/95940388?v=4?s=100" width="100px;" alt="guizo792"/><br /><sub><b>guizo792</b></sub></a><br /><a href="#content-guizo792" title="Content">🖋</a></td>
|
||||||
|
<td align="center" valign="top" width="12.5%"><a href="https://github.com/kazu728"><img src="https://avatars.githubusercontent.com/u/34614358?v=4?s=100" width="100px;" alt="Kazuki Matsuo"/><br /><sub><b>Kazuki Matsuo</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=kazu728" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -167,7 +167,7 @@
|
||||||
- **structs3**: Clarifed the hint
|
- **structs3**: Clarifed the hint
|
||||||
- **quiz2, as_ref_mut, options1, traits1, traits2**: Clarified hints
|
- **quiz2, as_ref_mut, options1, traits1, traits2**: Clarified hints
|
||||||
- **traits1, traits2, cli**: Tidied up unmatching backticks
|
- **traits1, traits2, cli**: Tidied up unmatching backticks
|
||||||
- **enums2**: Removed unneccessary indirection of self
|
- **enums2**: Removed unnecessary indirection of self
|
||||||
- **enums3**: Added an extra tuple comment
|
- **enums3**: Added an extra tuple comment
|
||||||
|
|
||||||
#### Housekeeping
|
#### Housekeeping
|
||||||
|
|
417
Cargo.lock
generated
417
Cargo.lock
generated
|
@ -4,18 +4,18 @@ version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.20"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.5.0"
|
version = "0.6.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
|
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"anstyle-parse",
|
"anstyle-parse",
|
||||||
|
@ -27,43 +27,49 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.3"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
|
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-parse"
|
name = "anstyle-parse"
|
||||||
version = "0.2.1"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"utf8parse",
|
"utf8parse",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-query"
|
name = "anstyle-query"
|
||||||
version = "1.0.0"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-wincon"
|
name = "anstyle-wincon"
|
||||||
version = "2.1.0"
|
version = "3.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
|
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert_cmd"
|
name = "anyhow"
|
||||||
version = "2.0.12"
|
version = "1.0.81"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6"
|
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "assert_cmd"
|
||||||
|
version = "2.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"bstr",
|
"bstr",
|
||||||
|
@ -76,9 +82,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
|
@ -88,15 +94,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.4.1"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.6.2"
|
version = "1.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a"
|
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
|
@ -111,9 +117,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.4.3"
|
version = "4.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6"
|
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
@ -121,9 +127,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.4.2"
|
version = "4.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
|
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
|
@ -133,9 +139,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.4.2"
|
version = "4.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -145,9 +151,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.5.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
|
@ -157,35 +163,31 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
version = "0.15.5"
|
version = "0.15.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60"
|
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"encode_unicode",
|
"encode_unicode",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"windows-sys 0.42.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.8"
|
version = "0.5.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.16"
|
version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "difflib"
|
name = "difflib"
|
||||||
|
@ -201,9 +203,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.9.0"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encode_unicode"
|
name = "encode_unicode"
|
||||||
|
@ -218,15 +220,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "errno"
|
||||||
version = "0.2.22"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -255,30 +267,30 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.0"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
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 = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.4"
|
version = "0.5.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
|
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.0.0"
|
version = "2.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
@ -286,9 +298,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indicatif"
|
name = "indicatif"
|
||||||
version = "0.17.6"
|
version = "0.17.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730"
|
checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console",
|
"console",
|
||||||
"instant",
|
"instant",
|
||||||
|
@ -326,20 +338,11 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.10.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kqueue"
|
name = "kqueue"
|
||||||
|
@ -369,30 +372,33 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.150"
|
version = "0.2.153"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.6.3"
|
version = "2.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.9"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
@ -412,7 +418,7 @@ version = "6.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.1",
|
"bitflags 2.5.0",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"filetime",
|
"filetime",
|
||||||
"fsevent-sys",
|
"fsevent-sys",
|
||||||
|
@ -438,9 +444,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
@ -453,20 +459,19 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.4.3"
|
version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b"
|
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
version = "3.0.3"
|
version = "3.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9"
|
checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"difflib",
|
"difflib",
|
||||||
"float-cmp",
|
"float-cmp",
|
||||||
"itertools",
|
|
||||||
"normalize-line-endings",
|
"normalize-line-endings",
|
||||||
"predicates-core",
|
"predicates-core",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -490,36 +495,48 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.53"
|
version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.26"
|
version = "1.0.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.3.5"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.7.2"
|
version = "1.10.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
|
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
@ -527,40 +544,49 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-syntax"
|
||||||
version = "0.3.8"
|
version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
|
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "rustix"
|
||||||
version = "0.6.29"
|
version = "0.38.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustlings"
|
name = "rustlings"
|
||||||
version = "5.6.1"
|
version = "5.6.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"clap",
|
"clap",
|
||||||
"console",
|
"console",
|
||||||
"glob",
|
"glob",
|
||||||
"home",
|
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"notify-debouncer-mini",
|
"notify-debouncer-mini",
|
||||||
"predicates",
|
"predicates",
|
||||||
"regex",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"toml",
|
"shlex",
|
||||||
|
"toml_edit",
|
||||||
|
"which",
|
||||||
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.13"
|
version = "1.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
|
@ -573,18 +599,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.158"
|
version = "1.0.197"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
|
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.158"
|
version = "1.0.197"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
|
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -593,9 +619,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.94"
|
version = "1.0.115"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
|
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
@ -604,24 +630,30 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "0.6.3"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
|
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "shlex"
|
||||||
version = "0.10.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.8"
|
version = "2.0.55"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
|
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -634,32 +666,20 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml"
|
|
||||||
version = "0.7.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"toml_edit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.3"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.19.15"
|
version = "0.22.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -670,15 +690,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.8"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
|
@ -697,9 +717,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.3"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
|
@ -711,6 +731,18 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "6.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"home",
|
||||||
|
"rustix",
|
||||||
|
"winsafe",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -729,9 +761,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
@ -742,28 +774,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 0.42.2",
|
|
||||||
"windows_aarch64_msvc 0.42.2",
|
|
||||||
"windows_i686_gnu 0.42.2",
|
|
||||||
"windows_i686_msvc 0.42.2",
|
|
||||||
"windows_x86_64_gnu 0.42.2",
|
|
||||||
"windows_x86_64_gnullvm 0.42.2",
|
|
||||||
"windows_x86_64_msvc 0.42.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -782,10 +808,19 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows-targets"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.4",
|
||||||
|
"windows_aarch64_msvc 0.52.4",
|
||||||
|
"windows_i686_gnu 0.52.4",
|
||||||
|
"windows_i686_msvc 0.52.4",
|
||||||
|
"windows_x86_64_gnu 0.52.4",
|
||||||
|
"windows_x86_64_gnullvm 0.52.4",
|
||||||
|
"windows_x86_64_msvc 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
|
@ -794,10 +829,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
|
@ -806,10 +841,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
|
@ -818,10 +853,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_gnu"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
|
@ -830,10 +865,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_i686_msvc"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
|
@ -842,10 +877,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
|
@ -854,10 +889,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.2"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
|
@ -866,10 +901,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.5.15"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
|
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winsafe"
|
||||||
|
version = "0.0.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
||||||
|
|
23
Cargo.toml
23
Cargo.toml
|
@ -9,22 +9,23 @@ authors = [
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
indicatif = "0.17.6"
|
anyhow = "1.0.81"
|
||||||
console = "0.15"
|
clap = { version = "4.5.4", features = ["derive"] }
|
||||||
|
console = "0.15.8"
|
||||||
|
indicatif = "0.17.8"
|
||||||
notify-debouncer-mini = "0.4.1"
|
notify-debouncer-mini = "0.4.1"
|
||||||
toml = "0.7.6"
|
serde_json = "1.0.115"
|
||||||
regex = "1.5"
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
shlex = "1.3.0"
|
||||||
serde_json = "1.0.81"
|
toml_edit = { version = "0.22.9", default-features = false, features = ["parse", "serde"] }
|
||||||
home = "0.5.3"
|
which = "6.0.1"
|
||||||
glob = "0.3.0"
|
winnow = "0.6.5"
|
||||||
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 = "2.0.12"
|
assert_cmd = "2.0.14"
|
||||||
predicates = "3.0.3"
|
|
||||||
glob = "0.3.0"
|
glob = "0.3.0"
|
||||||
|
predicates = "3.1.0"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
pub fn bigger(a: i32, b: i32) -> i32 {
|
pub fn bigger(a: i32, b: i32) -> i32 {
|
||||||
// Complete this function to return the bigger number!
|
// Complete this function to return the bigger number!
|
||||||
|
// If both numbers are equal, any of them can be returned.
|
||||||
// Do not use:
|
// Do not use:
|
||||||
// - another function call
|
// - another function call
|
||||||
// - additional variables
|
// - additional variables
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
let mut vec1 = fill_vec(vec0);
|
let vec1 = fill_vec(vec0);
|
||||||
|
|
||||||
assert_eq!(vec0, vec![22, 44, 66]);
|
assert_eq!(vec0, vec![22, 44, 66]);
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
let mut vec1 = fill_vec(vec0);
|
let vec1 = fill_vec(vec0);
|
||||||
|
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
let mut vec1 = fill_vec(vec0);
|
let vec1 = fill_vec(vec0);
|
||||||
|
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ fn trim_me(input: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compose_me(input: &str) -> String {
|
fn compose_me(input: &str) -> String {
|
||||||
// TODO: Add " world!" to the string! There's multiple ways to do this!
|
// TODO: Add " world!" to the string! There are multiple ways to do this!
|
||||||
???
|
???
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@
|
||||||
// the form : "<team_1_name>,<team_2_name>,<team_1_goals>,<team_2_goals>"
|
// the form : "<team_1_name>,<team_2_name>,<team_1_goals>,<team_2_goals>"
|
||||||
// Example: England,France,4,2 (England scored 4 goals, France 2).
|
// Example: England,France,4,2 (England scored 4 goals, France 2).
|
||||||
//
|
//
|
||||||
// You have to build a scores table containing the name of the team, goals the
|
// You have to build a scores table containing the name of the team, the total
|
||||||
// team scored, and goals the team conceded. One approach to build the scores
|
// number of goals the team scored, and the total number of goals the team
|
||||||
// table is to use a Hashmap. The solution is partially written to use a
|
// conceded. One approach to build the scores table is to use a Hashmap.
|
||||||
// Hashmap, complete it to pass the test.
|
// The solution is partially written to use a Hashmap,
|
||||||
|
// complete it to pass the test.
|
||||||
//
|
//
|
||||||
// Make me pass the tests!
|
// Make me pass the tests!
|
||||||
//
|
//
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
pub fn factorial(num: u64) -> u64 {
|
pub fn factorial(num: u64) -> u64 {
|
||||||
// Complete this function to return the factorial of num
|
// Complete this function to return the factorial of num
|
||||||
// Do not use:
|
// Do not use:
|
||||||
// - return
|
// - early returns (using the `return` keyword explicitly)
|
||||||
// Try not to use:
|
// Try not to use:
|
||||||
// - imperative style loops (for, while)
|
// - imperative style loops (for, while)
|
||||||
// - additional variables
|
// - additional variables
|
||||||
|
|
|
@ -27,22 +27,18 @@ impl Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () {
|
fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () {
|
||||||
let qc = Arc::new(q);
|
|
||||||
let qc1 = Arc::clone(&qc);
|
|
||||||
let qc2 = Arc::clone(&qc);
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
for val in &qc1.first_half {
|
for val in q.first_half {
|
||||||
println!("sending {:?}", val);
|
println!("sending {:?}", val);
|
||||||
tx.send(*val).unwrap();
|
tx.send(val).unwrap();
|
||||||
thread::sleep(Duration::from_secs(1));
|
thread::sleep(Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
for val in &qc2.second_half {
|
for val in q.second_half {
|
||||||
println!("sending {:?}", val);
|
println!("sending {:?}", val);
|
||||||
tx.send(*val).unwrap();
|
tx.send(val).unwrap();
|
||||||
thread::sleep(Duration::from_secs(1));
|
thread::sleep(Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,8 +24,9 @@ impl Default for Person {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Your task is to complete this implementation in order for the line `let p =
|
|
||||||
// Person::from("Mark,20")` to compile Please note that you'll need to parse the
|
// Your task is to complete this implementation in order for the line `let p1 =
|
||||||
|
// Person::from("Mark,20")` to compile. Please note that you'll need to parse the
|
||||||
// age component into a `usize` with something like `"4".parse::<usize>()`. The
|
// age component into a `usize` with something like `"4".parse::<usize>()`. The
|
||||||
// outcome of this needs to be handled appropriately.
|
// outcome of this needs to be handled appropriately.
|
||||||
//
|
//
|
||||||
|
@ -43,8 +44,7 @@ impl Default for Person {
|
||||||
// I AM NOT DONE
|
// I AM NOT DONE
|
||||||
|
|
||||||
impl From<&str> for Person {
|
impl From<&str> for Person {
|
||||||
fn from(s: &str) -> Person {
|
fn from(s: &str) -> Person {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -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, "Mike");
|
assert_eq!(p.name, "John");
|
||||||
assert_eq!(p.age, 32);
|
assert_eq!(p.age, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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,dog");
|
||||||
assert_eq!(p.name, "Mike");
|
assert_eq!(p.name, "John");
|
||||||
assert_eq!(p.age, 32);
|
assert_eq!(p.age, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
| error_handling | §9 |
|
| error_handling | §9 |
|
||||||
| generics | §10 |
|
| generics | §10 |
|
||||||
| traits | §10.2 |
|
| traits | §10.2 |
|
||||||
| tests | §11.1 |
|
|
||||||
| lifetimes | §10.3 |
|
| lifetimes | §10.3 |
|
||||||
|
| tests | §11.1 |
|
||||||
| iterators | §13.2-4 |
|
| iterators | §13.2-4 |
|
||||||
| threads | §16.1-3 |
|
|
||||||
| smart_pointers | §15, §16.3 |
|
| smart_pointers | §15, §16.3 |
|
||||||
|
| threads | §16.1-3 |
|
||||||
| macros | §19.5 |
|
| macros | §19.5 |
|
||||||
| clippy | §21.4 |
|
| clippy | §21.4 |
|
||||||
| conversions | n/a |
|
| conversions | n/a |
|
||||||
|
|
|
@ -145,7 +145,7 @@ after the `->`. This is where the function's return type should be -- take a
|
||||||
look at the `is_even` function for an example!
|
look at 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
|
||||||
for the prices here, since they can't be negative? If so, kudos!"""
|
for the inputs of the functions here, since the original prices shouldn't be negative? If so, kudos!"""
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
name = "functions5"
|
name = "functions5"
|
||||||
|
|
|
@ -137,7 +137,7 @@ fi
|
||||||
|
|
||||||
Path=${1:-rustlings/}
|
Path=${1:-rustlings/}
|
||||||
echo "Cloning Rustlings at $Path..."
|
echo "Cloning Rustlings at $Path..."
|
||||||
git clone -q https://github.com/rust-lang/rustlings "$Path"
|
git clone -q https://github.com/rust-lang/rustlings.git "$Path"
|
||||||
|
|
||||||
cd "$Path"
|
cd "$Path"
|
||||||
|
|
||||||
|
|
170
src/exercise.rs
170
src/exercise.rs
|
@ -1,19 +1,33 @@
|
||||||
use regex::Regex;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::env;
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::fs::{self, remove_file, File};
|
use std::fs::{self, remove_file, File};
|
||||||
use std::io::Read;
|
use std::io::{self, BufRead, BufReader};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{self, Command};
|
use std::process::{self, exit, Command, Stdio};
|
||||||
|
use std::{array, env, mem};
|
||||||
|
use winnow::ascii::{space0, Caseless};
|
||||||
|
use winnow::combinator::opt;
|
||||||
|
use winnow::Parser;
|
||||||
|
|
||||||
const RUSTC_COLOR_ARGS: &[&str] = &["--color", "always"];
|
const RUSTC_COLOR_ARGS: &[&str] = &["--color", "always"];
|
||||||
const RUSTC_EDITION_ARGS: &[&str] = &["--edition", "2021"];
|
const RUSTC_EDITION_ARGS: &[&str] = &["--edition", "2021"];
|
||||||
const RUSTC_NO_DEBUG_ARGS: &[&str] = &["-C", "strip=debuginfo"];
|
const RUSTC_NO_DEBUG_ARGS: &[&str] = &["-C", "strip=debuginfo"];
|
||||||
const I_AM_DONE_REGEX: &str = r"(?m)^\s*///?\s*I\s+AM\s+NOT\s+DONE";
|
|
||||||
const CONTEXT: usize = 2;
|
const CONTEXT: usize = 2;
|
||||||
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/22_clippy/Cargo.toml";
|
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/22_clippy/Cargo.toml";
|
||||||
|
|
||||||
|
// Checks if the line contains the "I AM NOT DONE" comment.
|
||||||
|
fn contains_not_done_comment(input: &str) -> bool {
|
||||||
|
(
|
||||||
|
space0::<_, ()>,
|
||||||
|
"//",
|
||||||
|
opt('/'),
|
||||||
|
space0,
|
||||||
|
Caseless("I AM NOT DONE"),
|
||||||
|
)
|
||||||
|
.parse_next(&mut &*input)
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
// Get a temporary file name that is hopefully unique
|
// Get a temporary file name that is hopefully unique
|
||||||
#[inline]
|
#[inline]
|
||||||
fn temp_file() -> String {
|
fn temp_file() -> String {
|
||||||
|
@ -58,7 +72,7 @@ pub struct Exercise {
|
||||||
|
|
||||||
// An enum to track of the state of an Exercise.
|
// An enum to track of the state of an Exercise.
|
||||||
// An Exercise can be either Done or Pending
|
// An Exercise can be either Done or Pending
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
// The state of the exercise once it's been completed
|
// The state of the exercise once it's been completed
|
||||||
Done,
|
Done,
|
||||||
|
@ -67,7 +81,7 @@ pub enum State {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The context information of a pending exercise
|
// The context information of a pending exercise
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub struct ContextLine {
|
pub struct ContextLine {
|
||||||
// The source code that is still pending completion
|
// The source code that is still pending completion
|
||||||
pub line: String,
|
pub line: String,
|
||||||
|
@ -148,7 +162,10 @@ path = "{}.rs""#,
|
||||||
.args(RUSTC_COLOR_ARGS)
|
.args(RUSTC_COLOR_ARGS)
|
||||||
.args(RUSTC_EDITION_ARGS)
|
.args(RUSTC_EDITION_ARGS)
|
||||||
.args(RUSTC_NO_DEBUG_ARGS)
|
.args(RUSTC_NO_DEBUG_ARGS)
|
||||||
.output()
|
.stdin(Stdio::null())
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.status()
|
||||||
.expect("Failed to compile!");
|
.expect("Failed to compile!");
|
||||||
// Due to an issue with Clippy, a cargo clean is required to catch all lints.
|
// 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
|
// See https://github.com/rust-lang/rust-clippy/issues/2604
|
||||||
|
@ -157,7 +174,10 @@ path = "{}.rs""#,
|
||||||
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()
|
.stdin(Stdio::null())
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.status()
|
||||||
.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])
|
||||||
|
@ -205,51 +225,101 @@ path = "{}.rs""#,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn state(&self) -> State {
|
pub fn state(&self) -> State {
|
||||||
let mut source_file = File::open(&self.path).unwrap_or_else(|e| {
|
let source_file = File::open(&self.path).unwrap_or_else(|e| {
|
||||||
panic!(
|
println!(
|
||||||
"We were unable to open the exercise file {}! {e}",
|
"Failed to open the exercise file {}: {e}",
|
||||||
self.path.display()
|
self.path.display(),
|
||||||
)
|
);
|
||||||
|
exit(1);
|
||||||
});
|
});
|
||||||
|
let mut source_reader = BufReader::new(source_file);
|
||||||
|
|
||||||
let source = {
|
// Read the next line into `buf` without the newline at the end.
|
||||||
let mut s = String::new();
|
let mut read_line = |buf: &mut String| -> io::Result<_> {
|
||||||
source_file.read_to_string(&mut s).unwrap_or_else(|e| {
|
let n = source_reader.read_line(buf)?;
|
||||||
panic!(
|
if buf.ends_with('\n') {
|
||||||
"We were unable to read the exercise file {}! {e}",
|
buf.pop();
|
||||||
self.path.display()
|
if buf.ends_with('\r') {
|
||||||
)
|
buf.pop();
|
||||||
});
|
}
|
||||||
s
|
}
|
||||||
|
Ok(n)
|
||||||
};
|
};
|
||||||
|
|
||||||
let re = Regex::new(I_AM_DONE_REGEX).unwrap();
|
let mut current_line_number: usize = 1;
|
||||||
|
// Keep the last `CONTEXT` lines while iterating over the file lines.
|
||||||
|
let mut prev_lines: [_; CONTEXT] = array::from_fn(|_| String::with_capacity(256));
|
||||||
|
let mut line = String::with_capacity(256);
|
||||||
|
|
||||||
if !re.is_match(&source) {
|
loop {
|
||||||
|
let n = read_line(&mut line).unwrap_or_else(|e| {
|
||||||
|
println!(
|
||||||
|
"Failed to read the exercise file {}: {e}",
|
||||||
|
self.path.display(),
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reached the end of the file and didn't find the comment.
|
||||||
|
if n == 0 {
|
||||||
return State::Done;
|
return State::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
let matched_line_index = source
|
if contains_not_done_comment(&line) {
|
||||||
.lines()
|
let mut context = Vec::with_capacity(2 * CONTEXT + 1);
|
||||||
|
// Previous lines.
|
||||||
|
for (ind, prev_line) in prev_lines
|
||||||
|
.into_iter()
|
||||||
|
.take(current_line_number - 1)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map(|(i, line)| if re.is_match(line) { Some(i) } else { None })
|
.rev()
|
||||||
.expect("This should not happen at all");
|
{
|
||||||
|
context.push(ContextLine {
|
||||||
|
line: prev_line,
|
||||||
|
number: current_line_number - 1 - ind,
|
||||||
|
important: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let min_line = ((matched_line_index as i32) - (CONTEXT as i32)).max(0) as usize;
|
// Current line.
|
||||||
let max_line = matched_line_index + CONTEXT;
|
context.push(ContextLine {
|
||||||
|
line,
|
||||||
|
number: current_line_number,
|
||||||
|
important: true,
|
||||||
|
});
|
||||||
|
|
||||||
let context = source
|
// Next lines.
|
||||||
.lines()
|
for ind in 0..CONTEXT {
|
||||||
.enumerate()
|
let mut next_line = String::with_capacity(256);
|
||||||
.filter(|&(i, _)| i >= min_line && i <= max_line)
|
let Ok(n) = read_line(&mut next_line) else {
|
||||||
.map(|(i, line)| ContextLine {
|
// If an error occurs, just ignore the next lines.
|
||||||
line: line.to_string(),
|
break;
|
||||||
number: i + 1,
|
};
|
||||||
important: i == matched_line_index,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
State::Pending(context)
|
// Reached the end of the file.
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.push(ContextLine {
|
||||||
|
line: next_line,
|
||||||
|
number: current_line_number + 1 + ind,
|
||||||
|
important: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return State::Pending(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_line_number += 1;
|
||||||
|
// Add the current line as a previous line and shift the older lines by one.
|
||||||
|
for prev_line in &mut prev_lines {
|
||||||
|
mem::swap(&mut line, prev_line);
|
||||||
|
}
|
||||||
|
// The current line now contains the oldest previous line.
|
||||||
|
// Recycle it for reading the next line.
|
||||||
|
line.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the exercise looks to be solved using self.state()
|
// Check that the exercise looks to be solved using self.state()
|
||||||
|
@ -375,4 +445,20 @@ mod test {
|
||||||
let out = exercise.compile().unwrap().run().unwrap();
|
let out = exercise.compile().unwrap().run().unwrap();
|
||||||
assert!(out.stdout.contains("THIS TEST TOO SHALL PASS"));
|
assert!(out.stdout.contains("THIS TEST TOO SHALL PASS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_not_done() {
|
||||||
|
assert!(contains_not_done_comment("// I AM NOT DONE"));
|
||||||
|
assert!(contains_not_done_comment("/// I AM NOT DONE"));
|
||||||
|
assert!(contains_not_done_comment("// I AM NOT DONE"));
|
||||||
|
assert!(contains_not_done_comment("/// I AM NOT DONE"));
|
||||||
|
assert!(contains_not_done_comment("// I AM NOT DONE "));
|
||||||
|
assert!(contains_not_done_comment("// I AM NOT DONE!"));
|
||||||
|
assert!(contains_not_done_comment("// I am not done"));
|
||||||
|
assert!(contains_not_done_comment("// i am NOT done"));
|
||||||
|
|
||||||
|
assert!(!contains_not_done_comment("I AM NOT DONE"));
|
||||||
|
assert!(!contains_not_done_comment("// NOT DONE"));
|
||||||
|
assert!(!contains_not_done_comment("DONE"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
184
src/main.rs
184
src/main.rs
|
@ -1,16 +1,18 @@
|
||||||
use crate::exercise::{Exercise, ExerciseList};
|
use crate::exercise::{Exercise, ExerciseList};
|
||||||
use crate::project::RustAnalyzerProject;
|
use crate::project::write_project_json;
|
||||||
use crate::run::{reset, run};
|
use crate::run::{reset, run};
|
||||||
use crate::verify::verify;
|
use crate::verify::verify;
|
||||||
|
use anyhow::Result;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use console::Emoji;
|
use console::Emoji;
|
||||||
use notify_debouncer_mini::notify::{self, RecursiveMode};
|
use notify_debouncer_mini::notify::{self, RecursiveMode};
|
||||||
use notify_debouncer_mini::{new_debouncer, DebouncedEventKind};
|
use notify_debouncer_mini::{new_debouncer, DebouncedEventKind};
|
||||||
|
use shlex::Shlex;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, prelude::*};
|
use std::io::{self, prelude::*};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::Command;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::mpsc::{channel, RecvTimeoutError};
|
use std::sync::mpsc::{channel, RecvTimeoutError};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -84,31 +86,32 @@ enum Subcommands {
|
||||||
Lsp,
|
Lsp,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
if args.command.is_none() {
|
if args.command.is_none() {
|
||||||
println!("\n{WELCOME}\n");
|
println!("\n{WELCOME}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Path::new("info.toml").exists() {
|
if which::which("rustc").is_err() {
|
||||||
println!(
|
|
||||||
"{} must be run from the rustlings directory",
|
|
||||||
std::env::current_exe().unwrap().to_str().unwrap()
|
|
||||||
);
|
|
||||||
println!("Try `cd rustlings/`!");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rustc_exists() {
|
|
||||||
println!("We cannot find `rustc`.");
|
println!("We cannot find `rustc`.");
|
||||||
println!("Try running `rustc --version` to diagnose your problem.");
|
println!("Try running `rustc --version` to diagnose your problem.");
|
||||||
println!("For instructions on how to install Rust, check the README.");
|
println!("For instructions on how to install Rust, check the README.");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let toml_str = &fs::read_to_string("info.toml").unwrap();
|
let info_file = fs::read_to_string("info.toml").unwrap_or_else(|e| {
|
||||||
let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises;
|
match e.kind() {
|
||||||
|
io::ErrorKind::NotFound => println!(
|
||||||
|
"The program must be run from the rustlings directory\nTry `cd rustlings/`!",
|
||||||
|
),
|
||||||
|
_ => println!("Failed to read the info.toml file: {e}"),
|
||||||
|
}
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
let exercises = toml_edit::de::from_str::<ExerciseList>(&info_file)
|
||||||
|
.unwrap()
|
||||||
|
.exercises;
|
||||||
let verbose = args.nocapture;
|
let verbose = args.nocapture;
|
||||||
|
|
||||||
let command = args.command.unwrap_or_else(|| {
|
let command = args.command.unwrap_or_else(|| {
|
||||||
|
@ -128,31 +131,43 @@ fn main() {
|
||||||
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 = filter.clone().unwrap_or_default().to_lowercase();
|
let lowercase_filter = filter
|
||||||
exercises.iter().for_each(|e| {
|
.as_ref()
|
||||||
let fname = format!("{}", e.path.display());
|
.map(|s| s.to_lowercase())
|
||||||
let filter_cond = filters
|
.unwrap_or_default();
|
||||||
|
let filters = lowercase_filter
|
||||||
.split(',')
|
.split(',')
|
||||||
.filter(|f| !f.trim().is_empty())
|
.filter_map(|f| {
|
||||||
.any(|f| e.name.contains(f) || fname.contains(f));
|
let f = f.trim();
|
||||||
let status = if e.looks_done() {
|
if f.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for exercise in &exercises {
|
||||||
|
let fname = exercise.path.to_string_lossy();
|
||||||
|
let filter_cond = filters
|
||||||
|
.iter()
|
||||||
|
.any(|f| exercise.name.contains(f) || fname.contains(f));
|
||||||
|
let looks_done = exercise.looks_done();
|
||||||
|
let status = if looks_done {
|
||||||
exercises_done += 1;
|
exercises_done += 1;
|
||||||
"Done"
|
"Done"
|
||||||
} else {
|
} else {
|
||||||
"Pending"
|
"Pending"
|
||||||
};
|
};
|
||||||
let solve_cond = {
|
let solve_cond =
|
||||||
(e.looks_done() && solved)
|
(looks_done && solved) || (!looks_done && unsolved) || (!solved && !unsolved);
|
||||||
|| (!e.looks_done() && unsolved)
|
|
||||||
|| (!solved && !unsolved)
|
|
||||||
};
|
|
||||||
if solve_cond && (filter_cond || filter.is_none()) {
|
if solve_cond && (filter_cond || filter.is_none()) {
|
||||||
let line = if paths {
|
let line = if paths {
|
||||||
format!("{fname}\n")
|
format!("{fname}\n")
|
||||||
} else if names {
|
} else if names {
|
||||||
format!("{}\n", e.name)
|
format!("{}\n", exercise.name)
|
||||||
} else {
|
} else {
|
||||||
format!("{:<17}\t{fname:<46}\t{status:<7}\n", e.name)
|
format!("{:<17}\t{fname:<46}\t{status:<7}\n", exercise.name)
|
||||||
};
|
};
|
||||||
// Somehow using println! leads to the binary panicking
|
// Somehow using println! leads to the binary panicking
|
||||||
// when its output is piped.
|
// when its output is piped.
|
||||||
|
@ -168,7 +183,8 @@ fn main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
let percentage_progress = exercises_done as f32 / exercises.len() as f32 * 100.0;
|
let percentage_progress = exercises_done as f32 / exercises.len() as f32 * 100.0;
|
||||||
println!(
|
println!(
|
||||||
"Progress: You completed {} / {} exercises ({:.1} %).",
|
"Progress: You completed {} / {} exercises ({:.1} %).",
|
||||||
|
@ -203,30 +219,17 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Subcommands::Lsp => {
|
Subcommands::Lsp => {
|
||||||
let mut project = RustAnalyzerProject::new();
|
if let Err(e) = write_project_json(exercises) {
|
||||||
project
|
println!("Failed to write rust-project.json to disk for rust-analyzer: {e}");
|
||||||
.get_sysroot_src()
|
|
||||||
.expect("Couldn't find toolchain path, do you have `rustc` installed?");
|
|
||||||
project
|
|
||||||
.exercises_to_json()
|
|
||||||
.expect("Couldn't parse rustlings exercises files");
|
|
||||||
|
|
||||||
if project.crates.is_empty() {
|
|
||||||
println!("Failed find any exercises, make sure you're in the `rustlings` folder");
|
|
||||||
} else if project.write_to_disk().is_err() {
|
|
||||||
println!("Failed to write rust-project.json to disk for rust-analyzer");
|
|
||||||
} else {
|
} else {
|
||||||
println!("Successfully generated rust-project.json");
|
println!("Successfully generated rust-project.json");
|
||||||
println!("rust-analyzer will now parse exercises, restart your language server or editor")
|
println!("rust-analyzer will now parse exercises, restart your language server or editor");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Subcommands::Watch { success_hints } => match watch(&exercises, verbose, 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 {e:?}.");
|
||||||
"Error: Could not watch your progress. Error message was {:?}.",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
println!("Most likely you've run out of disk space or your 'inotify limit' has been reached.");
|
println!("Most likely you've run out of disk space or your 'inotify limit' has been reached.");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -243,18 +246,28 @@ fn main() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_watch_shell(
|
fn spawn_watch_shell(
|
||||||
failed_exercise_hint: &Arc<Mutex<Option<String>>>,
|
failed_exercise_hint: Arc<Mutex<Option<String>>>,
|
||||||
should_quit: Arc<AtomicBool>,
|
should_quit: Arc<AtomicBool>,
|
||||||
) {
|
) {
|
||||||
let failed_exercise_hint = Arc::clone(failed_exercise_hint);
|
|
||||||
println!("Welcome to watch mode! You can type 'help' to get an overview of the commands you can use here.");
|
println!("Welcome to watch mode! You can type 'help' to get an overview of the commands you can use here.");
|
||||||
thread::spawn(move || loop {
|
|
||||||
let mut input = String::new();
|
thread::spawn(move || {
|
||||||
match io::stdin().read_line(&mut input) {
|
let mut input = String::with_capacity(32);
|
||||||
Ok(_) => {
|
let mut stdin = io::stdin().lock();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// Recycle input buffer.
|
||||||
|
input.clear();
|
||||||
|
|
||||||
|
if let Err(e) = stdin.read_line(&mut input) {
|
||||||
|
println!("error reading command: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
let input = input.trim();
|
let input = input.trim();
|
||||||
if input == "hint" {
|
if input == "hint" {
|
||||||
if let Some(hint) = &*failed_exercise_hint.lock().unwrap() {
|
if let Some(hint) = &*failed_exercise_hint.lock().unwrap() {
|
||||||
|
@ -262,37 +275,31 @@ fn spawn_watch_shell(
|
||||||
}
|
}
|
||||||
} else if input == "clear" {
|
} else if input == "clear" {
|
||||||
println!("\x1B[2J\x1B[1;1H");
|
println!("\x1B[2J\x1B[1;1H");
|
||||||
} else if input.eq("quit") {
|
} else if input == "quit" {
|
||||||
should_quit.store(true, Ordering::SeqCst);
|
should_quit.store(true, Ordering::SeqCst);
|
||||||
println!("Bye!");
|
println!("Bye!");
|
||||||
} else if input.eq("help") {
|
} else if input == "help" {
|
||||||
println!("Commands available to you in watch mode:");
|
println!("{WATCH_MODE_HELP_MESSAGE}");
|
||||||
println!(" hint - prints the current exercise's hint");
|
|
||||||
println!(" clear - clears the screen");
|
|
||||||
println!(" quit - quits watch mode");
|
|
||||||
println!(" !<cmd> - executes a command, like `!rustc --explain E0381`");
|
|
||||||
println!(" help - displays this help message");
|
|
||||||
println!();
|
|
||||||
println!("Watch mode automatically re-evaluates the current exercise");
|
|
||||||
println!("when you edit a file's contents.")
|
|
||||||
} else if let Some(cmd) = input.strip_prefix('!') {
|
} else if let Some(cmd) = input.strip_prefix('!') {
|
||||||
let parts: Vec<&str> = cmd.split_whitespace().collect();
|
let mut parts = Shlex::new(cmd);
|
||||||
if parts.is_empty() {
|
|
||||||
|
let Some(program) = parts.next() else {
|
||||||
println!("no command provided");
|
println!("no command provided");
|
||||||
} else if let Err(e) = Command::new(parts[0]).args(&parts[1..]).status() {
|
continue;
|
||||||
println!("failed to execute command `{}`: {}", cmd, e);
|
};
|
||||||
|
|
||||||
|
if let Err(e) = Command::new(program).args(parts).status() {
|
||||||
|
println!("failed to execute command `{cmd}`: {e}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("unknown command: {input}");
|
println!("unknown command: {input}\n{WATCH_MODE_HELP_MESSAGE}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(error) => println!("error reading command: {error}"),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_exercise<'a>(name: &str, exercises: &'a [Exercise]) -> &'a Exercise {
|
fn find_exercise<'a>(name: &str, exercises: &'a [Exercise]) -> &'a Exercise {
|
||||||
if name.eq("next") {
|
if name == "next" {
|
||||||
exercises
|
exercises
|
||||||
.iter()
|
.iter()
|
||||||
.find(|e| !e.looks_done())
|
.find(|e| !e.looks_done())
|
||||||
|
@ -338,7 +345,6 @@ fn watch(
|
||||||
|
|
||||||
clear_screen();
|
clear_screen();
|
||||||
|
|
||||||
let to_owned_hint = |t: &Exercise| t.hint.to_owned();
|
|
||||||
let failed_exercise_hint = match verify(
|
let failed_exercise_hint = match verify(
|
||||||
exercises.iter(),
|
exercises.iter(),
|
||||||
(0, exercises.len()),
|
(0, exercises.len()),
|
||||||
|
@ -346,9 +352,9 @@ fn watch(
|
||||||
success_hints,
|
success_hints,
|
||||||
) {
|
) {
|
||||||
Ok(_) => return Ok(WatchStatus::Finished),
|
Ok(_) => return Ok(WatchStatus::Finished),
|
||||||
Err(exercise) => Arc::new(Mutex::new(Some(to_owned_hint(exercise)))),
|
Err(exercise) => Arc::new(Mutex::new(Some(exercise.hint.clone()))),
|
||||||
};
|
};
|
||||||
spawn_watch_shell(&failed_exercise_hint, Arc::clone(&should_quit));
|
spawn_watch_shell(Arc::clone(&failed_exercise_hint), Arc::clone(&should_quit));
|
||||||
loop {
|
loop {
|
||||||
match rx.recv_timeout(Duration::from_secs(1)) {
|
match rx.recv_timeout(Duration::from_secs(1)) {
|
||||||
Ok(event) => match event {
|
Ok(event) => match event {
|
||||||
|
@ -383,7 +389,7 @@ fn watch(
|
||||||
Err(exercise) => {
|
Err(exercise) => {
|
||||||
let mut failed_exercise_hint =
|
let mut failed_exercise_hint =
|
||||||
failed_exercise_hint.lock().unwrap();
|
failed_exercise_hint.lock().unwrap();
|
||||||
*failed_exercise_hint = Some(to_owned_hint(exercise));
|
*failed_exercise_hint = Some(exercise.hint.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,19 +409,7 @@ fn watch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustc_exists() -> bool {
|
const DEFAULT_OUT: &str = "Thanks for installing Rustlings!
|
||||||
Command::new("rustc")
|
|
||||||
.args(["--version"])
|
|
||||||
.stdout(Stdio::null())
|
|
||||||
.stderr(Stdio::null())
|
|
||||||
.stdin(Stdio::null())
|
|
||||||
.spawn()
|
|
||||||
.and_then(|mut child| child.wait())
|
|
||||||
.map(|status| status.success())
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_OUT: &str = r#"Thanks for installing Rustlings!
|
|
||||||
|
|
||||||
Is this your first time? Don't worry, Rustlings was made for beginners! We are
|
Is this your first time? Don't worry, Rustlings was made for beginners! We are
|
||||||
going to teach you a lot of things about Rust, but before we can get
|
going to teach you a lot of things about Rust, but before we can get
|
||||||
|
@ -441,7 +435,7 @@ started, here's a couple of notes about how Rustlings operates:
|
||||||
autocompletion, run the command `rustlings lsp`.
|
autocompletion, run the command `rustlings lsp`.
|
||||||
|
|
||||||
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 = "+----------------------------------------------------+
|
const FENISH_LINE: &str = "+----------------------------------------------------+
|
||||||
| You made it to the Fe-nish line! |
|
| You made it to the Fe-nish line! |
|
||||||
|
@ -477,3 +471,13 @@ const WELCOME: &str = r" welcome to...
|
||||||
| | | |_| \__ \ |_| | | | | | (_| \__ \
|
| | | |_| \__ \ |_| | | | | | (_| \__ \
|
||||||
|_| \__,_|___/\__|_|_|_| |_|\__, |___/
|
|_| \__,_|___/\__|_|_|_| |_|\__, |___/
|
||||||
|___/";
|
|___/";
|
||||||
|
|
||||||
|
const WATCH_MODE_HELP_MESSAGE: &str = "Commands available to you in watch mode:
|
||||||
|
hint - prints the current exercise's hint
|
||||||
|
clear - clears the screen
|
||||||
|
quit - quits watch mode
|
||||||
|
!<cmd> - executes a command, like `!rustc --explain E0381`
|
||||||
|
help - displays this help message
|
||||||
|
|
||||||
|
Watch mode automatically re-evaluates the current exercise
|
||||||
|
when you edit a file's contents.";
|
||||||
|
|
132
src/project.rs
132
src/project.rs
|
@ -1,99 +1,83 @@
|
||||||
use glob::glob;
|
use anyhow::{Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::Serialize;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
use crate::exercise::Exercise;
|
||||||
|
|
||||||
/// Contains the structure of resulting rust-project.json file
|
/// Contains the structure of resulting rust-project.json file
|
||||||
/// and functions to build the data required to create the file
|
/// and functions to build the data required to create the file
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize)]
|
||||||
pub struct RustAnalyzerProject {
|
struct RustAnalyzerProject {
|
||||||
sysroot_src: String,
|
sysroot_src: PathBuf,
|
||||||
pub crates: Vec<Crate>,
|
crates: Vec<Crate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Crate {
|
struct Crate {
|
||||||
root_module: String,
|
root_module: PathBuf,
|
||||||
edition: String,
|
edition: &'static str,
|
||||||
deps: Vec<String>,
|
// Not used, but required in the JSON file.
|
||||||
cfg: Vec<String>,
|
deps: Vec<()>,
|
||||||
|
// Only `test` is used for all crates.
|
||||||
|
// Therefore, an array is used instead of a `Vec`.
|
||||||
|
cfg: [&'static str; 1],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RustAnalyzerProject {
|
impl RustAnalyzerProject {
|
||||||
pub fn new() -> RustAnalyzerProject {
|
fn build(exercises: Vec<Exercise>) -> Result<Self> {
|
||||||
RustAnalyzerProject {
|
let crates = exercises
|
||||||
sysroot_src: String::new(),
|
.into_iter()
|
||||||
crates: Vec::new(),
|
.map(|exercise| Crate {
|
||||||
}
|
root_module: exercise.path,
|
||||||
}
|
edition: "2021",
|
||||||
|
|
||||||
/// Write rust-project.json to disk
|
|
||||||
pub fn write_to_disk(&self) -> Result<(), std::io::Error> {
|
|
||||||
std::fs::write(
|
|
||||||
"./rust-project.json",
|
|
||||||
serde_json::to_vec(&self).expect("Failed to serialize to JSON"),
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If path contains .rs extension, add a crate to `rust-project.json`
|
|
||||||
fn path_to_json(&mut self, path: PathBuf) -> Result<(), Box<dyn Error>> {
|
|
||||||
if let Some(ext) = path.extension() {
|
|
||||||
if ext == "rs" {
|
|
||||||
self.crates.push(Crate {
|
|
||||||
root_module: path.display().to_string(),
|
|
||||||
edition: "2021".to_string(),
|
|
||||||
deps: Vec::new(),
|
deps: Vec::new(),
|
||||||
// This allows rust_analyzer to work inside #[test] blocks
|
// This allows rust_analyzer to work inside `#[test]` blocks
|
||||||
cfg: vec!["test".to_string()],
|
cfg: ["test"],
|
||||||
})
|
})
|
||||||
}
|
.collect();
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
if let Some(path) = env::var_os("RUST_SRC_PATH") {
|
||||||
}
|
return Ok(Self {
|
||||||
|
sysroot_src: PathBuf::from(path),
|
||||||
/// Parse the exercises folder for .rs files, any matches will create
|
crates,
|
||||||
/// a new `crate` in rust-project.json which allows rust-analyzer to
|
});
|
||||||
/// treat it like a normal binary
|
|
||||||
pub fn exercises_to_json(&mut self) -> Result<(), Box<dyn Error>> {
|
|
||||||
for path in glob("./exercises/**/*")? {
|
|
||||||
self.path_to_json(path?)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use `rustc` to determine the default toolchain
|
|
||||||
pub fn get_sysroot_src(&mut self) -> Result<(), Box<dyn Error>> {
|
|
||||||
// check if RUST_SRC_PATH is set
|
|
||||||
if let Ok(path) = env::var("RUST_SRC_PATH") {
|
|
||||||
self.sysroot_src = path;
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let toolchain = Command::new("rustc")
|
let toolchain = Command::new("rustc")
|
||||||
.arg("--print")
|
.arg("--print")
|
||||||
.arg("sysroot")
|
.arg("sysroot")
|
||||||
.output()?
|
.stderr(Stdio::inherit())
|
||||||
|
.output()
|
||||||
|
.context("Failed to get the sysroot from `rustc`. Do you have `rustc` installed?")?
|
||||||
.stdout;
|
.stdout;
|
||||||
|
|
||||||
let toolchain = String::from_utf8_lossy(&toolchain);
|
let toolchain =
|
||||||
let mut whitespace_iter = toolchain.split_whitespace();
|
String::from_utf8(toolchain).context("The toolchain path is invalid UTF8")?;
|
||||||
|
let toolchain = toolchain.trim_end();
|
||||||
|
println!("Determined toolchain: {toolchain}\n");
|
||||||
|
|
||||||
let toolchain = whitespace_iter.next().unwrap_or(&toolchain);
|
let mut sysroot_src = PathBuf::with_capacity(256);
|
||||||
|
sysroot_src.extend([toolchain, "lib", "rustlib", "src", "rust", "library"]);
|
||||||
|
|
||||||
println!("Determined toolchain: {}\n", &toolchain);
|
Ok(Self {
|
||||||
|
sysroot_src,
|
||||||
|
crates,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write `rust-project.json` to disk.
|
||||||
|
pub fn write_project_json(exercises: Vec<Exercise>) -> Result<()> {
|
||||||
|
let content = RustAnalyzerProject::build(exercises)?;
|
||||||
|
|
||||||
|
// Using the capacity 2^14 since the file length in bytes is higher than 2^13.
|
||||||
|
// The final length is not known exactly because it depends on the user's sysroot path,
|
||||||
|
// the current number of exercises etc.
|
||||||
|
let mut buf = Vec::with_capacity(1 << 14);
|
||||||
|
serde_json::to_writer(&mut buf, &content)?;
|
||||||
|
std::fs::write("rust-project.json", buf)?;
|
||||||
|
|
||||||
self.sysroot_src = (std::path::Path::new(toolchain)
|
|
||||||
.join("lib")
|
|
||||||
.join("rustlib")
|
|
||||||
.join("src")
|
|
||||||
.join("rust")
|
|
||||||
.join("library")
|
|
||||||
.to_string_lossy())
|
|
||||||
.to_string();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,8 @@ pub fn run(exercise: &Exercise, verbose: bool) -> Result<(), ()> {
|
||||||
// Resets the exercise by stashing the changes.
|
// Resets the exercise by stashing the changes.
|
||||||
pub fn reset(exercise: &Exercise) -> Result<(), ()> {
|
pub fn reset(exercise: &Exercise) -> Result<(), ()> {
|
||||||
let command = Command::new("git")
|
let command = Command::new("git")
|
||||||
.args(["stash", "--"])
|
.arg("stash")
|
||||||
|
.arg("--")
|
||||||
.arg(&exercise.path)
|
.arg(&exercise.path)
|
||||||
.spawn();
|
.spawn();
|
||||||
|
|
||||||
|
|
31
src/ui.rs
31
src/ui.rs
|
@ -1,33 +1,28 @@
|
||||||
macro_rules! warn {
|
macro_rules! print_emoji {
|
||||||
($fmt:literal, $ex:expr) => {{
|
($emoji:expr, $sign:expr, $color: ident, $fmt:literal, $ex:expr) => {{
|
||||||
use console::{style, Emoji};
|
use console::{style, Emoji};
|
||||||
use std::env;
|
use std::env;
|
||||||
let formatstr = format!($fmt, $ex);
|
let formatstr = format!($fmt, $ex);
|
||||||
if env::var("NO_EMOJI").is_ok() {
|
if env::var("NO_EMOJI").is_ok() {
|
||||||
println!("{} {}", style("!").red(), style(formatstr).red());
|
println!("{} {}", style($sign).$color(), style(formatstr).$color());
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
style(Emoji("⚠️ ", "!")).red(),
|
style(Emoji($emoji, $sign)).$color(),
|
||||||
style(formatstr).red()
|
style(formatstr).$color()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! success {
|
macro_rules! warn {
|
||||||
($fmt:literal, $ex:expr) => {{
|
($fmt:literal, $ex:expr) => {{
|
||||||
use console::{style, Emoji};
|
print_emoji!("⚠️ ", "!", red, $fmt, $ex);
|
||||||
use std::env;
|
}};
|
||||||
let formatstr = format!($fmt, $ex);
|
}
|
||||||
if env::var("NO_EMOJI").is_ok() {
|
|
||||||
println!("{} {}", style("✓").green(), style(formatstr).green());
|
macro_rules! success {
|
||||||
} else {
|
($fmt:literal, $ex:expr) => {{
|
||||||
println!(
|
print_emoji!("✅ ", "✓", green, $fmt, $ex);
|
||||||
"{} {}",
|
|
||||||
style(Emoji("✅", "✓")).green(),
|
|
||||||
style(formatstr).green()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn verify<'a>(
|
||||||
.progress_chars("#>-"),
|
.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!("({percentage:.1} %)"));
|
||||||
|
|
||||||
for exercise in exercises {
|
for exercise in exercises {
|
||||||
let compile_result = match exercise.mode {
|
let compile_result = match exercise.mode {
|
||||||
|
@ -37,11 +37,21 @@ pub fn verify<'a>(
|
||||||
}
|
}
|
||||||
percentage += 100.0 / total as f32;
|
percentage += 100.0 / total as f32;
|
||||||
bar.inc(1);
|
bar.inc(1);
|
||||||
bar.set_message(format!("({:.1} %)", percentage));
|
bar.set_message(format!("({percentage:.1} %)"));
|
||||||
|
if bar.position() == total as u64 {
|
||||||
|
println!(
|
||||||
|
"Progress: You completed {} / {} exercises ({:.1} %).",
|
||||||
|
bar.position(),
|
||||||
|
total,
|
||||||
|
percentage
|
||||||
|
);
|
||||||
|
bar.finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
enum RunMode {
|
enum RunMode {
|
||||||
Interactive,
|
Interactive,
|
||||||
NonInteractive,
|
NonInteractive,
|
||||||
|
@ -115,7 +125,7 @@ fn compile_and_test(
|
||||||
if verbose {
|
if verbose {
|
||||||
println!("{}", output.stdout);
|
println!("{}", output.stdout);
|
||||||
}
|
}
|
||||||
if let RunMode::Interactive = run_mode {
|
if run_mode == RunMode::Interactive {
|
||||||
Ok(prompt_for_completion(exercise, None, success_hints))
|
Ok(prompt_for_completion(exercise, None, success_hints))
|
||||||
} else {
|
} else {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
@ -182,27 +192,25 @@ fn prompt_for_completion(
|
||||||
Mode::Test => "The code is compiling, and the tests pass!",
|
Mode::Test => "The code is compiling, and the tests pass!",
|
||||||
Mode::Clippy => clippy_success_msg,
|
Mode::Clippy => clippy_success_msg,
|
||||||
};
|
};
|
||||||
println!();
|
|
||||||
if no_emoji {
|
if no_emoji {
|
||||||
println!("~*~ {success_msg} ~*~")
|
println!("\n~*~ {success_msg} ~*~\n");
|
||||||
} else {
|
} else {
|
||||||
println!("🎉 🎉 {success_msg} 🎉 🎉")
|
println!("\n🎉 🎉 {success_msg} 🎉 🎉\n");
|
||||||
}
|
}
|
||||||
println!();
|
|
||||||
|
|
||||||
if let Some(output) = prompt_output {
|
if let Some(output) = prompt_output {
|
||||||
println!("Output:");
|
println!(
|
||||||
println!("{}", separator());
|
"Output:\n{separator}\n{output}\n{separator}\n",
|
||||||
println!("{output}");
|
separator = separator(),
|
||||||
println!("{}", separator());
|
);
|
||||||
println!();
|
|
||||||
}
|
}
|
||||||
if success_hints {
|
if success_hints {
|
||||||
println!("Hints:");
|
println!(
|
||||||
println!("{}", separator());
|
"Hints:\n{separator}\n{}\n{separator}\n",
|
||||||
println!("{}", exercise.hint);
|
exercise.hint,
|
||||||
println!("{}", separator());
|
separator = separator(),
|
||||||
println!();
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("You can keep working on this exercise,");
|
println!("You can keep working on this exercise,");
|
||||||
|
@ -215,14 +223,14 @@ fn prompt_for_completion(
|
||||||
let formatted_line = if context_line.important {
|
let formatted_line = if context_line.important {
|
||||||
format!("{}", style(context_line.line).bold())
|
format!("{}", style(context_line.line).bold())
|
||||||
} else {
|
} else {
|
||||||
context_line.line.to_string()
|
context_line.line
|
||||||
};
|
};
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{:>2} {} {}",
|
"{:>2} {} {}",
|
||||||
style(context_line.number).blue().bold(),
|
style(context_line.number).blue().bold(),
|
||||||
style("|").blue(),
|
style("|").blue(),
|
||||||
formatted_line
|
formatted_line,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue