mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
Merge pull request #1119 from kbknapp/case-insensitive
Case insensitive
This commit is contained in:
commit
bc9ab21934
36 changed files with 2541 additions and 1722 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -1,23 +1,23 @@
|
|||
<a name="2.28.0"></a>
|
||||
## 2.28.0 (2017-11-27)
|
||||
## 2.28.0 (2017-11-28)
|
||||
|
||||
The minimum required Rust is now 1.20. This was done to start using bitflags 1.0 and having >1.0 deps is a *very good* thing!
|
||||
|
||||
#### Documentation
|
||||
|
||||
#### API Additions
|
||||
|
||||
* Adds the traits to be used with the `clap-derive` crate to be able to use Custom Derive ([6f4c3412](https://github.com/kbknapp/clap-rs/commit/6f4c3412415e882f5ca2cc3fbd6d4dce79440828))
|
||||
* changes the demo version to 2.28 to stay in sync ([ce6ca492](https://github.com/kbknapp/clap-rs/commit/ce6ca492c7510ab6474075806360b96081b021a9))
|
||||
* Fix URL path to github hosted files ([ce72aada](https://github.com/kbknapp/clap-rs/commit/ce72aada56a9581d4a6cb4bf9bdb861c3906f8df), closes [#1106](https://github.com/kbknapp/clap-rs/issues/1106))
|
||||
* fix typo ([002b07fc](https://github.com/kbknapp/clap-rs/commit/002b07fc98a1c85acb66296b1eec0b2aba906125))
|
||||
* **README.md:** updates the readme and pulls out some redundant sections ([db6caf86](https://github.com/kbknapp/clap-rs/commit/db6caf8663747e679d2f4ed3bd127f33476754aa))
|
||||
|
||||
#### Improvements
|
||||
|
||||
* adds '[SUBCOMMAND]' to usage strings with only AppSettings::AllowExternalSubcommands is used with no other subcommands ([e78bb757](https://github.com/kbknapp/clap-rs/commit/e78bb757a3df16e82d539e450c06767a6bfcf859), closes [#1093](https://github.com/kbknapp/clap-rs/issues/1093))
|
||||
* uses `.bash` for Bash completion scripts now instead of `.bash-completion` due to convention and `.bash-completion` not being supported by completion projects ([4740cde4](https://github.com/kbknapp/clap-rs/commit/4740cde404121a443c64d644eb4a0722c0b0a823)
|
||||
|
||||
#### Documentation
|
||||
#### API Additions
|
||||
|
||||
* Fix URL path to github hosted files ([ce72aada](https://github.com/kbknapp/clap-rs/commit/ce72aada56a9581d4a6cb4bf9bdb861c3906f8df), closes [#1106](https://github.com/kbknapp/clap-rs/issues/1106))
|
||||
* fix typo ([002b07fc](https://github.com/kbknapp/clap-rs/commit/002b07fc98a1c85acb66296b1eec0b2aba906125))
|
||||
* **README.md:** updates the readme and pulls out some redundant sections ([db6caf86](https://github.com/kbknapp/clap-rs/commit/db6caf8663747e679d2f4ed3bd127f33476754aa))
|
||||
* Adds Arg::case_insensitive(bool) which allows matching Arg::possible_values without worrying about ASCII case ([1fec268e](https://github.com/kbknapp/clap-rs/commit/1fec268e51736602e38e67c76266f439e2e0ef12), closes [#1118](https://github.com/kbknapp/clap-rs/issues/1118))
|
||||
* Adds the traits to be used with the clap-derive crate to be able to use Custom Derive ([6f4c3412](https://github.com/kbknapp/clap-rs/commit/6f4c3412415e882f5ca2cc3fbd6d4dce79440828))
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
|
@ -25,7 +25,6 @@ The minimum required Rust is now 1.20. This was done to start using bitflags 1.0
|
|||
* fixes a bug that allowed options to pass parsing when no value was provided ([2fb75821](https://github.com/kbknapp/clap-rs/commit/2fb758219c7a60d639da67692e100b855a8165ac), closes [#1105](https://github.com/kbknapp/clap-rs/issues/1105))
|
||||
* ignore PropagateGlobalValuesDown deprecation warning ([f61ce3f5](https://github.com/kbknapp/clap-rs/commit/f61ce3f55fe65e16b3db0bd4facdc4575de22767), closes [#1086](https://github.com/kbknapp/clap-rs/issues/1086))
|
||||
|
||||
|
||||
#### Deps
|
||||
|
||||
* Updates `bitflags` to 1.0
|
||||
|
|
|
@ -9,73 +9,77 @@ the following is a list of contributors:
|
|||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[willmurphyscode](https://github.com/willmurphyscode) |[mgeisler](https://github.com/mgeisler) |[nabijaczleweli](https://github.com/nabijaczleweli) |[Byron](https://github.com/Byron) |[hgrecco](https://github.com/hgrecco) |[bluejekyll](https://github.com/bluejekyll) |
|
||||
|
||||
[<img alt="james-darkfox" src="https://avatars3.githubusercontent.com/u/637155?v=4&s=117" width="117">](https://github.com/james-darkfox) |[<img alt="H2CO3" src="https://avatars2.githubusercontent.com/u/742370?v=4&s=117" width="117">](https://github.com/H2CO3) |[<img alt="nateozem" src="https://avatars2.githubusercontent.com/u/22719441?v=4&s=117" width="117">](https://github.com/nateozem) |[<img alt="glowing-chemist" src="https://avatars0.githubusercontent.com/u/17074682?v=4&s=117" width="117">](https://github.com/glowing-chemist) |[<img alt="Arnavion" src="https://avatars2.githubusercontent.com/u/1096010?v=4&s=117" width="117">](https://github.com/Arnavion) |[<img alt="rtaycher" src="https://avatars0.githubusercontent.com/u/324733?v=4&s=117" width="117">](https://github.com/rtaycher) |
|
||||
[<img alt="ignatenkobrain" src="https://avatars1.githubusercontent.com/u/2866862?v=4&s=117" width="117">](https://github.com/ignatenkobrain) |[<img alt="james-darkfox" src="https://avatars3.githubusercontent.com/u/637155?v=4&s=117" width="117">](https://github.com/james-darkfox) |[<img alt="H2CO3" src="https://avatars2.githubusercontent.com/u/742370?v=4&s=117" width="117">](https://github.com/H2CO3) |[<img alt="nateozem" src="https://avatars2.githubusercontent.com/u/22719441?v=4&s=117" width="117">](https://github.com/nateozem) |[<img alt="glowing-chemist" src="https://avatars0.githubusercontent.com/u/17074682?v=4&s=117" width="117">](https://github.com/glowing-chemist) |[<img alt="rtaycher" src="https://avatars0.githubusercontent.com/u/324733?v=4&s=117" width="117">](https://github.com/rtaycher) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[james-darkfox](https://github.com/james-darkfox) |[H2CO3](https://github.com/H2CO3) |[nateozem](https://github.com/nateozem) |[glowing-chemist](https://github.com/glowing-chemist) |[Arnavion](https://github.com/Arnavion) |[rtaycher](https://github.com/rtaycher) |
|
||||
[ignatenkobrain](https://github.com/ignatenkobrain) |[james-darkfox](https://github.com/james-darkfox) |[H2CO3](https://github.com/H2CO3) |[nateozem](https://github.com/nateozem) |[glowing-chemist](https://github.com/glowing-chemist) |[rtaycher](https://github.com/rtaycher) |
|
||||
|
||||
[<img alt="japaric" src="https://avatars3.githubusercontent.com/u/5018213?v=4&s=117" width="117">](https://github.com/japaric) |[<img alt="untitaker" src="https://avatars0.githubusercontent.com/u/837573?v=4&s=117" width="117">](https://github.com/untitaker) |[<img alt="afiune" src="https://avatars0.githubusercontent.com/u/5712253?v=4&s=117" width="117">](https://github.com/afiune) |[<img alt="crazymerlyn" src="https://avatars1.githubusercontent.com/u/6919679?v=4&s=117" width="117">](https://github.com/crazymerlyn) |[<img alt="SuperFluffy" src="https://avatars0.githubusercontent.com/u/701177?v=4&s=117" width="117">](https://github.com/SuperFluffy) |[<img alt="malbarbo" src="https://avatars3.githubusercontent.com/u/1678126?v=4&s=117" width="117">](https://github.com/malbarbo) |
|
||||
[<img alt="Arnavion" src="https://avatars2.githubusercontent.com/u/1096010?v=4&s=117" width="117">](https://github.com/Arnavion) |[<img alt="japaric" src="https://avatars3.githubusercontent.com/u/5018213?v=4&s=117" width="117">](https://github.com/japaric) |[<img alt="untitaker" src="https://avatars0.githubusercontent.com/u/837573?v=4&s=117" width="117">](https://github.com/untitaker) |[<img alt="afiune" src="https://avatars0.githubusercontent.com/u/5712253?v=4&s=117" width="117">](https://github.com/afiune) |[<img alt="crazymerlyn" src="https://avatars1.githubusercontent.com/u/6919679?v=4&s=117" width="117">](https://github.com/crazymerlyn) |[<img alt="SuperFluffy" src="https://avatars0.githubusercontent.com/u/701177?v=4&s=117" width="117">](https://github.com/SuperFluffy) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[japaric](https://github.com/japaric) |[untitaker](https://github.com/untitaker) |[afiune](https://github.com/afiune) |[crazymerlyn](https://github.com/crazymerlyn) |[SuperFluffy](https://github.com/SuperFluffy) |[malbarbo](https://github.com/malbarbo) |
|
||||
[Arnavion](https://github.com/Arnavion) |[japaric](https://github.com/japaric) |[untitaker](https://github.com/untitaker) |[afiune](https://github.com/afiune) |[crazymerlyn](https://github.com/crazymerlyn) |[SuperFluffy](https://github.com/SuperFluffy) |
|
||||
|
||||
[<img alt="matthiasbeyer" src="https://avatars0.githubusercontent.com/u/427866?v=4&s=117" width="117">](https://github.com/matthiasbeyer) |[<img alt="gohyda" src="https://avatars3.githubusercontent.com/u/10263838?v=4&s=117" width="117">](https://github.com/gohyda) |[<img alt="tshepang" src="https://avatars0.githubusercontent.com/u/588486?v=4&s=117" width="117">](https://github.com/tshepang) |[<img alt="golem131" src="https://avatars3.githubusercontent.com/u/2429587?v=4&s=117" width="117">](https://github.com/golem131) |[<img alt="jimmycuadra" src="https://avatars2.githubusercontent.com/u/122457?v=4&s=117" width="117">](https://github.com/jimmycuadra) |[<img alt="Nemo157" src="https://avatars1.githubusercontent.com/u/81079?v=4&s=117" width="117">](https://github.com/Nemo157) |
|
||||
[<img alt="malbarbo" src="https://avatars3.githubusercontent.com/u/1678126?v=4&s=117" width="117">](https://github.com/malbarbo) |[<img alt="matthiasbeyer" src="https://avatars0.githubusercontent.com/u/427866?v=4&s=117" width="117">](https://github.com/matthiasbeyer) |[<img alt="gohyda" src="https://avatars3.githubusercontent.com/u/10263838?v=4&s=117" width="117">](https://github.com/gohyda) |[<img alt="tshepang" src="https://avatars0.githubusercontent.com/u/588486?v=4&s=117" width="117">](https://github.com/tshepang) |[<img alt="golem131" src="https://avatars3.githubusercontent.com/u/2429587?v=4&s=117" width="117">](https://github.com/golem131) |[<img alt="jimmycuadra" src="https://avatars2.githubusercontent.com/u/122457?v=4&s=117" width="117">](https://github.com/jimmycuadra) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[matthiasbeyer](https://github.com/matthiasbeyer) |[gohyda](https://github.com/gohyda) |[tshepang](https://github.com/tshepang) |[golem131](https://github.com/golem131) |[jimmycuadra](https://github.com/jimmycuadra) |[Nemo157](https://github.com/Nemo157) |
|
||||
[malbarbo](https://github.com/malbarbo) |[matthiasbeyer](https://github.com/matthiasbeyer) |[gohyda](https://github.com/gohyda) |[tshepang](https://github.com/tshepang) |[golem131](https://github.com/golem131) |[jimmycuadra](https://github.com/jimmycuadra) |
|
||||
|
||||
[<img alt="SShrike" src="https://avatars1.githubusercontent.com/u/4061736?v=4&s=117" width="117">](https://github.com/SShrike) |[<img alt="porglezomp" src="https://avatars1.githubusercontent.com/u/1690225?v=4&s=117" width="117">](https://github.com/porglezomp) |[<img alt="wdv4758h" src="https://avatars1.githubusercontent.com/u/2716047?v=4&s=117" width="117">](https://github.com/wdv4758h) |[<img alt="frewsxcv" src="https://avatars2.githubusercontent.com/u/416575?v=4&s=117" width="117">](https://github.com/frewsxcv) |[<img alt="hoodie" src="https://avatars1.githubusercontent.com/u/260370?v=4&s=117" width="117">](https://github.com/hoodie) |[<img alt="huonw" src="https://avatars1.githubusercontent.com/u/1203825?v=4&s=117" width="117">](https://github.com/huonw) |
|
||||
[<img alt="Nemo157" src="https://avatars1.githubusercontent.com/u/81079?v=4&s=117" width="117">](https://github.com/Nemo157) |[<img alt="SShrike" src="https://avatars1.githubusercontent.com/u/4061736?v=4&s=117" width="117">](https://github.com/SShrike) |[<img alt="Eijebong" src="https://avatars2.githubusercontent.com/u/3650385?v=4&s=117" width="117">](https://github.com/Eijebong) |[<img alt="cstorey" src="https://avatars3.githubusercontent.com/u/743059?v=4&s=117" width="117">](https://github.com/cstorey) |[<img alt="wdv4758h" src="https://avatars1.githubusercontent.com/u/2716047?v=4&s=117" width="117">](https://github.com/wdv4758h) |[<img alt="frewsxcv" src="https://avatars2.githubusercontent.com/u/416575?v=4&s=117" width="117">](https://github.com/frewsxcv) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[SShrike](https://github.com/SShrike) |[porglezomp](https://github.com/porglezomp) |[wdv4758h](https://github.com/wdv4758h) |[frewsxcv](https://github.com/frewsxcv) |[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |
|
||||
[Nemo157](https://github.com/Nemo157) |[SShrike](https://github.com/SShrike) |[Eijebong](https://github.com/Eijebong) |[cstorey](https://github.com/cstorey) |[wdv4758h](https://github.com/wdv4758h) |[frewsxcv](https://github.com/frewsxcv) |
|
||||
|
||||
[<img alt="GrappigPanda" src="https://avatars0.githubusercontent.com/u/2055372?v=4&s=117" width="117">](https://github.com/GrappigPanda) |[<img alt="ignatenkobrain" src="https://avatars1.githubusercontent.com/u/2866862?v=4&s=117" width="117">](https://github.com/ignatenkobrain) |[<img alt="shepmaster" src="https://avatars0.githubusercontent.com/u/174509?v=4&s=117" width="117">](https://github.com/shepmaster) |[<img alt="cstorey" src="https://avatars3.githubusercontent.com/u/743059?v=4&s=117" width="117">](https://github.com/cstorey) |[<img alt="kieraneglin" src="https://avatars0.githubusercontent.com/u/569917?v=4&s=117" width="117">](https://github.com/kieraneglin) |[<img alt="musoke" src="https://avatars0.githubusercontent.com/u/16665084?v=4&s=117" width="117">](https://github.com/musoke) |
|
||||
[<img alt="hoodie" src="https://avatars1.githubusercontent.com/u/260370?v=4&s=117" width="117">](https://github.com/hoodie) |[<img alt="huonw" src="https://avatars1.githubusercontent.com/u/1203825?v=4&s=117" width="117">](https://github.com/huonw) |[<img alt="GrappigPanda" src="https://avatars0.githubusercontent.com/u/2055372?v=4&s=117" width="117">](https://github.com/GrappigPanda) |[<img alt="shepmaster" src="https://avatars0.githubusercontent.com/u/174509?v=4&s=117" width="117">](https://github.com/shepmaster) |[<img alt="porglezomp" src="https://avatars1.githubusercontent.com/u/1690225?v=4&s=117" width="117">](https://github.com/porglezomp) |[<img alt="kieraneglin" src="https://avatars0.githubusercontent.com/u/569917?v=4&s=117" width="117">](https://github.com/kieraneglin) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[GrappigPanda](https://github.com/GrappigPanda) |[ignatenkobrain](https://github.com/ignatenkobrain) |[shepmaster](https://github.com/shepmaster) |[cstorey](https://github.com/cstorey) |[kieraneglin](https://github.com/kieraneglin) |[musoke](https://github.com/musoke) |
|
||||
[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[GrappigPanda](https://github.com/GrappigPanda) |[shepmaster](https://github.com/shepmaster) |[porglezomp](https://github.com/porglezomp) |[kieraneglin](https://github.com/kieraneglin) |
|
||||
|
||||
[<img alt="nelsonjchen" src="https://avatars1.githubusercontent.com/u/5363?v=4&s=117" width="117">](https://github.com/nelsonjchen) |[<img alt="pkgw" src="https://avatars0.githubusercontent.com/u/59598?v=4&s=117" width="117">](https://github.com/pkgw) |[<img alt="Deedasmi" src="https://avatars0.githubusercontent.com/u/5093293?v=4&s=117" width="117">](https://github.com/Deedasmi) |[<img alt="vmchale" src="https://avatars1.githubusercontent.com/u/13259982?v=4&s=117" width="117">](https://github.com/vmchale) |[<img alt="messense" src="https://avatars0.githubusercontent.com/u/1556054?v=4&s=117" width="117">](https://github.com/messense) |[<img alt="Keats" src="https://avatars2.githubusercontent.com/u/680355?v=4&s=117" width="117">](https://github.com/Keats) |
|
||||
[<img alt="musoke" src="https://avatars0.githubusercontent.com/u/16665084?v=4&s=117" width="117">](https://github.com/musoke) |[<img alt="nelsonjchen" src="https://avatars1.githubusercontent.com/u/5363?v=4&s=117" width="117">](https://github.com/nelsonjchen) |[<img alt="pkgw" src="https://avatars0.githubusercontent.com/u/59598?v=4&s=117" width="117">](https://github.com/pkgw) |[<img alt="Deedasmi" src="https://avatars0.githubusercontent.com/u/5093293?v=4&s=117" width="117">](https://github.com/Deedasmi) |[<img alt="vmchale" src="https://avatars1.githubusercontent.com/u/13259982?v=4&s=117" width="117">](https://github.com/vmchale) |[<img alt="messense" src="https://avatars0.githubusercontent.com/u/1556054?v=4&s=117" width="117">](https://github.com/messense) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[nelsonjchen](https://github.com/nelsonjchen) |[pkgw](https://github.com/pkgw) |[Deedasmi](https://github.com/Deedasmi) |[vmchale](https://github.com/vmchale) |[messense](https://github.com/messense) |[Keats](https://github.com/Keats) |
|
||||
[musoke](https://github.com/musoke) |[nelsonjchen](https://github.com/nelsonjchen) |[pkgw](https://github.com/pkgw) |[Deedasmi](https://github.com/Deedasmi) |[vmchale](https://github.com/vmchale) |[messense](https://github.com/messense) |
|
||||
|
||||
[<img alt="starkat99" src="https://avatars1.githubusercontent.com/u/8295111?v=4&s=117" width="117">](https://github.com/starkat99) |[<img alt="durka" src="https://avatars3.githubusercontent.com/u/47007?v=4&s=117" width="117">](https://github.com/durka) |[<img alt="alex-gulyas" src="https://avatars0.githubusercontent.com/u/8698329?v=4&s=117" width="117">](https://github.com/alex-gulyas) |[<img alt="cite-reader" src="https://avatars1.githubusercontent.com/u/4196987?v=4&s=117" width="117">](https://github.com/cite-reader) |[<img alt="alexbool" src="https://avatars3.githubusercontent.com/u/1283792?v=4&s=117" width="117">](https://github.com/alexbool) |[<img alt="AluisioASG" src="https://avatars2.githubusercontent.com/u/1904165?v=4&s=117" width="117">](https://github.com/AluisioASG) |
|
||||
[<img alt="Keats" src="https://avatars2.githubusercontent.com/u/680355?v=4&s=117" width="117">](https://github.com/Keats) |[<img alt="starkat99" src="https://avatars1.githubusercontent.com/u/8295111?v=4&s=117" width="117">](https://github.com/starkat99) |[<img alt="durka" src="https://avatars3.githubusercontent.com/u/47007?v=4&s=117" width="117">](https://github.com/durka) |[<img alt="alex-gulyas" src="https://avatars0.githubusercontent.com/u/8698329?v=4&s=117" width="117">](https://github.com/alex-gulyas) |[<img alt="cite-reader" src="https://avatars1.githubusercontent.com/u/4196987?v=4&s=117" width="117">](https://github.com/cite-reader) |[<img alt="alexbool" src="https://avatars3.githubusercontent.com/u/1283792?v=4&s=117" width="117">](https://github.com/alexbool) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[starkat99](https://github.com/starkat99) |[durka](https://github.com/durka) |[alex-gulyas](https://github.com/alex-gulyas) |[cite-reader](https://github.com/cite-reader) |[alexbool](https://github.com/alexbool) |[AluisioASG](https://github.com/AluisioASG) |
|
||||
[Keats](https://github.com/Keats) |[starkat99](https://github.com/starkat99) |[durka](https://github.com/durka) |[alex-gulyas](https://github.com/alex-gulyas) |[cite-reader](https://github.com/cite-reader) |[alexbool](https://github.com/alexbool) |
|
||||
|
||||
[<img alt="BurntSushi" src="https://avatars3.githubusercontent.com/u/456674?v=4&s=117" width="117">](https://github.com/BurntSushi) |[<img alt="nox" src="https://avatars0.githubusercontent.com/u/123095?v=4&s=117" width="117">](https://github.com/nox) |[<img alt="pixelistik" src="https://avatars1.githubusercontent.com/u/170929?v=4&s=117" width="117">](https://github.com/pixelistik) |[<img alt="brennie" src="https://avatars3.githubusercontent.com/u/156585?v=4&s=117" width="117">](https://github.com/brennie) |[<img alt="ogham" src="https://avatars3.githubusercontent.com/u/503760?v=4&s=117" width="117">](https://github.com/ogham) |[<img alt="Bilalh" src="https://avatars0.githubusercontent.com/u/171602?v=4&s=117" width="117">](https://github.com/Bilalh) |
|
||||
[<img alt="AluisioASG" src="https://avatars2.githubusercontent.com/u/1904165?v=4&s=117" width="117">](https://github.com/AluisioASG) |[<img alt="BurntSushi" src="https://avatars3.githubusercontent.com/u/456674?v=4&s=117" width="117">](https://github.com/BurntSushi) |[<img alt="nox" src="https://avatars0.githubusercontent.com/u/123095?v=4&s=117" width="117">](https://github.com/nox) |[<img alt="pixelistik" src="https://avatars1.githubusercontent.com/u/170929?v=4&s=117" width="117">](https://github.com/pixelistik) |[<img alt="brennie" src="https://avatars3.githubusercontent.com/u/156585?v=4&s=117" width="117">](https://github.com/brennie) |[<img alt="ogham" src="https://avatars3.githubusercontent.com/u/503760?v=4&s=117" width="117">](https://github.com/ogham) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[BurntSushi](https://github.com/BurntSushi) |[nox](https://github.com/nox) |[pixelistik](https://github.com/pixelistik) |[brennie](https://github.com/brennie) |[ogham](https://github.com/ogham) |[Bilalh](https://github.com/Bilalh) |
|
||||
[AluisioASG](https://github.com/AluisioASG) |[BurntSushi](https://github.com/BurntSushi) |[nox](https://github.com/nox) |[pixelistik](https://github.com/pixelistik) |[brennie](https://github.com/brennie) |[ogham](https://github.com/ogham) |
|
||||
|
||||
[<img alt="dotdash" src="https://avatars1.githubusercontent.com/u/230962?v=4&s=117" width="117">](https://github.com/dotdash) |[<img alt="bradurani" src="https://avatars0.githubusercontent.com/u/4195952?v=4&s=117" width="117">](https://github.com/bradurani) |[<img alt="Seeker14491" src="https://avatars2.githubusercontent.com/u/6490497?v=4&s=117" width="117">](https://github.com/Seeker14491) |[<img alt="brianp" src="https://avatars1.githubusercontent.com/u/179134?v=4&s=117" width="117">](https://github.com/brianp) |[<img alt="casey" src="https://avatars2.githubusercontent.com/u/1945?v=4&s=117" width="117">](https://github.com/casey) |[<img alt="volks73" src="https://avatars1.githubusercontent.com/u/1915469?v=4&s=117" width="117">](https://github.com/volks73) |
|
||||
[<img alt="Bilalh" src="https://avatars0.githubusercontent.com/u/171602?v=4&s=117" width="117">](https://github.com/Bilalh) |[<img alt="dotdash" src="https://avatars1.githubusercontent.com/u/230962?v=4&s=117" width="117">](https://github.com/dotdash) |[<img alt="bradurani" src="https://avatars0.githubusercontent.com/u/4195952?v=4&s=117" width="117">](https://github.com/bradurani) |[<img alt="Seeker14491" src="https://avatars2.githubusercontent.com/u/6490497?v=4&s=117" width="117">](https://github.com/Seeker14491) |[<img alt="brianp" src="https://avatars1.githubusercontent.com/u/179134?v=4&s=117" width="117">](https://github.com/brianp) |[<img alt="casey" src="https://avatars2.githubusercontent.com/u/1945?v=4&s=117" width="117">](https://github.com/casey) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[dotdash](https://github.com/dotdash) |[bradurani](https://github.com/bradurani) |[Seeker14491](https://github.com/Seeker14491) |[brianp](https://github.com/brianp) |[casey](https://github.com/casey) |[volks73](https://github.com/volks73) |
|
||||
[Bilalh](https://github.com/Bilalh) |[dotdash](https://github.com/dotdash) |[bradurani](https://github.com/bradurani) |[Seeker14491](https://github.com/Seeker14491) |[brianp](https://github.com/brianp) |[casey](https://github.com/casey) |
|
||||
|
||||
[<img alt="daboross" src="https://avatars1.githubusercontent.com/u/1152146?v=4&s=117" width="117">](https://github.com/daboross) |[<img alt="mernen" src="https://avatars0.githubusercontent.com/u/6412?v=4&s=117" width="117">](https://github.com/mernen) |[<img alt="dguo" src="https://avatars0.githubusercontent.com/u/2763135?v=4&s=117" width="117">](https://github.com/dguo) |[<img alt="davidszotten" src="https://avatars3.githubusercontent.com/u/412005?v=4&s=117" width="117">](https://github.com/davidszotten) |[<img alt="drusellers" src="https://avatars1.githubusercontent.com/u/63355?v=4&s=117" width="117">](https://github.com/drusellers) |[<img alt="eddyb" src="https://avatars2.githubusercontent.com/u/77424?v=4&s=117" width="117">](https://github.com/eddyb) |
|
||||
[<img alt="volks73" src="https://avatars1.githubusercontent.com/u/1915469?v=4&s=117" width="117">](https://github.com/volks73) |[<img alt="daboross" src="https://avatars1.githubusercontent.com/u/1152146?v=4&s=117" width="117">](https://github.com/daboross) |[<img alt="mernen" src="https://avatars0.githubusercontent.com/u/6412?v=4&s=117" width="117">](https://github.com/mernen) |[<img alt="dguo" src="https://avatars0.githubusercontent.com/u/2763135?v=4&s=117" width="117">](https://github.com/dguo) |[<img alt="davidszotten" src="https://avatars3.githubusercontent.com/u/412005?v=4&s=117" width="117">](https://github.com/davidszotten) |[<img alt="drusellers" src="https://avatars1.githubusercontent.com/u/63355?v=4&s=117" width="117">](https://github.com/drusellers) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[daboross](https://github.com/daboross) |[mernen](https://github.com/mernen) |[dguo](https://github.com/dguo) |[davidszotten](https://github.com/davidszotten) |[drusellers](https://github.com/drusellers) |[eddyb](https://github.com/eddyb) |
|
||||
[volks73](https://github.com/volks73) |[daboross](https://github.com/daboross) |[mernen](https://github.com/mernen) |[dguo](https://github.com/dguo) |[davidszotten](https://github.com/davidszotten) |[drusellers](https://github.com/drusellers) |
|
||||
|
||||
[<img alt="Fraser999" src="https://avatars3.githubusercontent.com/u/190532?v=4&s=117" width="117">](https://github.com/Fraser999) |[<img alt="birkenfeld" src="https://avatars0.githubusercontent.com/u/144359?v=4&s=117" width="117">](https://github.com/birkenfeld) |[<img alt="guanqun" src="https://avatars0.githubusercontent.com/u/53862?v=4&s=117" width="117">](https://github.com/guanqun) |[<img alt="tanakh" src="https://avatars2.githubusercontent.com/u/109069?v=4&s=117" width="117">](https://github.com/tanakh) |[<img alt="SirVer" src="https://avatars0.githubusercontent.com/u/140115?v=4&s=117" width="117">](https://github.com/SirVer) |[<img alt="idmit" src="https://avatars1.githubusercontent.com/u/2546728?v=4&s=117" width="117">](https://github.com/idmit) |
|
||||
[<img alt="eddyb" src="https://avatars2.githubusercontent.com/u/77424?v=4&s=117" width="117">](https://github.com/eddyb) |[<img alt="Fraser999" src="https://avatars3.githubusercontent.com/u/190532?v=4&s=117" width="117">](https://github.com/Fraser999) |[<img alt="birkenfeld" src="https://avatars0.githubusercontent.com/u/144359?v=4&s=117" width="117">](https://github.com/birkenfeld) |[<img alt="guanqun" src="https://avatars0.githubusercontent.com/u/53862?v=4&s=117" width="117">](https://github.com/guanqun) |[<img alt="tanakh" src="https://avatars2.githubusercontent.com/u/109069?v=4&s=117" width="117">](https://github.com/tanakh) |[<img alt="SirVer" src="https://avatars0.githubusercontent.com/u/140115?v=4&s=117" width="117">](https://github.com/SirVer) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[Fraser999](https://github.com/Fraser999) |[birkenfeld](https://github.com/birkenfeld) |[guanqun](https://github.com/guanqun) |[tanakh](https://github.com/tanakh) |[SirVer](https://github.com/SirVer) |[idmit](https://github.com/idmit) |
|
||||
[eddyb](https://github.com/eddyb) |[Fraser999](https://github.com/Fraser999) |[birkenfeld](https://github.com/birkenfeld) |[guanqun](https://github.com/guanqun) |[tanakh](https://github.com/tanakh) |[SirVer](https://github.com/SirVer) |
|
||||
|
||||
[<img alt="archer884" src="https://avatars1.githubusercontent.com/u/679494?v=4&s=117" width="117">](https://github.com/archer884) |[<img alt="jacobmischka" src="https://avatars1.githubusercontent.com/u/3939997?v=4&s=117" width="117">](https://github.com/jacobmischka) |[<img alt="jespino" src="https://avatars0.githubusercontent.com/u/290303?v=4&s=117" width="117">](https://github.com/jespino) |[<img alt="jtdowney" src="https://avatars1.githubusercontent.com/u/44654?v=4&s=117" width="117">](https://github.com/jtdowney) |[<img alt="andete" src="https://avatars2.githubusercontent.com/u/689017?v=4&s=117" width="117">](https://github.com/andete) |[<img alt="joshtriplett" src="https://avatars2.githubusercontent.com/u/162737?v=4&s=117" width="117">](https://github.com/joshtriplett) |
|
||||
[<img alt="idmit" src="https://avatars1.githubusercontent.com/u/2546728?v=4&s=117" width="117">](https://github.com/idmit) |[<img alt="archer884" src="https://avatars1.githubusercontent.com/u/679494?v=4&s=117" width="117">](https://github.com/archer884) |[<img alt="jacobmischka" src="https://avatars1.githubusercontent.com/u/3939997?v=4&s=117" width="117">](https://github.com/jacobmischka) |[<img alt="jespino" src="https://avatars0.githubusercontent.com/u/290303?v=4&s=117" width="117">](https://github.com/jespino) |[<img alt="jfrankenau" src="https://avatars3.githubusercontent.com/u/2736480?v=4&s=117" width="117">](https://github.com/jfrankenau) |[<img alt="jtdowney" src="https://avatars1.githubusercontent.com/u/44654?v=4&s=117" width="117">](https://github.com/jtdowney) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[archer884](https://github.com/archer884) |[jacobmischka](https://github.com/jacobmischka) |[jespino](https://github.com/jespino) |[jtdowney](https://github.com/jtdowney) |[andete](https://github.com/andete) |[joshtriplett](https://github.com/joshtriplett) |
|
||||
[idmit](https://github.com/idmit) |[archer884](https://github.com/archer884) |[jacobmischka](https://github.com/jacobmischka) |[jespino](https://github.com/jespino) |[jfrankenau](https://github.com/jfrankenau) |[jtdowney](https://github.com/jtdowney) |
|
||||
|
||||
[<img alt="Kalwyn" src="https://avatars3.githubusercontent.com/u/22778640?v=4&s=117" width="117">](https://github.com/Kalwyn) |[<img alt="manuel-rhdt" src="https://avatars1.githubusercontent.com/u/3199013?v=4&s=117" width="117">](https://github.com/manuel-rhdt) |[<img alt="Marwes" src="https://avatars3.githubusercontent.com/u/957312?v=4&s=117" width="117">](https://github.com/Marwes) |[<img alt="mdaffin" src="https://avatars1.githubusercontent.com/u/171232?v=4&s=117" width="117">](https://github.com/mdaffin) |[<img alt="iliekturtles" src="https://avatars3.githubusercontent.com/u/5081378?v=4&s=117" width="117">](https://github.com/iliekturtles) |[<img alt="nicompte" src="https://avatars2.githubusercontent.com/u/439369?v=4&s=117" width="117">](https://github.com/nicompte) |
|
||||
[<img alt="andete" src="https://avatars2.githubusercontent.com/u/689017?v=4&s=117" width="117">](https://github.com/andete) |[<img alt="joshtriplett" src="https://avatars2.githubusercontent.com/u/162737?v=4&s=117" width="117">](https://github.com/joshtriplett) |[<img alt="Kalwyn" src="https://avatars3.githubusercontent.com/u/22778640?v=4&s=117" width="117">](https://github.com/Kalwyn) |[<img alt="manuel-rhdt" src="https://avatars1.githubusercontent.com/u/3199013?v=4&s=117" width="117">](https://github.com/manuel-rhdt) |[<img alt="Marwes" src="https://avatars3.githubusercontent.com/u/957312?v=4&s=117" width="117">](https://github.com/Marwes) |[<img alt="mdaffin" src="https://avatars1.githubusercontent.com/u/171232?v=4&s=117" width="117">](https://github.com/mdaffin) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[Kalwyn](https://github.com/Kalwyn) |[manuel-rhdt](https://github.com/manuel-rhdt) |[Marwes](https://github.com/Marwes) |[mdaffin](https://github.com/mdaffin) |[iliekturtles](https://github.com/iliekturtles) |[nicompte](https://github.com/nicompte) |
|
||||
[andete](https://github.com/andete) |[joshtriplett](https://github.com/joshtriplett) |[Kalwyn](https://github.com/Kalwyn) |[manuel-rhdt](https://github.com/manuel-rhdt) |[Marwes](https://github.com/Marwes) |[mdaffin](https://github.com/mdaffin) |
|
||||
|
||||
[<img alt="NickeZ" src="https://avatars2.githubusercontent.com/u/492753?v=4&s=117" width="117">](https://github.com/NickeZ) |[<img alt="nvzqz" src="https://avatars0.githubusercontent.com/u/10367662?v=4&s=117" width="117">](https://github.com/nvzqz) |[<img alt="nuew" src="https://avatars2.githubusercontent.com/u/26099511?v=4&s=117" width="117">](https://github.com/nuew) |[<img alt="Geogi" src="https://avatars1.githubusercontent.com/u/1818316?v=4&s=117" width="117">](https://github.com/Geogi) |[<img alt="flying-sheep" src="https://avatars0.githubusercontent.com/u/291575?v=4&s=117" width="117">](https://github.com/flying-sheep) |[<img alt="Phlosioneer" src="https://avatars2.githubusercontent.com/u/4657718?v=4&s=117" width="117">](https://github.com/Phlosioneer) |
|
||||
[<img alt="iliekturtles" src="https://avatars3.githubusercontent.com/u/5081378?v=4&s=117" width="117">](https://github.com/iliekturtles) |[<img alt="nicompte" src="https://avatars2.githubusercontent.com/u/439369?v=4&s=117" width="117">](https://github.com/nicompte) |[<img alt="NickeZ" src="https://avatars2.githubusercontent.com/u/492753?v=4&s=117" width="117">](https://github.com/NickeZ) |[<img alt="nvzqz" src="https://avatars0.githubusercontent.com/u/10367662?v=4&s=117" width="117">](https://github.com/nvzqz) |[<img alt="nuew" src="https://avatars2.githubusercontent.com/u/26099511?v=4&s=117" width="117">](https://github.com/nuew) |[<img alt="Geogi" src="https://avatars1.githubusercontent.com/u/1818316?v=4&s=117" width="117">](https://github.com/Geogi) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[NickeZ](https://github.com/NickeZ) |[nvzqz](https://github.com/nvzqz) |[nuew](https://github.com/nuew) |[Geogi](https://github.com/Geogi) |[flying-sheep](https://github.com/flying-sheep) |[Phlosioneer](https://github.com/Phlosioneer) |
|
||||
[iliekturtles](https://github.com/iliekturtles) |[nicompte](https://github.com/nicompte) |[NickeZ](https://github.com/NickeZ) |[nvzqz](https://github.com/nvzqz) |[nuew](https://github.com/nuew) |[Geogi](https://github.com/Geogi) |
|
||||
|
||||
[<img alt="peppsac" src="https://avatars3.githubusercontent.com/u/2198295?v=4&s=117" width="117">](https://github.com/peppsac) |[<img alt="golddranks" src="https://avatars1.githubusercontent.com/u/2675542?v=4&s=117" width="117">](https://github.com/golddranks) |[<img alt="hexjelly" src="https://avatars0.githubusercontent.com/u/435283?v=4&s=117" width="117">](https://github.com/hexjelly) |[<img alt="rnelson" src="https://avatars3.githubusercontent.com/u/118361?v=4&s=117" width="117">](https://github.com/rnelson) |[<img alt="swatteau" src="https://avatars3.githubusercontent.com/u/5521255?v=4&s=117" width="117">](https://github.com/swatteau) |[<img alt="tspiteri" src="https://avatars0.githubusercontent.com/u/18604588?v=4&s=117" width="117">](https://github.com/tspiteri) |
|
||||
[<img alt="focusaurus" src="https://avatars1.githubusercontent.com/u/482377?v=4&s=117" width="117">](https://github.com/focusaurus) |[<img alt="flying-sheep" src="https://avatars0.githubusercontent.com/u/291575?v=4&s=117" width="117">](https://github.com/flying-sheep) |[<img alt="Phlosioneer" src="https://avatars2.githubusercontent.com/u/4657718?v=4&s=117" width="117">](https://github.com/Phlosioneer) |[<img alt="peppsac" src="https://avatars3.githubusercontent.com/u/2198295?v=4&s=117" width="117">](https://github.com/peppsac) |[<img alt="golddranks" src="https://avatars1.githubusercontent.com/u/2675542?v=4&s=117" width="117">](https://github.com/golddranks) |[<img alt="hexjelly" src="https://avatars0.githubusercontent.com/u/435283?v=4&s=117" width="117">](https://github.com/hexjelly) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[peppsac](https://github.com/peppsac) |[golddranks](https://github.com/golddranks) |[hexjelly](https://github.com/hexjelly) |[rnelson](https://github.com/rnelson) |[swatteau](https://github.com/swatteau) |[tspiteri](https://github.com/tspiteri) |
|
||||
[focusaurus](https://github.com/focusaurus) |[flying-sheep](https://github.com/flying-sheep) |[Phlosioneer](https://github.com/Phlosioneer) |[peppsac](https://github.com/peppsac) |[golddranks](https://github.com/golddranks) |[hexjelly](https://github.com/hexjelly) |
|
||||
|
||||
[<img alt="siiptuo" src="https://avatars0.githubusercontent.com/u/10729330?v=4&s=117" width="117">](https://github.com/siiptuo) |[<img alt="vks" src="https://avatars2.githubusercontent.com/u/33460?v=4&s=117" width="117">](https://github.com/vks) |[<img alt="vsupalov" src="https://avatars2.githubusercontent.com/u/2801030?v=4&s=117" width="117">](https://github.com/vsupalov) |[<img alt="mineo" src="https://avatars1.githubusercontent.com/u/78236?v=4&s=117" width="117">](https://github.com/mineo) |[<img alt="wabain" src="https://avatars3.githubusercontent.com/u/7651435?v=4&s=117" width="117">](https://github.com/wabain) |[<img alt="grossws" src="https://avatars2.githubusercontent.com/u/171284?v=4&s=117" width="117">](https://github.com/grossws) |
|
||||
[<img alt="rnelson" src="https://avatars3.githubusercontent.com/u/118361?v=4&s=117" width="117">](https://github.com/rnelson) |[<img alt="swatteau" src="https://avatars3.githubusercontent.com/u/5521255?v=4&s=117" width="117">](https://github.com/swatteau) |[<img alt="tspiteri" src="https://avatars0.githubusercontent.com/u/18604588?v=4&s=117" width="117">](https://github.com/tspiteri) |[<img alt="siiptuo" src="https://avatars0.githubusercontent.com/u/10729330?v=4&s=117" width="117">](https://github.com/siiptuo) |[<img alt="vks" src="https://avatars2.githubusercontent.com/u/33460?v=4&s=117" width="117">](https://github.com/vks) |[<img alt="vsupalov" src="https://avatars2.githubusercontent.com/u/2801030?v=4&s=117" width="117">](https://github.com/vsupalov) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[siiptuo](https://github.com/siiptuo) |[vks](https://github.com/vks) |[vsupalov](https://github.com/vsupalov) |[mineo](https://github.com/mineo) |[wabain](https://github.com/wabain) |[grossws](https://github.com/grossws) |
|
||||
[rnelson](https://github.com/rnelson) |[swatteau](https://github.com/swatteau) |[tspiteri](https://github.com/tspiteri) |[siiptuo](https://github.com/siiptuo) |[vks](https://github.com/vks) |[vsupalov](https://github.com/vsupalov) |
|
||||
|
||||
[<img alt="kennytm" src="https://avatars1.githubusercontent.com/u/103023?v=4&s=117" width="117">](https://github.com/kennytm) |[<img alt="mvaude" src="https://avatars1.githubusercontent.com/u/9532611?v=4&s=117" width="117">](https://github.com/mvaude) |[<img alt="panicbit" src="https://avatars2.githubusercontent.com/u/628445?v=4&s=117" width="117">](https://github.com/panicbit) |[<img alt="mitsuhiko" src="https://avatars1.githubusercontent.com/u/7396?v=4&s=117" width="117">](https://github.com/mitsuhiko) |
|
||||
:---: |:---: |:---: |:---: |
|
||||
[kennytm](https://github.com/kennytm) |[mvaude](https://github.com/mvaude) |[panicbit](https://github.com/panicbit) |[mitsuhiko](https://github.com/mitsuhiko) |
|
||||
[<img alt="mineo" src="https://avatars1.githubusercontent.com/u/78236?v=4&s=117" width="117">](https://github.com/mineo) |[<img alt="wabain" src="https://avatars3.githubusercontent.com/u/7651435?v=4&s=117" width="117">](https://github.com/wabain) |[<img alt="grossws" src="https://avatars2.githubusercontent.com/u/171284?v=4&s=117" width="117">](https://github.com/grossws) |[<img alt="kennytm" src="https://avatars1.githubusercontent.com/u/103023?v=4&s=117" width="117">](https://github.com/kennytm) |[<img alt="mvaude" src="https://avatars1.githubusercontent.com/u/9532611?v=4&s=117" width="117">](https://github.com/mvaude) |[<img alt="panicbit" src="https://avatars2.githubusercontent.com/u/628445?v=4&s=117" width="117">](https://github.com/panicbit) |
|
||||
:---: |:---: |:---: |:---: |:---: |:---: |
|
||||
[mineo](https://github.com/mineo) |[wabain](https://github.com/wabain) |[grossws](https://github.com/grossws) |[kennytm](https://github.com/kennytm) |[mvaude](https://github.com/mvaude) |[panicbit](https://github.com/panicbit) |
|
||||
|
||||
[<img alt="mitsuhiko" src="https://avatars1.githubusercontent.com/u/7396?v=4&s=117" width="117">](https://github.com/mitsuhiko) |
|
||||
:---: |
|
||||
[mitsuhiko](https://github.com/mitsuhiko) |
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ The minimum required Rust is now 1.20. This was done to start using bitflags 1.0
|
|||
|
||||
* Updates `bitflags` to 1.0
|
||||
* Adds the traits to be used with the `clap-derive` crate to be able to use Custom Derive (for now must be accessed with `unstable` feature flag)
|
||||
* Adds Arg::case_insensitive(bool) which allows matching Arg::possible_values without worrying about ASCII case
|
||||
* Fixes a regression where --help couldn't be overridden
|
||||
* adds '[SUBCOMMAND]' to usage strings with only AppSettings::AllowExternalSubcommands is used with no other subcommands
|
||||
* uses `.bash` for Bash completion scripts now instead of `.bash-completion` due to convention and `.bash-completion` not being supported by completion projects
|
||||
|
|
|
@ -85,7 +85,7 @@ macro_rules! arg_post_processing {
|
|||
.filter(|&&(val, _)| val.is_none())
|
||||
.filter(|&&(_, req)| !$matcher.contains(&req))
|
||||
.map(|&(_, name)| name) {
|
||||
|
||||
|
||||
$me.required.push(n);
|
||||
}
|
||||
} else { sdebugln!("No"); }
|
||||
|
|
|
@ -23,5 +23,11 @@ pub struct AppMeta<'b> {
|
|||
|
||||
impl<'b> AppMeta<'b> {
|
||||
pub fn new() -> Self { Default::default() }
|
||||
pub fn with_name(s: String) -> Self { AppMeta { name: s, disp_ord: 999, ..Default::default() } }
|
||||
}
|
||||
pub fn with_name(s: String) -> Self {
|
||||
AppMeta {
|
||||
name: s,
|
||||
disp_ord: 999,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,10 +60,10 @@ use map::{self, VecMap};
|
|||
/// [`App::get_matches`]: ./struct.App.html#method.get_matches
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct App<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
#[doc(hidden)]
|
||||
pub p: Parser<'a, 'b>,
|
||||
#[doc(hidden)] pub p: Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,7 +79,11 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// let prog = App::new("My Program")
|
||||
/// # ;
|
||||
/// ```
|
||||
pub fn new<S: Into<String>>(n: S) -> Self { App { p: Parser::with_name(n.into()) } }
|
||||
pub fn new<S: Into<String>>(n: S) -> Self {
|
||||
App {
|
||||
p: Parser::with_name(n.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the name of the app
|
||||
pub fn get_name(&self) -> &str { &self.p.meta.name }
|
||||
|
@ -103,7 +107,9 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`App::version`]: ./struct.App.html#method.author
|
||||
#[deprecated(since="2.14.1", note="Can never work; use explicit App::author() and App::version() calls instead")]
|
||||
pub fn with_defaults<S: Into<String>>(n: S) -> Self {
|
||||
let mut a = App { p: Parser::with_name(n.into()) };
|
||||
let mut a = App {
|
||||
p: Parser::with_name(n.into()),
|
||||
};
|
||||
a.p.meta.author = Some("Kevin K. <kbknapp@gmail.com>");
|
||||
a.p.meta.version = Some("2.19.2");
|
||||
a
|
||||
|
@ -1073,7 +1079,8 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
/// [`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html
|
||||
pub fn subcommands<I>(mut self, subcmds: I) -> Self
|
||||
where I: IntoIterator<Item = App<'a, 'b>>
|
||||
where
|
||||
I: IntoIterator<Item = App<'a, 'b>>,
|
||||
{
|
||||
for subcmd in subcmds {
|
||||
self.p.add_subcommand(subcmd);
|
||||
|
@ -1380,10 +1387,12 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// `<project>/target/debug/build/myapp-<hash>/out/myapp.bash`.
|
||||
///
|
||||
/// Fish shell completions will use the file format `{bin_name}.fish`
|
||||
pub fn gen_completions<T: Into<OsString>, S: Into<String>>(&mut self,
|
||||
bin_name: S,
|
||||
for_shell: Shell,
|
||||
out_dir: T) {
|
||||
pub fn gen_completions<T: Into<OsString>, S: Into<String>>(
|
||||
&mut self,
|
||||
bin_name: S,
|
||||
for_shell: Shell,
|
||||
out_dir: T,
|
||||
) {
|
||||
self.p.meta.bin_name = Some(bin_name.into());
|
||||
self.p.gen_completions(for_shell, out_dir.into());
|
||||
}
|
||||
|
@ -1421,10 +1430,12 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// ```shell
|
||||
/// $ myapp generate-bash-completions > /usr/share/bash-completion/completions/myapp.bash
|
||||
/// ```
|
||||
pub fn gen_completions_to<W: Write, S: Into<String>>(&mut self,
|
||||
bin_name: S,
|
||||
for_shell: Shell,
|
||||
buf: &mut W) {
|
||||
pub fn gen_completions_to<W: Write, S: Into<String>>(
|
||||
&mut self,
|
||||
bin_name: S,
|
||||
for_shell: Shell,
|
||||
buf: &mut W,
|
||||
) {
|
||||
self.p.meta.bin_name = Some(bin_name.into());
|
||||
self.p.gen_completions_to(for_shell, buf);
|
||||
}
|
||||
|
@ -1497,8 +1508,9 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
|
||||
/// [`AppSettings::NoBinaryName`]: ./enum.AppSettings.html#variant.NoBinaryName
|
||||
pub fn get_matches_from<I, T>(mut self, itr: I) -> ArgMatches<'a>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
self.get_matches_from_safe_borrow(itr).unwrap_or_else(|e| {
|
||||
// Otherwise, write to stderr and exit
|
||||
|
@ -1553,8 +1565,9 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`kind`]: ./struct.Error.html
|
||||
/// [`AppSettings::NoBinaryName`]: ./enum.AppSettings.html#variant.NoBinaryName
|
||||
pub fn get_matches_from_safe<I, T>(mut self, itr: I) -> ClapResult<ArgMatches<'a>>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
self.get_matches_from_safe_borrow(itr)
|
||||
}
|
||||
|
@ -1581,8 +1594,9 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`App::get_matches_from_safe`]: ./struct.App.html#method.get_matches_from_safe
|
||||
/// [`AppSettings::NoBinaryName`]: ./enum.AppSettings.html#variant.NoBinaryName
|
||||
pub fn get_matches_from_safe_borrow<I, T>(&mut self, itr: I) -> ClapResult<ArgMatches<'a>>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
// If there are global arguments, or settings we need to propgate them down to subcommands
|
||||
// before parsing incase we run into a subcommand
|
||||
|
@ -1622,7 +1636,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
return Err(e);
|
||||
}
|
||||
|
||||
let global_arg_vec : Vec<&str> = (&self).p.global_args.iter().map(|ga| ga.b.name).collect();
|
||||
let global_arg_vec: Vec<&str> = (&self).p.global_args.iter().map(|ga| ga.b.name).collect();
|
||||
matcher.propagate_globals(&global_arg_vec);
|
||||
|
||||
Ok(matcher.into())
|
||||
|
@ -1674,14 +1688,18 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> {
|
|||
if let Some(v) = yaml["display_order"].as_i64() {
|
||||
a = a.display_order(v as usize);
|
||||
} else if yaml["display_order"] != Yaml::BadValue {
|
||||
panic!("Failed to convert YAML value {:?} to a u64",
|
||||
yaml["display_order"]);
|
||||
panic!(
|
||||
"Failed to convert YAML value {:?} to a u64",
|
||||
yaml["display_order"]
|
||||
);
|
||||
}
|
||||
if let Some(v) = yaml["setting"].as_str() {
|
||||
a = a.setting(v.parse().expect("unknown AppSetting found in YAML file"));
|
||||
} else if yaml["setting"] != Yaml::BadValue {
|
||||
panic!("Failed to convert YAML value {:?} to an AppSetting",
|
||||
yaml["setting"]);
|
||||
panic!(
|
||||
"Failed to convert YAML value {:?} to an AppSetting",
|
||||
yaml["setting"]
|
||||
);
|
||||
}
|
||||
if let Some(v) = yaml["settings"].as_vec() {
|
||||
for ys in v {
|
||||
|
@ -1692,27 +1710,32 @@ impl<'a> From<&'a Yaml> for App<'a, 'a> {
|
|||
} else if let Some(v) = yaml["settings"].as_str() {
|
||||
a = a.setting(v.parse().expect("unknown AppSetting found in YAML file"));
|
||||
} else if yaml["settings"] != Yaml::BadValue {
|
||||
panic!("Failed to convert YAML value {:?} to a string",
|
||||
yaml["settings"]);
|
||||
panic!(
|
||||
"Failed to convert YAML value {:?} to a string",
|
||||
yaml["settings"]
|
||||
);
|
||||
}
|
||||
if let Some(v) = yaml["global_setting"].as_str() {
|
||||
a = a.setting(v.parse().expect("unknown AppSetting found in YAML file"));
|
||||
} else if yaml["global_setting"] != Yaml::BadValue {
|
||||
panic!("Failed to convert YAML value {:?} to an AppSetting",
|
||||
yaml["setting"]);
|
||||
panic!(
|
||||
"Failed to convert YAML value {:?} to an AppSetting",
|
||||
yaml["setting"]
|
||||
);
|
||||
}
|
||||
if let Some(v) = yaml["global_settings"].as_vec() {
|
||||
for ys in v {
|
||||
if let Some(s) = ys.as_str() {
|
||||
a = a.global_setting(s.parse()
|
||||
.expect("unknown AppSetting found in YAML file"));
|
||||
a = a.global_setting(s.parse().expect("unknown AppSetting found in YAML file"));
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = yaml["global_settings"].as_str() {
|
||||
a = a.global_setting(v.parse().expect("unknown AppSetting found in YAML file"));
|
||||
} else if yaml["global_settings"] != Yaml::BadValue {
|
||||
panic!("Failed to convert YAML value {:?} to a string",
|
||||
yaml["global_settings"]);
|
||||
panic!(
|
||||
"Failed to convert YAML value {:?} to a string",
|
||||
yaml["global_settings"]
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! vec_or_str {
|
||||
|
@ -1800,8 +1823,10 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> {
|
|||
fn longest_filter(&self) -> bool { true }
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
if let Some(ref aliases) = self.p.meta.aliases {
|
||||
let vis_aliases: Vec<_> =
|
||||
aliases.iter().filter_map(|&(n, v)| if v { Some(n) } else { None }).collect();
|
||||
let vis_aliases: Vec<_> = aliases
|
||||
.iter()
|
||||
.filter_map(|&(n, v)| if v { Some(n) } else { None })
|
||||
.collect();
|
||||
if vis_aliases.is_empty() {
|
||||
None
|
||||
} else {
|
||||
|
|
1014
src/app/parser.rs
1014
src/app/parser.rs
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
// Std
|
||||
#[allow(unused_imports)]
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::str::FromStr;
|
||||
use std::ops::BitOr;
|
||||
|
@ -60,7 +60,10 @@ impl BitOr for AppFlags {
|
|||
|
||||
impl Default for AppFlags {
|
||||
fn default() -> Self {
|
||||
AppFlags(Flags::NEEDS_LONG_VERSION | Flags::NEEDS_LONG_HELP | Flags::NEEDS_SC_HELP | Flags::UTF8_NONE | Flags::COLOR_AUTO)
|
||||
AppFlags(
|
||||
Flags::NEEDS_LONG_VERSION | Flags::NEEDS_LONG_HELP | Flags::NEEDS_SC_HELP
|
||||
| Flags::UTF8_NONE | Flags::COLOR_AUTO,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,8 +141,8 @@ pub enum AppSettings {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, AppSettings};
|
||||
/// use std::ffi::OsString;
|
||||
/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
|
||||
|
@ -592,9 +595,9 @@ pub enum AppSettings {
|
|||
NextLineHelp,
|
||||
|
||||
/// **DEPRECATED**: This setting is no longer required in order to propagate values up or down
|
||||
///
|
||||
///
|
||||
/// Specifies that the parser should propagate global arg's values down or up through any *used*
|
||||
/// child subcommands. Meaning, if a subcommand wasn't used, the values won't be propagated to
|
||||
/// child subcommands. Meaning, if a subcommand wasn't used, the values won't be propagated to
|
||||
/// said subcommand.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -710,8 +713,8 @@ pub enum AppSettings {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, AppSettings, ErrorKind};
|
||||
/// use std::ffi::OsString;
|
||||
/// use std::os::unix::ffi::OsStringExt;
|
||||
|
@ -839,32 +842,23 @@ pub enum AppSettings {
|
|||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
WaitOnError,
|
||||
|
||||
#[doc(hidden)]
|
||||
NeedsLongVersion,
|
||||
#[doc(hidden)] NeedsLongVersion,
|
||||
|
||||
#[doc(hidden)]
|
||||
NeedsLongHelp,
|
||||
#[doc(hidden)] NeedsLongHelp,
|
||||
|
||||
#[doc(hidden)]
|
||||
NeedsSubcommandHelp,
|
||||
#[doc(hidden)] NeedsSubcommandHelp,
|
||||
|
||||
#[doc(hidden)]
|
||||
LowIndexMultiplePositional,
|
||||
#[doc(hidden)] LowIndexMultiplePositional,
|
||||
|
||||
#[doc(hidden)]
|
||||
TrailingValues,
|
||||
#[doc(hidden)] TrailingValues,
|
||||
|
||||
#[doc(hidden)]
|
||||
ValidNegNumFound,
|
||||
#[doc(hidden)] ValidNegNumFound,
|
||||
|
||||
#[doc(hidden)]
|
||||
Propagated,
|
||||
#[doc(hidden)] Propagated,
|
||||
|
||||
#[doc(hidden)]
|
||||
ValidArgFound,
|
||||
#[doc(hidden)] ValidArgFound,
|
||||
|
||||
#[doc(hidden)]
|
||||
ContainsLast,
|
||||
#[doc(hidden)] ContainsLast,
|
||||
}
|
||||
|
||||
impl FromStr for AppSettings {
|
||||
|
@ -916,74 +910,142 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn app_settings_fromstr() {
|
||||
assert_eq!("argsnegatesubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ArgsNegateSubcommands);
|
||||
assert_eq!("argrequiredelsehelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ArgRequiredElseHelp);
|
||||
assert_eq!("allowexternalsubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowExternalSubcommands);
|
||||
assert_eq!("allowinvalidutf8".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowInvalidUtf8);
|
||||
assert_eq!("allowleadinghyphen".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowLeadingHyphen);
|
||||
assert_eq!("allownegativenumbers".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowNegativeNumbers);
|
||||
assert_eq!("coloredhelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColoredHelp);
|
||||
assert_eq!("colorauto".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColorAuto);
|
||||
assert_eq!("coloralways".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColorAlways);
|
||||
assert_eq!("colornever".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColorNever);
|
||||
assert_eq!("disablehelpsubcommand".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DisableHelpSubcommand);
|
||||
assert_eq!("disableversion".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DisableVersion);
|
||||
assert_eq!("dontcollapseargsinusage".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DontCollapseArgsInUsage);
|
||||
assert_eq!("dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DontDelimitTrailingValues);
|
||||
assert_eq!("derivedisplayorder".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DeriveDisplayOrder);
|
||||
assert_eq!("globalversion".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::GlobalVersion);
|
||||
assert_eq!("hidden".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::Hidden);
|
||||
assert_eq!("hidepossiblevaluesinhelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::HidePossibleValuesInHelp);
|
||||
assert_eq!("lowindexmultiplePositional".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::LowIndexMultiplePositional);
|
||||
assert_eq!("nobinaryname".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::NoBinaryName);
|
||||
assert_eq!("nextlinehelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::NextLineHelp);
|
||||
assert_eq!("subcommandsnegatereqs".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::SubcommandsNegateReqs);
|
||||
assert_eq!("subcommandrequired".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::SubcommandRequired);
|
||||
assert_eq!("subcommandrequiredelsehelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::SubcommandRequiredElseHelp);
|
||||
assert_eq!("strictutf8".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::StrictUtf8);
|
||||
assert_eq!("trailingvararg".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::TrailingVarArg);
|
||||
assert_eq!("unifiedhelpmessage".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::UnifiedHelpMessage);
|
||||
assert_eq!("versionlesssubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::VersionlessSubcommands);
|
||||
assert_eq!("waitonerror".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::WaitOnError);
|
||||
assert_eq!("validnegnumfound".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ValidNegNumFound);
|
||||
assert_eq!("validargfound".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ValidArgFound);
|
||||
assert_eq!("propagated".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::Propagated);
|
||||
assert_eq!("trailingvalues".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::TrailingValues);
|
||||
assert_eq!("infersubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::InferSubcommands);
|
||||
assert_eq!(
|
||||
"argsnegatesubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ArgsNegateSubcommands
|
||||
);
|
||||
assert_eq!(
|
||||
"argrequiredelsehelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ArgRequiredElseHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"allowexternalsubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowExternalSubcommands
|
||||
);
|
||||
assert_eq!(
|
||||
"allowinvalidutf8".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowInvalidUtf8
|
||||
);
|
||||
assert_eq!(
|
||||
"allowleadinghyphen".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowLeadingHyphen
|
||||
);
|
||||
assert_eq!(
|
||||
"allownegativenumbers".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::AllowNegativeNumbers
|
||||
);
|
||||
assert_eq!(
|
||||
"coloredhelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColoredHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"colorauto".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColorAuto
|
||||
);
|
||||
assert_eq!(
|
||||
"coloralways".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColorAlways
|
||||
);
|
||||
assert_eq!(
|
||||
"colornever".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ColorNever
|
||||
);
|
||||
assert_eq!(
|
||||
"disablehelpsubcommand".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DisableHelpSubcommand
|
||||
);
|
||||
assert_eq!(
|
||||
"disableversion".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DisableVersion
|
||||
);
|
||||
assert_eq!(
|
||||
"dontcollapseargsinusage".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DontCollapseArgsInUsage
|
||||
);
|
||||
assert_eq!(
|
||||
"dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DontDelimitTrailingValues
|
||||
);
|
||||
assert_eq!(
|
||||
"derivedisplayorder".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::DeriveDisplayOrder
|
||||
);
|
||||
assert_eq!(
|
||||
"globalversion".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::GlobalVersion
|
||||
);
|
||||
assert_eq!(
|
||||
"hidden".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::Hidden
|
||||
);
|
||||
assert_eq!(
|
||||
"hidepossiblevaluesinhelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::HidePossibleValuesInHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"lowindexmultiplePositional".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::LowIndexMultiplePositional
|
||||
);
|
||||
assert_eq!(
|
||||
"nobinaryname".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::NoBinaryName
|
||||
);
|
||||
assert_eq!(
|
||||
"nextlinehelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::NextLineHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"subcommandsnegatereqs".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::SubcommandsNegateReqs
|
||||
);
|
||||
assert_eq!(
|
||||
"subcommandrequired".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::SubcommandRequired
|
||||
);
|
||||
assert_eq!(
|
||||
"subcommandrequiredelsehelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::SubcommandRequiredElseHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"strictutf8".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::StrictUtf8
|
||||
);
|
||||
assert_eq!(
|
||||
"trailingvararg".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::TrailingVarArg
|
||||
);
|
||||
assert_eq!(
|
||||
"unifiedhelpmessage".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::UnifiedHelpMessage
|
||||
);
|
||||
assert_eq!(
|
||||
"versionlesssubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::VersionlessSubcommands
|
||||
);
|
||||
assert_eq!(
|
||||
"waitonerror".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::WaitOnError
|
||||
);
|
||||
assert_eq!(
|
||||
"validnegnumfound".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ValidNegNumFound
|
||||
);
|
||||
assert_eq!(
|
||||
"validargfound".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::ValidArgFound
|
||||
);
|
||||
assert_eq!(
|
||||
"propagated".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::Propagated
|
||||
);
|
||||
assert_eq!(
|
||||
"trailingvalues".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::TrailingValues
|
||||
);
|
||||
assert_eq!(
|
||||
"infersubcommands".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::InferSubcommands
|
||||
);
|
||||
assert!("hahahaha".parse::<AppSettings>().is_err());
|
||||
}
|
||||
}
|
||||
|
|
260
src/app/usage.rs
260
src/app/usage.rs
|
@ -19,11 +19,13 @@ pub fn create_usage_with_title(p: &Parser, used: &[&str]) -> String {
|
|||
}
|
||||
|
||||
// Creates a usage string to be used in error message (i.e. one with currently used args)
|
||||
pub fn create_error_usage<'a, 'b>(p: &Parser<'a, 'b>,
|
||||
matcher: &'b ArgMatcher<'a>,
|
||||
extra: Option<&str>)
|
||||
-> String {
|
||||
let mut args: Vec<_> = matcher.arg_names()
|
||||
pub fn create_error_usage<'a, 'b>(
|
||||
p: &Parser<'a, 'b>,
|
||||
matcher: &'b ArgMatcher<'a>,
|
||||
extra: Option<&str>,
|
||||
) -> String {
|
||||
let mut args: Vec<_> = matcher
|
||||
.arg_names()
|
||||
.iter()
|
||||
.filter(|n| {
|
||||
if let Some(o) = find_by_name!(p, **n, opts, iter) {
|
||||
|
@ -60,20 +62,15 @@ pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
|
|||
let name = p.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
p.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&p.meta.name)
|
||||
});
|
||||
.unwrap_or_else(|| p.meta.bin_name.as_ref().unwrap_or(&p.meta.name));
|
||||
usage.push_str(&*name);
|
||||
let req_string = if incl_reqs {
|
||||
let mut reqs: Vec<&str> = p.required().map(|r| &**r).collect();
|
||||
reqs.sort();
|
||||
reqs.dedup();
|
||||
get_required_usage_from(p, &reqs, None, None, false).iter().fold(String::new(), |a, s| {
|
||||
a + &format!(" {}", s)[..]
|
||||
})
|
||||
get_required_usage_from(p, &reqs, None, None, false)
|
||||
.iter()
|
||||
.fold(String::new(), |a, s| a + &format!(" {}", s)[..])
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
@ -84,8 +81,9 @@ pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
|
|||
} else if flags {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
if !p.is_set(AS::UnifiedHelpMessage) &&
|
||||
p.opts.iter().any(|o| !o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden)) {
|
||||
if !p.is_set(AS::UnifiedHelpMessage) && p.opts.iter().any(|o| {
|
||||
!o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden)
|
||||
}) {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
|
||||
|
@ -94,13 +92,19 @@ pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
|
|||
let has_last = p.positionals.values().any(|p| p.is_set(ArgSettings::Last));
|
||||
// places a '--' in the usage string if there are args and options
|
||||
// supporting multiple values
|
||||
if p.opts.iter().any(|o| o.is_set(ArgSettings::Multiple)) &&
|
||||
p.positionals.values().any(|p| !p.is_set(ArgSettings::Required)) &&
|
||||
!(p.has_visible_subcommands() || p.is_set(AS::AllowExternalSubcommands)) && !has_last {
|
||||
if p.opts.iter().any(|o| o.is_set(ArgSettings::Multiple))
|
||||
&& p.positionals
|
||||
.values()
|
||||
.any(|p| !p.is_set(ArgSettings::Required))
|
||||
&& !(p.has_visible_subcommands() || p.is_set(AS::AllowExternalSubcommands))
|
||||
&& !has_last
|
||||
{
|
||||
usage.push_str(" [--]");
|
||||
}
|
||||
let not_req_or_hidden =
|
||||
|p: &PosBuilder| (!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last)) && !p.is_set(ArgSettings::Hidden);
|
||||
let not_req_or_hidden = |p: &PosBuilder| {
|
||||
(!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last))
|
||||
&& !p.is_set(ArgSettings::Hidden)
|
||||
};
|
||||
if p.has_positionals() && p.positionals.values().any(not_req_or_hidden) {
|
||||
if let Some(args_tag) = get_args_tag(p, incl_reqs) {
|
||||
usage.push_str(&*args_tag);
|
||||
|
@ -114,7 +118,11 @@ pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
|
|||
.expect(INTERNAL_ERROR_MSG);
|
||||
debugln!("usage::create_help_usage: '{}' has .last(true)", pos.name());
|
||||
let req = pos.is_set(ArgSettings::Required);
|
||||
if req && p.positionals.values().any(|p| !p.is_set(ArgSettings::Required)) {
|
||||
if req
|
||||
&& p.positionals
|
||||
.values()
|
||||
.any(|p| !p.is_set(ArgSettings::Required))
|
||||
{
|
||||
usage.push_str(" -- <");
|
||||
} else if req {
|
||||
usage.push_str(" [--] <");
|
||||
|
@ -161,21 +169,16 @@ fn create_smart_usage(p: &Parser, used: &[&str]) -> String {
|
|||
let mut hs: Vec<&str> = p.required().map(|s| &**s).collect();
|
||||
hs.extend_from_slice(used);
|
||||
|
||||
let r_string =
|
||||
get_required_usage_from(p, &hs, None, None, false).iter().fold(String::new(), |acc, s| {
|
||||
acc + &format!(" {}", s)[..]
|
||||
});
|
||||
let r_string = get_required_usage_from(p, &hs, None, None, false)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
|
||||
|
||||
usage.push_str(&p.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
p.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&p.meta.name)
|
||||
})
|
||||
[..]);
|
||||
usage.push_str(
|
||||
&p.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| p.meta.bin_name.as_ref().unwrap_or(&p.meta.name))[..],
|
||||
);
|
||||
usage.push_str(&*r_string);
|
||||
if p.is_set(AS::SubcommandRequired) {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
|
@ -189,10 +192,11 @@ fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
|
|||
debugln!("usage::get_args_tag;");
|
||||
let mut count = 0;
|
||||
'outer: for pos in p.positionals
|
||||
.values()
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last)) {
|
||||
.values()
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
{
|
||||
debugln!("usage::get_args_tag:iter:{}:", pos.b.name);
|
||||
if let Some(g_vec) = p.groups_for_arg(pos.b.name) {
|
||||
for grp_s in &g_vec {
|
||||
|
@ -204,8 +208,10 @@ fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
|
|||
}
|
||||
}
|
||||
count += 1;
|
||||
debugln!("usage::get_args_tag:iter: {} Args not required or hidden",
|
||||
count);
|
||||
debugln!(
|
||||
"usage::get_args_tag:iter: {} Args not required or hidden",
|
||||
count
|
||||
);
|
||||
}
|
||||
if !p.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
|
||||
debugln!("usage::get_args_tag:iter: More than one, returning [ARGS]");
|
||||
|
@ -214,52 +220,65 @@ fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
|
|||
let pos = p.positionals
|
||||
.values()
|
||||
.find(|pos| {
|
||||
!pos.is_set(ArgSettings::Required) && !pos.is_set(ArgSettings::Hidden) &&
|
||||
!pos.is_set(ArgSettings::Last)
|
||||
})
|
||||
!pos.is_set(ArgSettings::Required) && !pos.is_set(ArgSettings::Hidden)
|
||||
&& !pos.is_set(ArgSettings::Last)
|
||||
})
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
debugln!("usage::get_args_tag:iter: Exactly one, returning '{}'",
|
||||
pos.name());
|
||||
return Some(format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()));
|
||||
debugln!(
|
||||
"usage::get_args_tag:iter: Exactly one, returning '{}'",
|
||||
pos.name()
|
||||
);
|
||||
return Some(format!(
|
||||
" [{}]{}",
|
||||
pos.name_no_brackets(),
|
||||
pos.multiple_str()
|
||||
));
|
||||
} else if p.is_set(AS::DontCollapseArgsInUsage) && !p.positionals.is_empty() && incl_reqs {
|
||||
debugln!("usage::get_args_tag:iter: Don't collapse returning all");
|
||||
return Some(p.positionals
|
||||
.values()
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
.map(|pos| {
|
||||
format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(""));
|
||||
return Some(
|
||||
p.positionals
|
||||
.values()
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
.map(|pos| {
|
||||
format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
);
|
||||
} else if !incl_reqs {
|
||||
debugln!("usage::get_args_tag:iter: incl_reqs=false, building secondary usage string");
|
||||
let highest_req_pos = p.positionals
|
||||
.iter()
|
||||
.filter_map(|(idx, pos)| if pos.b.is_set(ArgSettings::Required) &&
|
||||
!pos.b.is_set(ArgSettings::Last) {
|
||||
Some(idx)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.filter_map(|(idx, pos)| {
|
||||
if pos.b.is_set(ArgSettings::Required) && !pos.b.is_set(ArgSettings::Last) {
|
||||
Some(idx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.max()
|
||||
.unwrap_or_else(|| p.positionals.len());
|
||||
return Some(p.positionals
|
||||
.iter()
|
||||
.filter_map(|(idx, pos)| if idx <= highest_req_pos {
|
||||
Some(pos)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
.map(|pos| {
|
||||
format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(""));
|
||||
return Some(
|
||||
p.positionals
|
||||
.iter()
|
||||
.filter_map(|(idx, pos)| {
|
||||
if idx <= highest_req_pos {
|
||||
Some(pos)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
.map(|pos| {
|
||||
format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
);
|
||||
}
|
||||
Some("".into())
|
||||
}
|
||||
|
@ -296,15 +315,18 @@ fn needs_flags_tag(p: &Parser) -> bool {
|
|||
}
|
||||
|
||||
// Returns the required args in usage string form by fully unrolling all groups
|
||||
pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>,
|
||||
reqs: &[&'a str],
|
||||
matcher: Option<&ArgMatcher<'a>>,
|
||||
extra: Option<&str>,
|
||||
incl_last: bool)
|
||||
-> VecDeque<String> {
|
||||
debugln!("usage::get_required_usage_from: reqs={:?}, extra={:?}",
|
||||
reqs,
|
||||
extra);
|
||||
pub fn get_required_usage_from<'a, 'b>(
|
||||
p: &Parser<'a, 'b>,
|
||||
reqs: &[&'a str],
|
||||
matcher: Option<&ArgMatcher<'a>>,
|
||||
extra: Option<&str>,
|
||||
incl_last: bool,
|
||||
) -> VecDeque<String> {
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: reqs={:?}, extra={:?}",
|
||||
reqs,
|
||||
extra
|
||||
);
|
||||
let mut desc_reqs: Vec<&str> = vec![];
|
||||
desc_reqs.extend(extra);
|
||||
let mut new_reqs: Vec<&str> = vec![];
|
||||
|
@ -346,8 +368,10 @@ pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>,
|
|||
get_requires!(@group a, new_reqs, reqs);
|
||||
}
|
||||
desc_reqs.extend_from_slice(&*new_reqs);
|
||||
debugln!("usage::get_required_usage_from: after init desc_reqs={:?}",
|
||||
desc_reqs);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after init desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
loop {
|
||||
let mut tmp = vec![];
|
||||
for a in &new_reqs {
|
||||
|
@ -361,20 +385,26 @@ pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>,
|
|||
break;
|
||||
} else {
|
||||
debugln!("usage::get_required_usage_from: after iter tmp={:?}", tmp);
|
||||
debugln!("usage::get_required_usage_from: after iter new_reqs={:?}",
|
||||
new_reqs);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after iter new_reqs={:?}",
|
||||
new_reqs
|
||||
);
|
||||
desc_reqs.extend_from_slice(&*new_reqs);
|
||||
new_reqs.clear();
|
||||
new_reqs.extend_from_slice(&*tmp);
|
||||
debugln!("usage::get_required_usage_from: after iter desc_reqs={:?}",
|
||||
desc_reqs);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after iter desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
}
|
||||
}
|
||||
desc_reqs.extend_from_slice(reqs);
|
||||
desc_reqs.sort();
|
||||
desc_reqs.dedup();
|
||||
debugln!("usage::get_required_usage_from: final desc_reqs={:?}",
|
||||
desc_reqs);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: final desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
let mut ret_val = VecDeque::new();
|
||||
let args_in_groups = p.groups
|
||||
.iter()
|
||||
|
@ -383,7 +413,8 @@ pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>,
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let pmap = if let Some(m) = matcher {
|
||||
desc_reqs.iter()
|
||||
desc_reqs
|
||||
.iter()
|
||||
.filter(|a| p.positionals.values().any(|p| &&p.b.name == a))
|
||||
.filter(|&pos| !m.contains(pos))
|
||||
.filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos))
|
||||
|
@ -392,7 +423,8 @@ pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>,
|
|||
.map(|pos| (pos.index, pos))
|
||||
.collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
|
||||
} else {
|
||||
desc_reqs.iter()
|
||||
desc_reqs
|
||||
.iter()
|
||||
.filter(|a| p.positionals.values().any(|pos| &&pos.b.name == a))
|
||||
.filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
|
@ -400,31 +432,39 @@ pub fn get_required_usage_from<'a, 'b>(p: &Parser<'a, 'b>,
|
|||
.map(|pos| (pos.index, pos))
|
||||
.collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
|
||||
};
|
||||
debugln!("usage::get_required_usage_from: args_in_groups={:?}",
|
||||
args_in_groups);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: args_in_groups={:?}",
|
||||
args_in_groups
|
||||
);
|
||||
for &p in pmap.values() {
|
||||
let s = p.to_string();
|
||||
if args_in_groups.is_empty() || !args_in_groups.contains(&&*s) {
|
||||
ret_val.push_back(s);
|
||||
}
|
||||
}
|
||||
for a in desc_reqs.iter()
|
||||
.filter(|name| !p.positionals.values().any(|p| &&p.b.name == name))
|
||||
.filter(|name| !p.groups.iter().any(|g| &&g.name == name))
|
||||
.filter(|name| !args_in_groups.contains(name))
|
||||
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name))) {
|
||||
for a in desc_reqs
|
||||
.iter()
|
||||
.filter(|name| !p.positionals.values().any(|p| &&p.b.name == name))
|
||||
.filter(|name| !p.groups.iter().any(|g| &&g.name == name))
|
||||
.filter(|name| !args_in_groups.contains(name))
|
||||
.filter(|name| {
|
||||
!(matcher.is_some() && matcher.as_ref().unwrap().contains(name))
|
||||
}) {
|
||||
debugln!("usage::get_required_usage_from:iter:{}:", a);
|
||||
let arg = find_by_name!(p, *a, flags, iter)
|
||||
.map(|f| f.to_string())
|
||||
.unwrap_or_else(|| {
|
||||
find_by_name!(p, *a, opts, iter)
|
||||
.map(|o| o.to_string())
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
});
|
||||
find_by_name!(p, *a, opts, iter)
|
||||
.map(|o| o.to_string())
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
});
|
||||
ret_val.push_back(arg);
|
||||
}
|
||||
let mut g_vec: Vec<String> = vec![];
|
||||
for g in desc_reqs.iter().filter(|n| p.groups.iter().any(|g| &&g.name == n)) {
|
||||
for g in desc_reqs
|
||||
.iter()
|
||||
.filter(|n| p.groups.iter().any(|g| &&g.name == n))
|
||||
{
|
||||
let g_string = p.args_in_group(g).join("|");
|
||||
let elem = format!("<{}>", &g_string[..g_string.len()]);
|
||||
if !g_vec.contains(&elem) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// std
|
||||
use std::fmt::Display;
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
// Internal
|
||||
use INTERNAL_ERROR_MSG;
|
||||
|
@ -10,22 +12,24 @@ use errors::{Error, ErrorKind};
|
|||
use errors::Result as ClapResult;
|
||||
use osstringext::OsStrExt2;
|
||||
use app::settings::AppSettings as AS;
|
||||
use app::parser::{Parser, ParseResult};
|
||||
use app::parser::{ParseResult, Parser};
|
||||
use fmt::{Colorizer, ColorizerOption};
|
||||
use app::usage;
|
||||
|
||||
pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>)
|
||||
where 'a: 'b,
|
||||
'b: 'z;
|
||||
where
|
||||
'a: 'b,
|
||||
'b: 'z;
|
||||
|
||||
impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
||||
pub fn new(p: &'z mut Parser<'a, 'b>) -> Self { Validator(p) }
|
||||
|
||||
pub fn validate(&mut self,
|
||||
needs_val_of: ParseResult<'a>,
|
||||
subcmd_name: Option<String>,
|
||||
matcher: &mut ArgMatcher<'a>)
|
||||
-> ClapResult<()> {
|
||||
pub fn validate(
|
||||
&mut self,
|
||||
needs_val_of: ParseResult<'a>,
|
||||
subcmd_name: Option<String>,
|
||||
matcher: &mut ArgMatcher<'a>,
|
||||
) -> ClapResult<()> {
|
||||
debugln!("Validator::validate;");
|
||||
let mut reqs_validated = false;
|
||||
self.0.add_env(matcher)?;
|
||||
|
@ -45,21 +49,24 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
true
|
||||
};
|
||||
if should_err {
|
||||
return Err(Error::empty_value(o,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
return Err(Error::empty_value(
|
||||
o,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if matcher.is_empty() && matcher.subcommand_name().is_none() &&
|
||||
self.0.is_set(AS::ArgRequiredElseHelp) {
|
||||
if matcher.is_empty() && matcher.subcommand_name().is_none()
|
||||
&& self.0.is_set(AS::ArgRequiredElseHelp)
|
||||
{
|
||||
let mut out = vec![];
|
||||
self.0.write_help_err(&mut out)?;
|
||||
return Err(Error {
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
}
|
||||
self.validate_blacklist(matcher)?;
|
||||
if !(self.0.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) && !reqs_validated {
|
||||
|
@ -71,40 +78,54 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_values<A>(&self,
|
||||
arg: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher<'a>)
|
||||
-> ClapResult<()>
|
||||
where A: AnyArg<'a, 'b> + Display
|
||||
fn validate_values<A>(
|
||||
&self,
|
||||
arg: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher<'a>,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_values: arg={:?}", arg.name());
|
||||
for val in &ma.vals {
|
||||
if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() {
|
||||
debugln!("Validator::validate_values: invalid UTF-8 found in val {:?}",
|
||||
val);
|
||||
return Err(Error::invalid_utf8(&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
debugln!(
|
||||
"Validator::validate_values: invalid UTF-8 found in val {:?}",
|
||||
val
|
||||
);
|
||||
return Err(Error::invalid_utf8(
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
if let Some(p_vals) = arg.possible_vals() {
|
||||
debugln!("Validator::validate_values: possible_vals={:?}", p_vals);
|
||||
let val_str = val.to_string_lossy();
|
||||
if !p_vals.contains(&&*val_str) {
|
||||
return Err(Error::invalid_value(val_str,
|
||||
p_vals,
|
||||
arg,
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
let ok = if arg.is_set(ArgSettings::CaseInsensitive) {
|
||||
p_vals.iter().any(|pv| pv.eq_ignore_ascii_case(&*val_str))
|
||||
} else {
|
||||
p_vals.contains(&&*val_str)
|
||||
};
|
||||
if !ok {
|
||||
return Err(Error::invalid_value(
|
||||
val_str,
|
||||
p_vals,
|
||||
arg,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_() &&
|
||||
matcher.contains(&*arg.name()) {
|
||||
if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_()
|
||||
&& matcher.contains(&*arg.name())
|
||||
{
|
||||
debugln!("Validator::validate_values: illegal empty val found");
|
||||
return Err(Error::empty_value(arg,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
return Err(Error::empty_value(
|
||||
arg,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
if let Some(vtor) = arg.validator() {
|
||||
debug!("Validator::validate_values: checking validator...");
|
||||
|
@ -119,9 +140,11 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
debug!("Validator::validate_values: checking validator_os...");
|
||||
if let Err(e) = vtor(val) {
|
||||
sdebugln!("error");
|
||||
return Err(Error::value_validation(Some(arg),
|
||||
(*e).to_string_lossy().to_string(),
|
||||
self.0.color()));
|
||||
return Err(Error::value_validation(
|
||||
Some(arg),
|
||||
(*e).to_string_lossy().to_string(),
|
||||
self.0.color(),
|
||||
));
|
||||
} else {
|
||||
sdebugln!("good");
|
||||
}
|
||||
|
@ -131,8 +154,10 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
}
|
||||
|
||||
fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_blacklist: blacklist={:?}",
|
||||
self.0.blacklist);
|
||||
debugln!(
|
||||
"Validator::validate_blacklist: blacklist={:?}",
|
||||
self.0.blacklist
|
||||
);
|
||||
macro_rules! build_err {
|
||||
($p:expr, $name:expr, $matcher:ident) => ({
|
||||
debugln!("build_err!: name={}", $name);
|
||||
|
@ -166,19 +191,36 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
}
|
||||
|
||||
for name in &self.0.blacklist {
|
||||
debugln!("Validator::validate_blacklist:iter:{}: Checking blacklisted arg", name);
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}: Checking blacklisted arg",
|
||||
name
|
||||
);
|
||||
let mut should_err = false;
|
||||
if self.0.groups.iter().any(|g| &g.name == name) {
|
||||
debugln!("Validator::validate_blacklist:iter:{}: groups contains it...", name);
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}: groups contains it...",
|
||||
name
|
||||
);
|
||||
for n in self.0.arg_names_in_group(name) {
|
||||
debugln!("Validator::validate_blacklist:iter:{}:iter:{}: looking in group...", name, n);
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}:iter:{}: looking in group...",
|
||||
name,
|
||||
n
|
||||
);
|
||||
if matcher.contains(n) {
|
||||
debugln!("Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...", name, n);
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...",
|
||||
name,
|
||||
n
|
||||
);
|
||||
return Err(build_err!(self.0, n, matcher));
|
||||
}
|
||||
}
|
||||
} else if let Some(ma) = matcher.get(name) {
|
||||
debugln!("Validator::validate_blacklist:iter:{}: matcher contains it...", name);
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}: matcher contains it...",
|
||||
name
|
||||
);
|
||||
should_err = ma.occurs > 0;
|
||||
}
|
||||
if should_err {
|
||||
|
@ -191,9 +233,11 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_matched_args;");
|
||||
for (name, ma) in matcher.iter() {
|
||||
debugln!("Validator::validate_matched_args:iter:{}: vals={:#?}",
|
||||
name,
|
||||
ma.vals);
|
||||
debugln!(
|
||||
"Validator::validate_matched_args:iter:{}: vals={:#?}",
|
||||
name,
|
||||
ma.vals
|
||||
);
|
||||
if let Some(opt) = find_by_name!(self.0, *name, opts, iter) {
|
||||
self.validate_arg_num_vals(opt, ma, matcher)?;
|
||||
self.validate_values(opt, ma, matcher)?;
|
||||
|
@ -223,31 +267,35 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_num_occurs<A>(&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher)
|
||||
-> ClapResult<()>
|
||||
where A: AnyArg<'a, 'b> + Display
|
||||
fn validate_arg_num_occurs<A>(
|
||||
&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_num_occurs: a={};", a.name());
|
||||
if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage(a,
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
return Err(Error::unexpected_multiple_usage(
|
||||
a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_num_vals<A>(&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher)
|
||||
-> ClapResult<()>
|
||||
where A: AnyArg<'a, 'b> + Display
|
||||
fn validate_arg_num_vals<A>(
|
||||
&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_num_vals;");
|
||||
if let Some(num) = a.num_vals() {
|
||||
|
@ -259,74 +307,79 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
};
|
||||
if should_err {
|
||||
debugln!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
|
||||
return Err(Error::wrong_number_of_values(a,
|
||||
num,
|
||||
if a.is_set(ArgSettings::Multiple) {
|
||||
(ma.vals.len() % num as usize)
|
||||
} else {
|
||||
ma.vals.len()
|
||||
},
|
||||
if ma.vals.len() == 1 ||
|
||||
(a.is_set(ArgSettings::Multiple) &&
|
||||
(ma.vals.len() % num as usize) ==
|
||||
1) {
|
||||
"as"
|
||||
} else {
|
||||
"ere"
|
||||
},
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
return Err(Error::wrong_number_of_values(
|
||||
a,
|
||||
num,
|
||||
if a.is_set(ArgSettings::Multiple) {
|
||||
(ma.vals.len() % num as usize)
|
||||
} else {
|
||||
ma.vals.len()
|
||||
},
|
||||
if ma.vals.len() == 1
|
||||
|| (a.is_set(ArgSettings::Multiple) && (ma.vals.len() % num as usize) == 1)
|
||||
{
|
||||
"as"
|
||||
} else {
|
||||
"ere"
|
||||
},
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(num) = a.max_vals() {
|
||||
debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num);
|
||||
if (ma.vals.len() as u64) > num {
|
||||
debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues");
|
||||
return Err(Error::too_many_values(ma.vals
|
||||
.iter()
|
||||
.last()
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.to_str()
|
||||
.expect(INVALID_UTF8),
|
||||
a,
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
return Err(Error::too_many_values(
|
||||
ma.vals
|
||||
.iter()
|
||||
.last()
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.to_str()
|
||||
.expect(INVALID_UTF8),
|
||||
a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let min_vals_zero = if let Some(num) = a.min_vals() {
|
||||
debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num);
|
||||
if (ma.vals.len() as u64) < num && num != 0 {
|
||||
debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues");
|
||||
return Err(Error::too_few_values(a,
|
||||
num,
|
||||
ma.vals.len(),
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
return Err(Error::too_few_values(
|
||||
a,
|
||||
num,
|
||||
ma.vals.len(),
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
num == 0
|
||||
} else { false };
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// Issue 665 (https://github.com/kbknapp/clap-rs/issues/665)
|
||||
// Issue 1105 (https://github.com/kbknapp/clap-rs/issues/1105)
|
||||
if a.takes_value() && !min_vals_zero && ma.vals.is_empty() {
|
||||
return Err(Error::empty_value(a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
return Err(Error::empty_value(
|
||||
a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_requires<A>(&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher)
|
||||
-> ClapResult<()>
|
||||
where A: AnyArg<'a, 'b> + Display
|
||||
fn validate_arg_requires<A>(
|
||||
&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_requires;");
|
||||
if let Some(a_reqs) = a.requires() {
|
||||
|
@ -342,8 +395,10 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
}
|
||||
|
||||
fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_required: required={:?};",
|
||||
self.0.required);
|
||||
debugln!(
|
||||
"Validator::validate_required: required={:?};",
|
||||
self.0.required
|
||||
);
|
||||
'outer: for name in &self.0.required {
|
||||
debugln!("Validator::validate_required:iter:{}:", name);
|
||||
if matcher.contains(name) {
|
||||
|
@ -377,25 +432,25 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
}
|
||||
|
||||
fn validate_conflicts<A>(&self, a: &A, matcher: &ArgMatcher) -> Option<bool>
|
||||
where A: AnyArg<'a, 'b>
|
||||
where
|
||||
A: AnyArg<'a, 'b>,
|
||||
{
|
||||
debugln!("Validator::validate_conflicts: a={:?};", a.name());
|
||||
a.blacklist()
|
||||
.map(|bl| {
|
||||
bl.iter()
|
||||
.any(|conf| {
|
||||
matcher.contains(conf) ||
|
||||
self.0
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| &g.name == conf)
|
||||
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
|
||||
})
|
||||
a.blacklist().map(|bl| {
|
||||
bl.iter().any(|conf| {
|
||||
matcher.contains(conf)
|
||||
|| self.0
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| &g.name == conf)
|
||||
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_required_unless<A>(&self, a: &A, matcher: &ArgMatcher) -> Option<bool>
|
||||
where A: AnyArg<'a, 'b>
|
||||
where
|
||||
A: AnyArg<'a, 'b>,
|
||||
{
|
||||
debugln!("Validator::validate_required_unless: a={:?};", a.name());
|
||||
macro_rules! check {
|
||||
|
@ -426,11 +481,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
use_stderr: true,
|
||||
when: self.0.color(),
|
||||
});
|
||||
let mut reqs = self.0
|
||||
.required
|
||||
.iter()
|
||||
.map(|&r| &*r)
|
||||
.collect::<Vec<_>>();
|
||||
let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>();
|
||||
if let Some(r) = extra {
|
||||
reqs.push(r);
|
||||
}
|
||||
|
@ -440,22 +491,27 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
let req_args =
|
||||
usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true)
|
||||
.iter()
|
||||
.fold(String::new(),
|
||||
|acc, s| acc + &format!("\n {}", c.error(s))[..]);
|
||||
debugln!("Validator::missing_required_error: req_args={:#?}",
|
||||
req_args);
|
||||
Err(Error::missing_required_argument(&*req_args,
|
||||
&*usage::create_error_usage(self.0, matcher, extra),
|
||||
self.0.color()))
|
||||
.fold(String::new(), |acc, s| {
|
||||
acc + &format!("\n {}", c.error(s))[..]
|
||||
});
|
||||
debugln!(
|
||||
"Validator::missing_required_error: req_args={:#?}",
|
||||
req_args
|
||||
);
|
||||
Err(Error::missing_required_argument(
|
||||
&*req_args,
|
||||
&*usage::create_error_usage(self.0, matcher, extra),
|
||||
self.0.color(),
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_missing_required_ok<A>(&self, a: &A, matcher: &ArgMatcher) -> bool
|
||||
where A: AnyArg<'a, 'b>
|
||||
where
|
||||
A: AnyArg<'a, 'b>,
|
||||
{
|
||||
debugln!("Validator::is_missing_required_ok: a={}", a.name());
|
||||
self.validate_conflicts(a, matcher).unwrap_or(false) ||
|
||||
self.validate_required_unless(a, matcher)
|
||||
.unwrap_or(false)
|
||||
self.validate_conflicts(a, matcher).unwrap_or(false)
|
||||
|| self.validate_required_unless(a, matcher).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
|
223
src/args/arg.rs
223
src/args/arg.rs
|
@ -1,10 +1,10 @@
|
|||
#[cfg(feature = "yaml")]
|
||||
use std::collections::BTreeMap;
|
||||
use std::rc::Rc;
|
||||
use std::ffi::{OsString, OsStr};
|
||||
#[cfg(target_os="windows")]
|
||||
use std::ffi::{OsStr, OsString};
|
||||
#[cfg(target_os = "windows")]
|
||||
use osstringext::OsStrExt3;
|
||||
#[cfg(not(target_os="windows"))]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::env;
|
||||
|
||||
|
@ -14,7 +14,7 @@ use map::VecMap;
|
|||
|
||||
use usage_parser::UsageParser;
|
||||
use args::settings::ArgSettings;
|
||||
use args::arg_builder::{Base, Valued, Switched};
|
||||
use args::arg_builder::{Base, Switched, Valued};
|
||||
|
||||
/// The abstract representation of a command line argument. Used to set all the options and
|
||||
/// relationships that define a valid argument for the program.
|
||||
|
@ -41,18 +41,14 @@ use args::arg_builder::{Base, Valued, Switched};
|
|||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Arg<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
#[doc(hidden)]
|
||||
pub b: Base<'a, 'b>,
|
||||
#[doc(hidden)]
|
||||
pub s: Switched<'b>,
|
||||
#[doc(hidden)]
|
||||
pub v: Valued<'a, 'b>,
|
||||
#[doc(hidden)]
|
||||
pub index: Option<u64>,
|
||||
#[doc(hidden)]
|
||||
pub r_ifs: Option<Vec<(&'a str, &'b str)>>,
|
||||
#[doc(hidden)] pub b: Base<'a, 'b>,
|
||||
#[doc(hidden)] pub s: Switched<'b>,
|
||||
#[doc(hidden)] pub v: Valued<'a, 'b>,
|
||||
#[doc(hidden)] pub index: Option<u64>,
|
||||
#[doc(hidden)] pub r_ifs: Option<Vec<(&'a str, &'b str)>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> Arg<'a, 'b> {
|
||||
|
@ -73,7 +69,12 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// ```
|
||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||
/// [`Arg`]: ./struct.Arg.html
|
||||
pub fn with_name(n: &'a str) -> Self { Arg { b: Base::new(n), ..Default::default() } }
|
||||
pub fn with_name(n: &'a str) -> Self {
|
||||
Arg {
|
||||
b: Base::new(n),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance of [`Arg`] from a .yml (YAML) file.
|
||||
///
|
||||
|
@ -143,11 +144,11 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
a.setb(ArgSettings::RequiredUnlessAll);
|
||||
a
|
||||
}
|
||||
s => {
|
||||
panic!("Unknown Arg setting '{}' in YAML file for arg '{}'",
|
||||
s,
|
||||
name_str)
|
||||
}
|
||||
s => panic!(
|
||||
"Unknown Arg setting '{}' in YAML file for arg '{}'",
|
||||
s,
|
||||
name_str
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,10 +606,10 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// that cannot be read by this program. Obviously I'm going on
|
||||
/// and on, so I'll stop now.
|
||||
///
|
||||
/// -h, --help
|
||||
/// -h, --help
|
||||
/// Prints help information
|
||||
///
|
||||
/// -V, --version
|
||||
/// -V, --version
|
||||
/// Prints version information
|
||||
/// ```
|
||||
/// [`Arg::help`]: ./struct.Arg.html#method.help
|
||||
|
@ -624,13 +625,13 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// allows one to access this arg early using the `--` syntax. Accessing an arg early, even with
|
||||
/// the `--` syntax is otherwise not possible.
|
||||
///
|
||||
/// **NOTE:** This will change the usage string to look like `$ prog [FLAGS] [-- <ARG>]` if
|
||||
/// **NOTE:** This will change the usage string to look like `$ prog [FLAGS] [-- <ARG>]` if
|
||||
/// `ARG` is marked as `.last(true)`.
|
||||
///
|
||||
/// **NOTE:** This setting will imply [`AppSettings::DontCollapseArgsInUsage`] because failing
|
||||
/// to set this can make the usage string very confusing.
|
||||
///
|
||||
/// **NOTE**: This setting only applies to positional arguments, and has no affect on FLAGS /
|
||||
/// **NOTE**: This setting only applies to positional arguments, and has no affect on FLAGS /
|
||||
/// OPTIONS
|
||||
///
|
||||
/// **CAUTION:** Setting an argument to `.last(true)` *and* having child subcommands is not
|
||||
|
@ -1891,10 +1892,10 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// **WARNING:**
|
||||
///
|
||||
/// Setting `multiple(true)` for an [option] with no other details, allows multiple values
|
||||
/// **and** multiple occurrences because it isn't possible to have more occurrences than values
|
||||
/// for options. Because multiple values are allowed, `--option val1 val2 val3` is perfectly
|
||||
/// valid, be careful when designing a CLI where positional arguments are expected after a
|
||||
/// option which accepts multiple values, as `clap` will continue parsing *values* until it
|
||||
/// **and** multiple occurrences because it isn't possible to have more occurrences than values
|
||||
/// for options. Because multiple values are allowed, `--option val1 val2 val3` is perfectly
|
||||
/// valid, be careful when designing a CLI where positional arguments are expected after a
|
||||
/// option which accepts multiple values, as `clap` will continue parsing *values* until it
|
||||
/// reaches the max or specific number of values defined, or another flag or option.
|
||||
///
|
||||
/// **Pro Tip**:
|
||||
|
@ -1904,35 +1905,35 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Arg::multiple(true)`].
|
||||
///
|
||||
/// **WARNING:**
|
||||
///
|
||||
///
|
||||
/// When using args with `multiple(true)` on [options] or [positionals] (i.e. those args that
|
||||
/// accept values) and [subcommands], one needs to consider the posibility of an argument value
|
||||
/// being the same as a valid subcommand. By default `clap` will parse the argument in question
|
||||
/// as a value *only if* a value is possible at that moment. Otherwise it will be parsed as a
|
||||
/// subcommand. In effect, this means using `multiple(true)` with no additional parameters and
|
||||
/// a possible value that coincides with a subcommand name, the subcommand cannot be called
|
||||
/// a possible value that coincides with a subcommand name, the subcommand cannot be called
|
||||
/// unless another argument is passed first.
|
||||
///
|
||||
///
|
||||
/// As an example, consider a CLI with an option `--ui-paths=<paths>...` and subcommand `signer`
|
||||
///
|
||||
///
|
||||
/// The following would be parsed as values to `--ui-paths`.
|
||||
///
|
||||
///
|
||||
/// ```notrust
|
||||
/// $ program --ui-paths path1 path2 signer
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// This is because `--ui-paths` accepts multiple values. `clap` will continue parsing values
|
||||
/// until another argument is reached and it knows `--ui-paths` is done.
|
||||
///
|
||||
///
|
||||
/// By adding additional parameters to `--ui-paths` we can solve this issue. Consider adding
|
||||
/// [`Arg::number_of_values(1)`] as discussed above. The following are all valid, and `signer`
|
||||
/// [`Arg::number_of_values(1)`] as discussed above. The following are all valid, and `signer`
|
||||
/// is parsed as both a subcommand and a value in the second case.
|
||||
///
|
||||
///
|
||||
/// ```notrust
|
||||
/// $ program --ui-paths path1 signer
|
||||
/// $ program --ui-paths path1 --ui-paths signer signer
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
|
@ -2133,8 +2134,8 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// Specifies that an argument can be matched to all child [`SubCommand`]s.
|
||||
///
|
||||
/// **NOTE:** Global arguments *only* propagate down, **not** up (to parent commands), however
|
||||
/// their values once a user uses them will be propagated back up to parents. In effect, this
|
||||
/// means one should *define* all global arguments at the top level, however it doesn't matter
|
||||
/// their values once a user uses them will be propagated back up to parents. In effect, this
|
||||
/// means one should *define* all global arguments at the top level, however it doesn't matter
|
||||
/// where the user *uses* the global argument.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -2390,6 +2391,59 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
self
|
||||
}
|
||||
|
||||
/// When used with [`Arg::possible_values`] it allows the argument value to pass validation even if
|
||||
/// the case differs from that of the specified `possible_value`.
|
||||
///
|
||||
/// **Pro Tip:** Use this setting with [`arg_enum!`]
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use std::ascii::AsciiExt;
|
||||
/// let m = App::new("pv")
|
||||
/// .arg(Arg::with_name("option")
|
||||
/// .long("--option")
|
||||
/// .takes_value(true)
|
||||
/// .possible_value("test123")
|
||||
/// .case_insensitive(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "pv", "--option", "TeSt123",
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(m.value_of("option").unwrap().eq_ignore_ascii_case("test123"));
|
||||
/// ```
|
||||
///
|
||||
/// This setting also works when multiple values can be defined:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg};
|
||||
/// let m = App::new("pv")
|
||||
/// .arg(Arg::with_name("option")
|
||||
/// .short("-o")
|
||||
/// .long("--option")
|
||||
/// .takes_value(true)
|
||||
/// .possible_value("test123")
|
||||
/// .possible_value("test321")
|
||||
/// .multiple(true)
|
||||
/// .case_insensitive(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "pv", "--option", "TeSt123", "teST123", "tESt321"
|
||||
/// ]);
|
||||
///
|
||||
/// let matched_vals = m.values_of("option").unwrap().collect::<Vec<_>>();
|
||||
/// assert_eq!(&*matched_vals, &["TeSt123", "teST123", "tESt321"]);
|
||||
/// ```
|
||||
/// [`Arg::case_insensitive(true)`]: ./struct.Arg.html#method.possible_values
|
||||
/// [`arg_enum!`]: ./macro.arg_enum.html
|
||||
pub fn case_insensitive(self, ci: bool) -> Self {
|
||||
if ci {
|
||||
self.set(ArgSettings::CaseInsensitive)
|
||||
} else {
|
||||
self.unset(ArgSettings::CaseInsensitive)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the name of the [`ArgGroup`] the argument belongs to.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -2550,19 +2604,20 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
||||
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||
pub fn validator<F>(mut self, f: F) -> Self
|
||||
where F: Fn(String) -> Result<(), String> + 'static
|
||||
where
|
||||
F: Fn(String) -> Result<(), String> + 'static,
|
||||
{
|
||||
self.v.validator = Some(Rc::new(f));
|
||||
self
|
||||
}
|
||||
|
||||
/// Works identically to Validator but is intended to be used with values that could
|
||||
/// Works identically to Validator but is intended to be used with values that could
|
||||
/// contain non UTF-8 formatted strings.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```rust")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```rust")]
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use std::ffi::{OsStr, OsString};
|
||||
/// # use std::os::unix::ffi::OsStrExt;
|
||||
|
@ -2587,7 +2642,8 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
||||
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||
pub fn validator_os<F>(mut self, f: F) -> Self
|
||||
where F: Fn(&OsStr) -> Result<(), OsString> + 'static
|
||||
where
|
||||
F: Fn(&OsStr) -> Result<(), OsString> + 'static,
|
||||
{
|
||||
self.v.validator_os = Some(Rc::new(f));
|
||||
self
|
||||
|
@ -2890,9 +2946,11 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
self.unsetb(ArgSettings::ValueDelimiterNotSet);
|
||||
self.setb(ArgSettings::TakesValue);
|
||||
self.setb(ArgSettings::UseValueDelimiter);
|
||||
self.v.val_delim = Some(d.chars()
|
||||
.nth(0)
|
||||
.expect("Failed to get value_delimiter from arg"));
|
||||
self.v.val_delim = Some(
|
||||
d.chars()
|
||||
.nth(0)
|
||||
.expect("Failed to get value_delimiter from arg"),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -3210,20 +3268,23 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
||||
pub fn default_value_if(self, arg: &'a str, val: Option<&'b str>, default: &'b str) -> Self {
|
||||
self.default_value_if_os(arg,
|
||||
val.map(str::as_bytes).map(OsStr::from_bytes),
|
||||
OsStr::from_bytes(default.as_bytes()))
|
||||
self.default_value_if_os(
|
||||
arg,
|
||||
val.map(str::as_bytes).map(OsStr::from_bytes),
|
||||
OsStr::from_bytes(default.as_bytes()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`]
|
||||
/// only using [`OsStr`]s instead.
|
||||
/// [`Arg::default_value_if`]: ./struct.Arg.html#method.default_value_if
|
||||
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
||||
pub fn default_value_if_os(mut self,
|
||||
arg: &'a str,
|
||||
val: Option<&'b OsStr>,
|
||||
default: &'b OsStr)
|
||||
-> Self {
|
||||
pub fn default_value_if_os(
|
||||
mut self,
|
||||
arg: &'a str,
|
||||
val: Option<&'b OsStr>,
|
||||
default: &'b OsStr,
|
||||
) -> Self {
|
||||
self.setb(ArgSettings::TakesValue);
|
||||
if let Some(ref mut vm) = self.v.default_vals_ifs {
|
||||
let l = vm.len();
|
||||
|
@ -3322,9 +3383,11 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
||||
pub fn default_value_ifs(mut self, ifs: &[(&'a str, Option<&'b str>, &'b str)]) -> Self {
|
||||
for &(arg, val, default) in ifs {
|
||||
self = self.default_value_if_os(arg,
|
||||
val.map(str::as_bytes).map(OsStr::from_bytes),
|
||||
OsStr::from_bytes(default.as_bytes()));
|
||||
self = self.default_value_if_os(
|
||||
arg,
|
||||
val.map(str::as_bytes).map(OsStr::from_bytes),
|
||||
OsStr::from_bytes(default.as_bytes()),
|
||||
);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -3344,7 +3407,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// Specifies that if the value is not passed in as an argument, that it should be retrieved
|
||||
/// from the environment, if available. If it is not present in the environment, then default
|
||||
/// rules will apply.
|
||||
///
|
||||
///
|
||||
/// **NOTE:** If the user *does not* use this argument at runtime, [`ArgMatches::occurrences_of`]
|
||||
/// will return `0` even though the [`ArgMatches::value_of`] will return the default specified.
|
||||
///
|
||||
|
@ -3352,23 +3415,23 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// return `true` if the variable is present in the environemnt . If you wish to determine whether
|
||||
/// the argument was used at runtime or not, consider [`ArgMatches::occurrences_of`] which will
|
||||
/// return `0` if the argument was *not* used at runtime.
|
||||
///
|
||||
///
|
||||
/// **NOTE:** This implicitly sets [`Arg::takes_value(true)`].
|
||||
///
|
||||
///
|
||||
/// **NOTE:** If [`Arg::multiple(true)`] is set then [`Arg::use_delimiter(true)`] should also be
|
||||
/// set. Otherwise, only a single argument will be returned from the environment variable. The
|
||||
/// default delimiter is `,` and follows all the other delimiter rules.
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
///
|
||||
/// In this example, we show the variable coming from the environment:
|
||||
///
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG", "env");
|
||||
///
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
|
@ -3379,15 +3442,15 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
///
|
||||
/// assert_eq!(m.value_of("flag"), Some("env"));
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// In this example, we show the variable coming from an option on the CLI:
|
||||
///
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG", "env");
|
||||
///
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
|
@ -3398,16 +3461,16 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
///
|
||||
/// assert_eq!(m.value_of("flag"), Some("opt"));
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// In this example, we show the variable coming from the environment even with the
|
||||
/// presence of a default:
|
||||
///
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG", "env");
|
||||
///
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
|
@ -3419,15 +3482,15 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
///
|
||||
/// assert_eq!(m.value_of("flag"), Some("env"));
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// In this example, we show the use of multiple values in a single environment variable:
|
||||
///
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG_MULTI", "env1,env2");
|
||||
///
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
|
@ -3440,9 +3503,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
///
|
||||
/// assert_eq!(m.values_of("flag").unwrap().collect::<Vec<_>>(), vec!["env1", "env2"]);
|
||||
/// ```
|
||||
pub fn env(self, name: &'a str) -> Self {
|
||||
self.env_os(OsStr::new(name))
|
||||
}
|
||||
pub fn env(self, name: &'a str) -> Self { self.env_os(OsStr::new(name)) }
|
||||
|
||||
/// Specifies that if the value is not passed in as an argument, that it should be retrieved
|
||||
/// from the environment if available in the exact same manner as [`Arg::env`] only using
|
||||
|
@ -3606,7 +3667,5 @@ impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for Arg<'a, 'b> {
|
|||
}
|
||||
|
||||
impl<'n, 'e> PartialEq for Arg<'n, 'e> {
|
||||
fn eq(&self, other: &Arg<'n, 'e>) -> bool {
|
||||
self.b == other.b
|
||||
}
|
||||
fn eq(&self, other: &Arg<'n, 'e>) -> bool { self.b == other.b }
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
use args::{ArgSettings, Arg, ArgFlags};
|
||||
use args::{Arg, ArgFlags, ArgSettings};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Base<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
pub name: &'a str,
|
||||
pub help: Option<&'b str>,
|
||||
|
@ -17,7 +17,12 @@ pub struct Base<'a, 'b>
|
|||
}
|
||||
|
||||
impl<'n, 'e> Base<'n, 'e> {
|
||||
pub fn new(name: &'n str) -> Self { Base { name: name, ..Default::default() } }
|
||||
pub fn new(name: &'n str) -> Self {
|
||||
Base {
|
||||
name: name,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, s: ArgSettings) { self.settings.set(s); }
|
||||
pub fn unset(&mut self, s: ArgSettings) { self.settings.unset(s); }
|
||||
|
@ -29,7 +34,5 @@ impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Base<'n, 'e> {
|
|||
}
|
||||
|
||||
impl<'n, 'e> PartialEq for Base<'n, 'e> {
|
||||
fn eq(&self, other: &Base<'n, 'e>) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
||||
fn eq(&self, other: &Base<'n, 'e>) -> bool { self.name == other.name }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
use Arg;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -21,16 +21,19 @@ impl<'a> Default for ArgMatcher<'a> {
|
|||
impl<'a> ArgMatcher<'a> {
|
||||
pub fn new() -> Self { ArgMatcher::default() }
|
||||
|
||||
pub fn propagate_globals(&mut self, global_arg_vec : &[&'a str]) {
|
||||
debugln!("ArgMatcher::get_global_values: global_arg_vec={:?}", global_arg_vec);
|
||||
pub fn propagate_globals(&mut self, global_arg_vec: &[&'a str]) {
|
||||
debugln!(
|
||||
"ArgMatcher::get_global_values: global_arg_vec={:?}",
|
||||
global_arg_vec
|
||||
);
|
||||
let mut vals_map = HashMap::new();
|
||||
self.fill_in_global_values(global_arg_vec, &mut vals_map);
|
||||
}
|
||||
|
||||
fn fill_in_global_values(
|
||||
&mut self,
|
||||
global_arg_vec: &[&'a str],
|
||||
vals_map: &mut HashMap<&'a str, MatchedArg>
|
||||
&mut self,
|
||||
global_arg_vec: &[&'a str],
|
||||
vals_map: &mut HashMap<&'a str, MatchedArg>,
|
||||
) {
|
||||
for global_arg in global_arg_vec {
|
||||
if let Some(ma) = self.get(global_arg) {
|
||||
|
@ -120,7 +123,8 @@ impl<'a> ArgMatcher<'a> {
|
|||
}
|
||||
|
||||
pub fn needs_more_vals<'b, A>(&self, o: &A) -> bool
|
||||
where A: AnyArg<'a, 'b>
|
||||
where
|
||||
A: AnyArg<'a, 'b>,
|
||||
{
|
||||
debugln!("ArgMatcher::needs_more_vals: o={}", o.name());
|
||||
if let Some(ma) = self.get(o.name()) {
|
||||
|
|
|
@ -59,12 +59,9 @@ use args::SubCommand;
|
|||
/// [`App::get_matches`]: ./struct.App.html#method.get_matches
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ArgMatches<'a> {
|
||||
#[doc(hidden)]
|
||||
pub args: HashMap<&'a str, MatchedArg>,
|
||||
#[doc(hidden)]
|
||||
pub subcommand: Option<Box<SubCommand<'a>>>,
|
||||
#[doc(hidden)]
|
||||
pub usage: Option<String>,
|
||||
#[doc(hidden)] pub args: HashMap<&'a str, MatchedArg>,
|
||||
#[doc(hidden)] pub subcommand: Option<Box<SubCommand<'a>>>,
|
||||
#[doc(hidden)] pub usage: Option<String>,
|
||||
}
|
||||
|
||||
impl<'a> Default for ArgMatches<'a> {
|
||||
|
@ -79,7 +76,11 @@ impl<'a> Default for ArgMatches<'a> {
|
|||
|
||||
impl<'a> ArgMatches<'a> {
|
||||
#[doc(hidden)]
|
||||
pub fn new() -> Self { ArgMatches { ..Default::default() } }
|
||||
pub fn new() -> Self {
|
||||
ArgMatches {
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the value of a specific [option] or [positional] argument (i.e. an argument that takes
|
||||
/// an additional value at runtime). If the option wasn't present at runtime
|
||||
|
@ -126,8 +127,8 @@ impl<'a> ArgMatches<'a> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg};
|
||||
/// use std::ffi::OsString;
|
||||
/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
|
||||
|
@ -161,8 +162,8 @@ impl<'a> ArgMatches<'a> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg};
|
||||
/// use std::ffi::OsString;
|
||||
/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
|
||||
|
@ -211,7 +212,9 @@ impl<'a> ArgMatches<'a> {
|
|||
if let Some(arg) = self.args.get(name.as_ref()) {
|
||||
fn to_str_slice(o: &OsString) -> &str { o.to_str().expect(INVALID_UTF8) }
|
||||
let to_str_slice: fn(&OsString) -> &str = to_str_slice; // coerce to fn pointer
|
||||
return Some(Values { iter: arg.vals.iter().map(to_str_slice) });
|
||||
return Some(Values {
|
||||
iter: arg.vals.iter().map(to_str_slice),
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -222,8 +225,8 @@ impl<'a> ArgMatches<'a> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg};
|
||||
/// use std::ffi::OsString;
|
||||
/// use std::os::unix::ffi::OsStringExt;
|
||||
|
@ -242,10 +245,12 @@ impl<'a> ArgMatches<'a> {
|
|||
/// ```
|
||||
pub fn values_of_lossy<S: AsRef<str>>(&'a self, name: S) -> Option<Vec<String>> {
|
||||
if let Some(arg) = self.args.get(name.as_ref()) {
|
||||
return Some(arg.vals
|
||||
.iter()
|
||||
.map(|v| v.to_string_lossy().into_owned())
|
||||
.collect());
|
||||
return Some(
|
||||
arg.vals
|
||||
.iter()
|
||||
.map(|v| v.to_string_lossy().into_owned())
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -258,8 +263,8 @@ impl<'a> ArgMatches<'a> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg};
|
||||
/// use std::ffi::{OsStr,OsString};
|
||||
/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
|
||||
|
@ -285,7 +290,9 @@ impl<'a> ArgMatches<'a> {
|
|||
fn to_str_slice(o: &OsString) -> &OsStr { &*o }
|
||||
let to_str_slice: fn(&'a OsString) -> &'a OsStr = to_str_slice; // coerce to fn pointer
|
||||
if let Some(arg) = self.args.get(name.as_ref()) {
|
||||
return Some(OsValues { iter: arg.vals.iter().map(to_str_slice) });
|
||||
return Some(OsValues {
|
||||
iter: arg.vals.iter().map(to_str_slice),
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -507,7 +514,9 @@ impl<'a> ArgMatches<'a> {
|
|||
/// [`ArgMatches::subcommand_matches`]: ./struct.ArgMatches.html#method.subcommand_matches
|
||||
/// [`ArgMatches::subcommand_name`]: ./struct.ArgMatches.html#method.subcommand_name
|
||||
pub fn subcommand(&self) -> (&str, Option<&ArgMatches<'a>>) {
|
||||
self.subcommand.as_ref().map_or(("", None), |sc| (&sc.name[..], Some(&sc.matches)))
|
||||
self.subcommand
|
||||
.as_ref()
|
||||
.map_or(("", None), |sc| (&sc.name[..], Some(&sc.matches)))
|
||||
}
|
||||
|
||||
/// Returns a string slice of the usage statement for the [`App`] or [`SubCommand`]
|
||||
|
@ -573,7 +582,9 @@ impl<'a> Default for Values<'a> {
|
|||
static EMPTY: [OsString; 0] = [];
|
||||
// This is never called because the iterator is empty:
|
||||
fn to_str_slice(_: &OsString) -> &str { unreachable!() };
|
||||
Values { iter: EMPTY[..].iter().map(to_str_slice) }
|
||||
Values {
|
||||
iter: EMPTY[..].iter().map(to_str_slice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,8 +607,8 @@ fn test_default_values_with_shorter_lifetime() {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg};
|
||||
/// use std::ffi::OsString;
|
||||
/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
|
||||
|
@ -634,7 +645,9 @@ impl<'a> Default for OsValues<'a> {
|
|||
static EMPTY: [OsString; 0] = [];
|
||||
// This is never called because the iterator is empty:
|
||||
fn to_str_slice(_: &OsString) -> &OsStr { unreachable!() };
|
||||
OsValues { iter: EMPTY[..].iter().map(to_str_slice) }
|
||||
OsValues {
|
||||
iter: EMPTY[..].iter().map(to_str_slice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,18 +79,12 @@ use yaml_rust::Yaml;
|
|||
/// [requirement]: ./struct.Arg.html#method.requires
|
||||
#[derive(Default)]
|
||||
pub struct ArgGroup<'a> {
|
||||
#[doc(hidden)]
|
||||
pub name: &'a str,
|
||||
#[doc(hidden)]
|
||||
pub args: Vec<&'a str>,
|
||||
#[doc(hidden)]
|
||||
pub required: bool,
|
||||
#[doc(hidden)]
|
||||
pub requires: Option<Vec<&'a str>>,
|
||||
#[doc(hidden)]
|
||||
pub conflicts: Option<Vec<&'a str>>,
|
||||
#[doc(hidden)]
|
||||
pub multiple: bool,
|
||||
#[doc(hidden)] pub name: &'a str,
|
||||
#[doc(hidden)] pub args: Vec<&'a str>,
|
||||
#[doc(hidden)] pub required: bool,
|
||||
#[doc(hidden)] pub requires: Option<Vec<&'a str>>,
|
||||
#[doc(hidden)] pub conflicts: Option<Vec<&'a str>>,
|
||||
#[doc(hidden)] pub multiple: bool,
|
||||
}
|
||||
|
||||
impl<'a> ArgGroup<'a> {
|
||||
|
@ -154,9 +148,11 @@ impl<'a> ArgGroup<'a> {
|
|||
/// [argument]: ./struct.Arg.html
|
||||
#[cfg_attr(feature = "lints", allow(should_assert_eq))]
|
||||
pub fn arg(mut self, n: &'a str) -> Self {
|
||||
assert!(self.name != n,
|
||||
"ArgGroup '{}' can not have same name as arg inside it",
|
||||
&*self.name);
|
||||
assert!(
|
||||
self.name != n,
|
||||
"ArgGroup '{}' can not have same name as arg inside it",
|
||||
&*self.name
|
||||
);
|
||||
self.args.push(n);
|
||||
self
|
||||
}
|
||||
|
@ -426,19 +422,21 @@ impl<'a> ArgGroup<'a> {
|
|||
|
||||
impl<'a> Debug for ArgGroup<'a> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
write!(f,
|
||||
"{{\n\
|
||||
\tname: {:?},\n\
|
||||
\targs: {:?},\n\
|
||||
\trequired: {:?},\n\
|
||||
\trequires: {:?},\n\
|
||||
\tconflicts: {:?},\n\
|
||||
}}",
|
||||
self.name,
|
||||
self.args,
|
||||
self.required,
|
||||
self.requires,
|
||||
self.conflicts)
|
||||
write!(
|
||||
f,
|
||||
"{{\n\
|
||||
\tname: {:?},\n\
|
||||
\targs: {:?},\n\
|
||||
\trequired: {:?},\n\
|
||||
\trequires: {:?},\n\
|
||||
\tconflicts: {:?},\n\
|
||||
}}",
|
||||
self.name,
|
||||
self.args,
|
||||
self.required,
|
||||
self.requires,
|
||||
self.conflicts
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,7 +460,9 @@ impl<'a> From<&'a BTreeMap<Yaml, Yaml>> for ArgGroup<'a> {
|
|||
let mut a = ArgGroup::default();
|
||||
let group_settings = if b.len() == 1 {
|
||||
let name_yml = b.keys().nth(0).expect("failed to get name");
|
||||
let name_str = name_yml.as_str().expect("failed to convert arg YAML name to str");
|
||||
let name_str = name_yml
|
||||
.as_str()
|
||||
.expect("failed to convert arg YAML name to str");
|
||||
a.name = name_str;
|
||||
b.get(name_yml)
|
||||
.expect("failed to get name_str")
|
||||
|
@ -491,12 +491,12 @@ impl<'a> From<&'a BTreeMap<Yaml, Yaml>> for ArgGroup<'a> {
|
|||
}
|
||||
a
|
||||
}
|
||||
s => {
|
||||
panic!("Unknown ArgGroup setting '{}' in YAML file for \
|
||||
ArgGroup '{}'",
|
||||
s,
|
||||
a.name)
|
||||
}
|
||||
s => panic!(
|
||||
"Unknown ArgGroup setting '{}' in YAML file for \
|
||||
ArgGroup '{}'",
|
||||
s,
|
||||
a.name
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,17 +551,19 @@ mod test {
|
|||
let reqs = vec!["r1", "r2", "r3", "r4"];
|
||||
let confs = vec!["c1", "c2", "c3", "c4"];
|
||||
|
||||
let debug_str = format!("{{\n\
|
||||
\tname: \"test\",\n\
|
||||
\targs: {:?},\n\
|
||||
\trequired: {:?},\n\
|
||||
\trequires: {:?},\n\
|
||||
\tconflicts: {:?},\n\
|
||||
}}",
|
||||
args,
|
||||
true,
|
||||
Some(reqs),
|
||||
Some(confs));
|
||||
let debug_str = format!(
|
||||
"{{\n\
|
||||
\tname: \"test\",\n\
|
||||
\targs: {:?},\n\
|
||||
\trequired: {:?},\n\
|
||||
\trequires: {:?},\n\
|
||||
\tconflicts: {:?},\n\
|
||||
}}",
|
||||
args,
|
||||
true,
|
||||
Some(reqs),
|
||||
Some(confs)
|
||||
);
|
||||
assert_eq!(&*format!("{:?}", g), &*debug_str);
|
||||
}
|
||||
|
||||
|
@ -589,10 +591,9 @@ mod test {
|
|||
assert_eq!(g2.conflicts, Some(confs));
|
||||
}
|
||||
|
||||
#[cfg(feature="yaml")]
|
||||
#[cfg(feature = "yaml")]
|
||||
#[cfg_attr(feature = "yaml", test)]
|
||||
fn test_yaml() {
|
||||
|
||||
let g_yaml = "name: test
|
||||
args:
|
||||
- a1
|
||||
|
|
|
@ -4,10 +4,8 @@ use std::ffi::OsString;
|
|||
#[doc(hidden)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MatchedArg {
|
||||
#[doc(hidden)]
|
||||
pub occurs: u64,
|
||||
#[doc(hidden)]
|
||||
pub vals: Vec<OsString>,
|
||||
#[doc(hidden)] pub occurs: u64,
|
||||
#[doc(hidden)] pub vals: Vec<OsString>,
|
||||
}
|
||||
|
||||
impl Default for MatchedArg {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
pub use self::any_arg::{AnyArg, DispOrder};
|
||||
pub use self::arg::Arg;
|
||||
pub use self::arg_builder::{Base, Switched, Valued, FlagBuilder, OptBuilder, PosBuilder};
|
||||
pub use self::arg_builder::{Base, FlagBuilder, OptBuilder, PosBuilder, Switched, Valued};
|
||||
pub use self::arg_matcher::ArgMatcher;
|
||||
pub use self::arg_matches::{Values, OsValues, ArgMatches};
|
||||
pub use self::arg_matches::{ArgMatches, OsValues, Values};
|
||||
pub use self::group::ArgGroup;
|
||||
pub use self::matched_arg::MatchedArg;
|
||||
pub use self::settings::{ArgFlags, ArgSettings};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// Std
|
||||
#[allow(unused_imports)]
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::str::FromStr;
|
||||
|
||||
bitflags! {
|
||||
struct Flags: u16 {
|
||||
struct Flags: u32 {
|
||||
const REQUIRED = 1;
|
||||
const MULTIPLE = 1 << 1;
|
||||
const EMPTY_VALS = 1 << 2;
|
||||
|
@ -21,6 +21,7 @@ bitflags! {
|
|||
const REQUIRE_EQUALS = 1 << 13;
|
||||
const LAST = 1 << 14;
|
||||
const HIDE_DEFAULT_VAL = 1 << 15;
|
||||
const CASE_INSENSITIVE = 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +48,7 @@ impl ArgFlags {
|
|||
AllowLeadingHyphen => Flags::ALLOW_TAC_VALS,
|
||||
RequireEquals => Flags::REQUIRE_EQUALS,
|
||||
Last => Flags::LAST,
|
||||
CaseInsensitive => Flags::CASE_INSENSITIVE,
|
||||
HideDefaultValue => Flags::HIDE_DEFAULT_VAL
|
||||
}
|
||||
}
|
||||
|
@ -92,10 +94,10 @@ pub enum ArgSettings {
|
|||
Last,
|
||||
/// Hides the default value from the help string
|
||||
HideDefaultValue,
|
||||
#[doc(hidden)]
|
||||
RequiredUnlessAll,
|
||||
#[doc(hidden)]
|
||||
ValueDelimiterNotSet,
|
||||
/// Makes `Arg::possible_values` case insensitive
|
||||
CaseInsensitive,
|
||||
#[doc(hidden)] RequiredUnlessAll,
|
||||
#[doc(hidden)] ValueDelimiterNotSet,
|
||||
}
|
||||
|
||||
impl FromStr for ArgSettings {
|
||||
|
@ -118,6 +120,7 @@ impl FromStr for ArgSettings {
|
|||
"requireequals" => Ok(ArgSettings::RequireEquals),
|
||||
"last" => Ok(ArgSettings::Last),
|
||||
"hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue),
|
||||
"caseinsensitive" => Ok(ArgSettings::CaseInsensitive),
|
||||
_ => Err("unknown ArgSetting, cannot convert from str".to_owned()),
|
||||
}
|
||||
}
|
||||
|
@ -129,38 +132,71 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn arg_settings_fromstr() {
|
||||
assert_eq!("allowleadinghyphen".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::AllowLeadingHyphen);
|
||||
assert_eq!("emptyvalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::EmptyValues);
|
||||
assert_eq!("global".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Global);
|
||||
assert_eq!("hidepossiblevalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HidePossibleValues);
|
||||
assert_eq!("hidden".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Hidden);
|
||||
assert_eq!("multiple".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Multiple);
|
||||
assert_eq!("nextlinehelp".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::NextLineHelp);
|
||||
assert_eq!("requiredunlessall".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequiredUnlessAll);
|
||||
assert_eq!("requiredelimiter".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequireDelimiter);
|
||||
assert_eq!("required".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Required);
|
||||
assert_eq!("takesvalue".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::TakesValue);
|
||||
assert_eq!("usevaluedelimiter".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::UseValueDelimiter);
|
||||
assert_eq!("valuedelimiternotset".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::ValueDelimiterNotSet);
|
||||
assert_eq!("requireequals".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequireEquals);
|
||||
assert_eq!("last".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Last);
|
||||
assert_eq!("hidedefaultvalue".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HideDefaultValue);
|
||||
assert_eq!(
|
||||
"allowleadinghyphen".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::AllowLeadingHyphen
|
||||
);
|
||||
assert_eq!(
|
||||
"emptyvalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::EmptyValues
|
||||
);
|
||||
assert_eq!(
|
||||
"global".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Global
|
||||
);
|
||||
assert_eq!(
|
||||
"hidepossiblevalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HidePossibleValues
|
||||
);
|
||||
assert_eq!(
|
||||
"hidden".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Hidden
|
||||
);
|
||||
assert_eq!(
|
||||
"multiple".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Multiple
|
||||
);
|
||||
assert_eq!(
|
||||
"nextlinehelp".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::NextLineHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"requiredunlessall".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequiredUnlessAll
|
||||
);
|
||||
assert_eq!(
|
||||
"requiredelimiter".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequireDelimiter
|
||||
);
|
||||
assert_eq!(
|
||||
"required".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Required
|
||||
);
|
||||
assert_eq!(
|
||||
"takesvalue".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::TakesValue
|
||||
);
|
||||
assert_eq!(
|
||||
"usevaluedelimiter".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::UseValueDelimiter
|
||||
);
|
||||
assert_eq!(
|
||||
"valuedelimiternotset".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::ValueDelimiterNotSet
|
||||
);
|
||||
assert_eq!(
|
||||
"requireequals".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequireEquals
|
||||
);
|
||||
assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
|
||||
assert_eq!(
|
||||
"hidedefaultvalue".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HideDefaultValue
|
||||
);
|
||||
assert_eq!(
|
||||
"caseinsensitive".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::CaseInsensitive
|
||||
);
|
||||
assert!("hahahaha".parse::<ArgSettings>().is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,8 @@ use ArgMatches;
|
|||
/// [arguments]: ./struct.Arg.html
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubCommand<'a> {
|
||||
#[doc(hidden)]
|
||||
pub name: String,
|
||||
#[doc(hidden)]
|
||||
pub matches: ArgMatches<'a>,
|
||||
#[doc(hidden)] pub name: String,
|
||||
#[doc(hidden)] pub matches: ArgMatches<'a>,
|
||||
}
|
||||
|
||||
impl<'a> SubCommand<'a> {
|
||||
|
|
|
@ -7,7 +7,8 @@ use args::{ArgSettings, OptBuilder};
|
|||
use completions;
|
||||
|
||||
pub struct BashGen<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
@ -16,9 +17,10 @@ impl<'a, 'b> BashGen<'a, 'b> {
|
|||
pub fn new(p: &'b Parser<'a, 'b>) -> Self { BashGen { p: p } }
|
||||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
|
||||
w!(buf,
|
||||
format!("_{name}() {{
|
||||
w!(
|
||||
buf,
|
||||
format!(
|
||||
"_{name}() {{
|
||||
local i cur prev opts cmds
|
||||
COMPREPLY=()
|
||||
cur=\"${{COMP_WORDS[COMP_CWORD]}}\"
|
||||
|
@ -60,13 +62,14 @@ impl<'a, 'b> BashGen<'a, 'b> {
|
|||
|
||||
complete -F _{name} -o bashdefault -o default {name}
|
||||
",
|
||||
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||
name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||
name_opts_details =
|
||||
self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||
subcmds = self.all_subcommands(),
|
||||
subcmd_details = self.subcommand_details())
|
||||
.as_bytes());
|
||||
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||
name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||
name_opts_details =
|
||||
self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||
subcmds = self.all_subcommands(),
|
||||
subcmd_details = self.subcommand_details()
|
||||
).as_bytes()
|
||||
);
|
||||
}
|
||||
|
||||
fn all_subcommands(&self) -> String {
|
||||
|
@ -75,12 +78,14 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
let scs = completions::all_subcommand_names(self.p);
|
||||
|
||||
for sc in &scs {
|
||||
subcmds = format!("{}
|
||||
subcmds = format!(
|
||||
"{}
|
||||
{name})
|
||||
cmd+=\"__{name}\"
|
||||
;;",
|
||||
subcmds,
|
||||
name = sc.replace("-", "__"));
|
||||
subcmds,
|
||||
name = sc.replace("-", "__")
|
||||
);
|
||||
}
|
||||
|
||||
subcmds
|
||||
|
@ -94,7 +99,8 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
scs.dedup();
|
||||
|
||||
for sc in &scs {
|
||||
subcmd_dets = format!("{}
|
||||
subcmd_dets = format!(
|
||||
"{}
|
||||
{subcmd})
|
||||
opts=\"{sc_opts}\"
|
||||
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then
|
||||
|
@ -110,11 +116,12 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
|
||||
return 0
|
||||
;;",
|
||||
subcmd_dets,
|
||||
subcmd = sc.replace("-", "__"),
|
||||
sc_opts = self.all_options_for_path(&*sc),
|
||||
level = sc.split("__").map(|_| 1).fold(0, |acc, n| acc + n),
|
||||
opts_details = self.option_details_for_path(&*sc));
|
||||
subcmd_dets,
|
||||
subcmd = sc.replace("-", "__"),
|
||||
sc_opts = self.all_options_for_path(&*sc),
|
||||
level = sc.split("__").map(|_| 1).fold(0, |acc, n| acc + n),
|
||||
opts_details = self.option_details_for_path(&*sc)
|
||||
);
|
||||
}
|
||||
|
||||
subcmd_dets
|
||||
|
@ -130,24 +137,28 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
let mut opts = String::new();
|
||||
for o in p.opts() {
|
||||
if let Some(l) = o.s.long {
|
||||
opts = format!("{}
|
||||
opts = format!(
|
||||
"{}
|
||||
--{})
|
||||
COMPREPLY=({})
|
||||
return 0
|
||||
;;",
|
||||
opts,
|
||||
l,
|
||||
self.vals_for(o));
|
||||
opts,
|
||||
l,
|
||||
self.vals_for(o)
|
||||
);
|
||||
}
|
||||
if let Some(s) = o.s.short {
|
||||
opts = format!("{}
|
||||
opts = format!(
|
||||
"{}
|
||||
-{})
|
||||
COMPREPLY=({})
|
||||
return 0
|
||||
;;",
|
||||
opts,
|
||||
s,
|
||||
self.vals_for(o));
|
||||
opts,
|
||||
s,
|
||||
self.vals_for(o)
|
||||
);
|
||||
}
|
||||
}
|
||||
opts
|
||||
|
@ -164,10 +175,12 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
} else if let Some(vec) = o.val_names() {
|
||||
let mut it = vec.iter().peekable();
|
||||
while let Some((_, val)) = it.next() {
|
||||
ret = format!("{}<{}>{}",
|
||||
ret,
|
||||
val,
|
||||
if it.peek().is_some() { " " } else { "" });
|
||||
ret = format!(
|
||||
"{}<{}>{}",
|
||||
ret,
|
||||
val,
|
||||
if it.peek().is_some() { " " } else { "" }
|
||||
);
|
||||
}
|
||||
let num = vec.len();
|
||||
if o.is_set(ArgSettings::Multiple) && num == 1 {
|
||||
|
@ -176,10 +189,12 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
} else if let Some(num) = o.num_vals() {
|
||||
let mut it = (0..num).peekable();
|
||||
while let Some(_) = it.next() {
|
||||
ret = format!("{}<{}>{}",
|
||||
ret,
|
||||
o.name(),
|
||||
if it.peek().is_some() { " " } else { "" });
|
||||
ret = format!(
|
||||
"{}<{}>{}",
|
||||
ret,
|
||||
o.name(),
|
||||
if it.peek().is_some() { " " } else { "" }
|
||||
);
|
||||
}
|
||||
if o.is_set(ArgSettings::Multiple) && num == 1 {
|
||||
ret = format!("{}...", ret);
|
||||
|
@ -203,26 +218,35 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
p = &find_subcmd!(p, sc).unwrap().p;
|
||||
}
|
||||
let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s));
|
||||
opts = format!("{} {}",
|
||||
opts,
|
||||
longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
|
||||
opts = format!("{} {}",
|
||||
opts,
|
||||
p.positionals
|
||||
.values()
|
||||
.fold(String::new(), |acc, p| format!("{} {}", acc, p)));
|
||||
opts = format!("{} {}",
|
||||
opts,
|
||||
p.subcommands
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name)));
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l))
|
||||
);
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
p.positionals
|
||||
.values()
|
||||
.fold(String::new(), |acc, p| format!("{} {}", acc, p))
|
||||
);
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
p.subcommands
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name))
|
||||
);
|
||||
for sc in &p.subcommands {
|
||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||
opts = format!("{} {}",
|
||||
opts,
|
||||
aliases.iter()
|
||||
.map(|&(n, _)| n)
|
||||
.fold(String::new(), |acc, a| format!("{} {}", acc, a)));
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
aliases
|
||||
.iter()
|
||||
.map(|&(n, _)| n)
|
||||
.fold(String::new(), |acc, a| format!("{} {}", acc, a))
|
||||
);
|
||||
}
|
||||
}
|
||||
opts
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
|
@ -6,7 +5,8 @@ use std::io::Write;
|
|||
use app::parser::Parser;
|
||||
|
||||
pub struct FishGen<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
@ -31,8 +31,7 @@ impl<'a, 'b> FishGen<'a, 'b> {
|
|||
return 1
|
||||
end
|
||||
|
||||
"#
|
||||
.to_string();
|
||||
"#.to_string();
|
||||
|
||||
let mut buffer = detect_subcommand_function;
|
||||
gen_fish_inner(command, self, &command.to_string(), &mut buffer);
|
||||
|
@ -41,9 +40,7 @@ end
|
|||
}
|
||||
|
||||
// Escape string inside single quotes
|
||||
fn escape_string(string: &str) -> String {
|
||||
string.replace("\\", "\\\\").replace("'", "\\'")
|
||||
}
|
||||
fn escape_string(string: &str) -> String { string.replace("\\", "\\\\").replace("'", "\\'") }
|
||||
|
||||
fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buffer: &mut String) {
|
||||
debugln!("FishGen::gen_fish_inner;");
|
||||
|
@ -59,9 +56,11 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buf
|
|||
// -f # don't use file completion
|
||||
// -n "__fish_using_command myprog subcmd1" # complete for command "myprog subcmd1"
|
||||
|
||||
let basic_template = format!("complete -c {} -n \"__fish_using_command {}\"",
|
||||
root_command,
|
||||
parent_cmds);
|
||||
let basic_template = format!(
|
||||
"complete -c {} -n \"__fish_using_command {}\"",
|
||||
root_command,
|
||||
parent_cmds
|
||||
);
|
||||
|
||||
for option in comp_gen.p.opts() {
|
||||
let mut template = basic_template.clone();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
macro_rules! w {
|
||||
($buf:expr, $to_w:expr) => {
|
||||
match $buf.write_all($to_w) {
|
||||
|
@ -20,7 +19,7 @@ macro_rules! get_zsh_arg_conflicts {
|
|||
if let Some(l) = arg.long() {
|
||||
v.push(format!("--{}", l));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.join(" ")
|
||||
} else {
|
||||
String::new()
|
||||
|
|
|
@ -18,7 +18,8 @@ use self::powershell::PowerShellGen;
|
|||
pub use self::shell::Shell;
|
||||
|
||||
pub struct ComplGen<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
@ -44,7 +45,10 @@ impl<'a, 'b> ComplGen<'a, 'b> {
|
|||
// aliasing.
|
||||
pub fn all_subcommand_names(p: &Parser) -> Vec<String> {
|
||||
debugln!("all_subcommand_names;");
|
||||
let mut subcmds: Vec<_> = subcommands_of(p).iter().map(|&(ref n, _)| n.clone()).collect();
|
||||
let mut subcmds: Vec<_> = subcommands_of(p)
|
||||
.iter()
|
||||
.map(|&(ref n, _)| n.clone())
|
||||
.collect();
|
||||
for sc_v in p.subcommands.iter().map(|s| all_subcommand_names(&s.p)) {
|
||||
subcmds.extend(sc_v);
|
||||
}
|
||||
|
@ -75,14 +79,24 @@ pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> {
|
|||
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
|
||||
// aliasing.
|
||||
pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
|
||||
debugln!("subcommands_of: name={}, bin_name={}",
|
||||
p.meta.name,
|
||||
p.meta.bin_name.as_ref().unwrap());
|
||||
debugln!(
|
||||
"subcommands_of: name={}, bin_name={}",
|
||||
p.meta.name,
|
||||
p.meta.bin_name.as_ref().unwrap()
|
||||
);
|
||||
let mut subcmds = vec![];
|
||||
|
||||
debugln!("subcommands_of: Has subcommands...{:?}", p.has_subcommands());
|
||||
debugln!(
|
||||
"subcommands_of: Has subcommands...{:?}",
|
||||
p.has_subcommands()
|
||||
);
|
||||
if !p.has_subcommands() {
|
||||
let mut ret = vec![(p.meta.name.clone(), p.meta.bin_name.as_ref().unwrap().clone())];
|
||||
let mut ret = vec![
|
||||
(
|
||||
p.meta.name.clone(),
|
||||
p.meta.bin_name.as_ref().unwrap().clone(),
|
||||
),
|
||||
];
|
||||
debugln!("subcommands_of: Looking for aliases...");
|
||||
if let Some(ref aliases) = p.meta.aliases {
|
||||
for &(n, _) in aliases {
|
||||
|
@ -98,9 +112,11 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
|
|||
return ret;
|
||||
}
|
||||
for sc in &p.subcommands {
|
||||
debugln!("subcommands_of:iter: name={}, bin_name={}",
|
||||
sc.p.meta.name,
|
||||
sc.p.meta.bin_name.as_ref().unwrap());
|
||||
debugln!(
|
||||
"subcommands_of:iter: name={}, bin_name={}",
|
||||
sc.p.meta.name,
|
||||
sc.p.meta.bin_name.as_ref().unwrap()
|
||||
);
|
||||
|
||||
debugln!("subcommands_of:iter: Looking for aliases...");
|
||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||
|
@ -114,7 +130,10 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
|
|||
subcmds.push((n.to_owned(), als_bin_name.join(" ")));
|
||||
}
|
||||
}
|
||||
subcmds.push((sc.p.meta.name.clone(), sc.p.meta.bin_name.as_ref().unwrap().clone()));
|
||||
subcmds.push((
|
||||
sc.p.meta.name.clone(),
|
||||
sc.p.meta.bin_name.as_ref().unwrap().clone(),
|
||||
));
|
||||
}
|
||||
subcmds
|
||||
}
|
||||
|
@ -138,7 +157,13 @@ pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String> {
|
|||
}
|
||||
for sc in &p.subcommands {
|
||||
let name = &*sc.p.meta.name;
|
||||
let path = sc.p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__");
|
||||
let path = sc.p
|
||||
.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.replace(" ", "__");
|
||||
subcmds.push(path.clone());
|
||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||
for &(n, _) in aliases {
|
||||
|
@ -146,7 +171,10 @@ pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String> {
|
|||
}
|
||||
}
|
||||
}
|
||||
for sc_v in p.subcommands.iter().map(|s| get_all_subcommand_paths(&s.p, false)) {
|
||||
for sc_v in p.subcommands
|
||||
.iter()
|
||||
.map(|s| get_all_subcommand_paths(&s.p, false))
|
||||
{
|
||||
subcmds.extend(sc_v);
|
||||
}
|
||||
subcmds
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
|
@ -7,7 +6,8 @@ use app::parser::Parser;
|
|||
use INTERNAL_ERROR_MSG;
|
||||
|
||||
pub struct PowerShellGen<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
|
|||
let bin_name = self.p.meta.bin_name.as_ref().unwrap();
|
||||
|
||||
let mut names = vec![];
|
||||
let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, "", &mut names);
|
||||
let (subcommands_detection_cases, subcommands_cases) =
|
||||
generate_inner(self.p, "", &mut names);
|
||||
|
||||
let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)];
|
||||
if cfg!(windows) {
|
||||
|
@ -74,23 +75,33 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_inner<'a, 'b, 'p>(p: &'p Parser<'a, 'b>, previous_command_name: &str, names: &mut Vec<&'p str>) -> (String, String) {
|
||||
fn generate_inner<'a, 'b, 'p>(
|
||||
p: &'p Parser<'a, 'b>,
|
||||
previous_command_name: &str,
|
||||
names: &mut Vec<&'p str>,
|
||||
) -> (String, String) {
|
||||
debugln!("PowerShellGen::generate_inner;");
|
||||
let command_name = if previous_command_name.is_empty() {
|
||||
format!("{}_{}", previous_command_name, &p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG))
|
||||
format!(
|
||||
"{}_{}",
|
||||
previous_command_name,
|
||||
&p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG)
|
||||
)
|
||||
} else {
|
||||
format!("{}_{}", previous_command_name, &p.meta.name)
|
||||
};
|
||||
|
||||
let mut subcommands_detection_cases = if !names.contains(&&*p.meta.name) {
|
||||
names.push(&*p.meta.name);
|
||||
format!(r"
|
||||
format!(
|
||||
r"
|
||||
'{0}' {{
|
||||
$command += '_{0}'
|
||||
break
|
||||
}}
|
||||
",
|
||||
&p.meta.name)
|
||||
&p.meta.name
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
@ -106,13 +117,15 @@ fn generate_inner<'a, 'b, 'p>(p: &'p Parser<'a, 'b>, previous_command_name: &str
|
|||
completions.push_str(&format!("'--{}', ", long));
|
||||
}
|
||||
|
||||
let mut subcommands_cases = format!(r"
|
||||
let mut subcommands_cases = format!(
|
||||
r"
|
||||
'{}' {{
|
||||
$completions = @({})
|
||||
}}
|
||||
",
|
||||
&command_name,
|
||||
completions.trim_right_matches(", "));
|
||||
&command_name,
|
||||
completions.trim_right_matches(", ")
|
||||
);
|
||||
|
||||
for subcommand in &p.subcommands {
|
||||
let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#[allow(unused_imports)]
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::str::FromStr;
|
||||
use std::fmt;
|
||||
|
@ -27,7 +27,6 @@ impl FromStr for Shell {
|
|||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
|
||||
"ZSH" | _ if s.eq_ignore_ascii_case("zsh") => Ok(Shell::Zsh),
|
||||
"FISH" | _ if s.eq_ignore_ascii_case("fish") => Ok(Shell::Fish),
|
||||
"BASH" | _ if s.eq_ignore_ascii_case("bash") => Ok(Shell::Bash),
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
// Std
|
||||
use std::io::Write;
|
||||
#[allow(unused_imports)]
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
// Internal
|
||||
use app::App;
|
||||
use app::parser::Parser;
|
||||
use args::{ArgSettings, AnyArg};
|
||||
use args::{AnyArg, ArgSettings};
|
||||
use completions;
|
||||
use INTERNAL_ERROR_MSG;
|
||||
|
||||
pub struct ZshGen<'a, 'b>
|
||||
where 'a: 'b
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
@ -25,8 +25,10 @@ impl<'a, 'b> ZshGen<'a, 'b> {
|
|||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
debugln!("ZshGen::generate_to;");
|
||||
w!(buf,
|
||||
format!("\
|
||||
w!(
|
||||
buf,
|
||||
format!(
|
||||
"\
|
||||
#compdef {name}
|
||||
|
||||
_{name}() {{
|
||||
|
@ -41,11 +43,12 @@ _{name}() {{
|
|||
{subcommand_details}
|
||||
|
||||
_{name} \"$@\"",
|
||||
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||
initial_args = get_args_of(self.p),
|
||||
subcommands = get_subcommands_of(self.p),
|
||||
subcommand_details = subcommand_details(self.p)).as_bytes());
|
||||
|
||||
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||
initial_args = get_args_of(self.p),
|
||||
subcommands = get_subcommands_of(self.p),
|
||||
subcommand_details = subcommand_details(self.p)
|
||||
).as_bytes()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +82,9 @@ _{name} \"$@\"",
|
|||
fn subcommand_details(p: &Parser) -> String {
|
||||
debugln!("ZshGen::subcommand_details;");
|
||||
// First we do ourself
|
||||
let mut ret = vec![format!("\
|
||||
let mut ret = vec![
|
||||
format!(
|
||||
"\
|
||||
(( $+functions[_{bin_name_underscore}_commands] )) ||
|
||||
_{bin_name_underscore}_commands() {{
|
||||
local commands; commands=(
|
||||
|
@ -89,7 +94,9 @@ _{bin_name_underscore}_commands() {{
|
|||
}}",
|
||||
bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"),
|
||||
bin_name = p.meta.bin_name.as_ref().unwrap(),
|
||||
subcommands_and_args = subcommands_and_args_of(p))];
|
||||
subcommands_and_args = subcommands_and_args_of(p)
|
||||
),
|
||||
];
|
||||
|
||||
// Next we start looping through all the children, grandchildren, etc.
|
||||
let mut all_subcommands = completions::all_subcommands(p);
|
||||
|
@ -97,7 +104,8 @@ _{bin_name_underscore}_commands() {{
|
|||
all_subcommands.dedup();
|
||||
for &(_, ref bin_name) in &all_subcommands {
|
||||
debugln!("ZshGen::subcommand_details:iter: bin_name={}", bin_name);
|
||||
ret.push(format!("\
|
||||
ret.push(format!(
|
||||
"\
|
||||
(( $+functions[_{bin_name_underscore}_commands] )) ||
|
||||
_{bin_name_underscore}_commands() {{
|
||||
local commands; commands=(
|
||||
|
@ -107,7 +115,8 @@ _{bin_name_underscore}_commands() {{
|
|||
}}",
|
||||
bin_name_underscore = bin_name.replace(" ", "__"),
|
||||
bin_name = bin_name,
|
||||
subcommands_and_args = subcommands_and_args_of(parser_of(p, bin_name))));
|
||||
subcommands_and_args = subcommands_and_args_of(parser_of(p, bin_name))
|
||||
));
|
||||
}
|
||||
|
||||
ret.join("\n")
|
||||
|
@ -129,9 +138,16 @@ fn subcommands_and_args_of(p: &Parser) -> String {
|
|||
let mut ret = vec![];
|
||||
fn add_sc(sc: &App, n: &str, ret: &mut Vec<String>) {
|
||||
debugln!("ZshGen::add_sc;");
|
||||
let s = format!("\"{name}:{help}\" \\",
|
||||
name = n,
|
||||
help = sc.p.meta.about.unwrap_or("").replace("[", "\\[").replace("]", "\\]"));
|
||||
let s = format!(
|
||||
"\"{name}:{help}\" \\",
|
||||
name = n,
|
||||
help = sc.p
|
||||
.meta
|
||||
.about
|
||||
.unwrap_or("")
|
||||
.replace("[", "\\[")
|
||||
.replace("]", "\\]")
|
||||
);
|
||||
if !s.is_empty() {
|
||||
ret.push(s);
|
||||
}
|
||||
|
@ -139,7 +155,10 @@ fn subcommands_and_args_of(p: &Parser) -> String {
|
|||
|
||||
// First the subcommands
|
||||
for sc in p.subcommands() {
|
||||
debugln!("ZshGen::subcommands_and_args_of:iter: subcommand={}", sc.p.meta.name);
|
||||
debugln!(
|
||||
"ZshGen::subcommands_and_args_of:iter: subcommand={}",
|
||||
sc.p.meta.name
|
||||
);
|
||||
add_sc(sc, &sc.p.meta.name, &mut ret);
|
||||
if let Some(ref v) = sc.p.meta.aliases {
|
||||
for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n, _)| n) {
|
||||
|
@ -151,9 +170,15 @@ fn subcommands_and_args_of(p: &Parser) -> String {
|
|||
// Then the positional args
|
||||
for arg in p.positionals() {
|
||||
debugln!("ZshGen::subcommands_and_args_of:iter: arg={}", arg.b.name);
|
||||
let a = format!("\"{name}:{help}\" \\",
|
||||
name = arg.b.name.to_ascii_uppercase(),
|
||||
help = arg.b.help.unwrap_or("").replace("[", "\\[").replace("]", "\\]"));
|
||||
let a = format!(
|
||||
"\"{name}:{help}\" \\",
|
||||
name = arg.b.name.to_ascii_uppercase(),
|
||||
help = arg.b
|
||||
.help
|
||||
.unwrap_or("")
|
||||
.replace("[", "\\[")
|
||||
.replace("]", "\\]")
|
||||
);
|
||||
|
||||
if !a.is_empty() {
|
||||
ret.push(a);
|
||||
|
@ -195,7 +220,10 @@ fn subcommands_and_args_of(p: &Parser) -> String {
|
|||
fn get_subcommands_of(p: &Parser) -> String {
|
||||
debugln!("get_subcommands_of;");
|
||||
|
||||
debugln!("get_subcommands_of: Has subcommands...{:?}", p.has_subcommands());
|
||||
debugln!(
|
||||
"get_subcommands_of: Has subcommands...{:?}",
|
||||
p.has_subcommands()
|
||||
);
|
||||
if !p.has_subcommands() {
|
||||
return String::new();
|
||||
}
|
||||
|
@ -218,17 +246,18 @@ fn get_subcommands_of(p: &Parser) -> String {
|
|||
}
|
||||
|
||||
format!(
|
||||
"case $state in
|
||||
"case $state in
|
||||
({name})
|
||||
curcontext=\"${{curcontext%:*:*}}:{name_hyphen}-command-$words[1]:\"
|
||||
case $line[1] in
|
||||
{subcommands}
|
||||
esac
|
||||
;;
|
||||
esac",
|
||||
esac",
|
||||
name = p.meta.name,
|
||||
name_hyphen = p.meta.bin_name.as_ref().unwrap().replace(" ", "-"),
|
||||
subcommands = subcmds.join("\n"))
|
||||
subcommands = subcmds.join("\n")
|
||||
)
|
||||
}
|
||||
|
||||
fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> {
|
||||
|
@ -265,8 +294,10 @@ fn get_args_of(p: &Parser) -> String {
|
|||
let opts = write_opts_of(p);
|
||||
let flags = write_flags_of(p);
|
||||
let sc_or_a = if p.has_subcommands() || p.has_positionals() {
|
||||
format!("\"1:: :_{name}_commands\" \\",
|
||||
name = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"))
|
||||
format!(
|
||||
"\"1:: :_{name}_commands\" \\",
|
||||
name = p.meta.bin_name.as_ref().unwrap().replace(" ", "__")
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
@ -295,7 +326,8 @@ fn get_args_of(p: &Parser) -> String {
|
|||
|
||||
// Escape string inside single quotes and brackets
|
||||
fn escape_string(string: &str) -> String {
|
||||
string.replace("\\", "\\\\")
|
||||
string
|
||||
.replace("\\", "\\\\")
|
||||
.replace("'", "'\\''")
|
||||
.replace("[", "\\[")
|
||||
.replace("]", "\\]")
|
||||
|
@ -325,23 +357,27 @@ fn write_opts_of(p: &Parser) -> String {
|
|||
String::new()
|
||||
};
|
||||
if let Some(short) = o.short() {
|
||||
let s = format!("'{conflicts}{multiple}-{arg}+[{help}]{possible_values}' \\",
|
||||
let s = format!(
|
||||
"'{conflicts}{multiple}-{arg}+[{help}]{possible_values}' \\",
|
||||
conflicts = conflicts,
|
||||
multiple = multiple,
|
||||
arg = short,
|
||||
possible_values = pv,
|
||||
help = help);
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_opts_of:iter: Wrote...{}", &*s);
|
||||
ret.push(s);
|
||||
}
|
||||
if let Some(long) = o.long() {
|
||||
let l = format!("'{conflicts}{multiple}--{arg}+[{help}]{possible_values}' \\",
|
||||
let l = format!(
|
||||
"'{conflicts}{multiple}--{arg}+[{help}]{possible_values}' \\",
|
||||
conflicts = conflicts,
|
||||
multiple = multiple,
|
||||
arg = long,
|
||||
possible_values = pv,
|
||||
help = help);
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_opts_of:iter: Wrote...{}", &*l);
|
||||
ret.push(l);
|
||||
|
@ -370,22 +406,26 @@ fn write_flags_of(p: &Parser) -> String {
|
|||
""
|
||||
};
|
||||
if let Some(short) = f.short() {
|
||||
let s = format!("'{conflicts}{multiple}-{arg}[{help}]' \\",
|
||||
let s = format!(
|
||||
"'{conflicts}{multiple}-{arg}[{help}]' \\",
|
||||
multiple = multiple,
|
||||
conflicts = conflicts,
|
||||
arg = short,
|
||||
help = help);
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_flags_of:iter: Wrote...{}", &*s);
|
||||
ret.push(s);
|
||||
}
|
||||
|
||||
if let Some(long) = f.long() {
|
||||
let l = format!("'{conflicts}{multiple}--{arg}[{help}]' \\",
|
||||
let l = format!(
|
||||
"'{conflicts}{multiple}--{arg}[{help}]' \\",
|
||||
conflicts = conflicts,
|
||||
multiple = multiple,
|
||||
arg = long,
|
||||
help = help);
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_flags_of:iter: Wrote...{}", &*l);
|
||||
ret.push(l);
|
||||
|
|
497
src/errors.rs
497
src/errors.rs
|
@ -8,8 +8,8 @@ use std::process;
|
|||
use std::result::Result as StdResult;
|
||||
|
||||
// Internal
|
||||
use args::{FlagBuilder, AnyArg};
|
||||
use fmt::{Colorizer, ColorizerOption, ColorWhen};
|
||||
use args::{AnyArg, FlagBuilder};
|
||||
use fmt::{ColorWhen, Colorizer, ColorizerOption};
|
||||
use suggestions;
|
||||
|
||||
/// Short hand for [`Result`] type
|
||||
|
@ -58,8 +58,8 @@ pub enum ErrorKind {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(feature="suggestions"), doc=" ```no_run")]
|
||||
#[cfg_attr( feature="suggestions" , doc=" ```")]
|
||||
#[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")]
|
||||
#[cfg_attr(feature = "suggestions", doc = " ```")]
|
||||
/// # use clap::{App, Arg, ErrorKind, SubCommand};
|
||||
/// let result = App::new("prog")
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
|
@ -300,8 +300,8 @@ pub enum ErrorKind {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc=" ```ignore")]
|
||||
#[cfg_attr( unix , doc=" ```")]
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg, ErrorKind, AppSettings};
|
||||
/// # use std::os::unix::ffi::OsStringExt;
|
||||
/// # use std::ffi::OsString;
|
||||
|
@ -384,8 +384,7 @@ impl Error {
|
|||
/// Should the message be written to `stdout` or not
|
||||
pub fn use_stderr(&self) -> bool {
|
||||
match self.kind {
|
||||
ErrorKind::HelpDisplayed |
|
||||
ErrorKind::VersionDisplayed => false,
|
||||
ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
@ -405,14 +404,16 @@ impl Error {
|
|||
pub fn write_to<W: Write>(&self, w: &mut W) -> io::Result<()> { write!(w, "{}", self.message) }
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn argument_conflict<'a, 'b, A, O, U>(arg: &A,
|
||||
other: Option<O>,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where A: AnyArg<'a, 'b> + Display,
|
||||
O: Into<String>,
|
||||
U: Display
|
||||
pub fn argument_conflict<'a, 'b, A, O, U>(
|
||||
arg: &A,
|
||||
other: Option<O>,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
O: Into<String>,
|
||||
U: Display,
|
||||
{
|
||||
let mut v = vec![arg.name().to_owned()];
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
|
@ -420,24 +421,23 @@ impl Error {
|
|||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' cannot be used with {}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*arg.to_string()),
|
||||
match other {
|
||||
Some(name) => {
|
||||
let n = name.into();
|
||||
v.push(n.clone());
|
||||
c.warning(format!("'{}'", n))
|
||||
}
|
||||
None => {
|
||||
c.none("one or more of the other specified arguments"
|
||||
.to_owned())
|
||||
}
|
||||
},
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The argument '{}' cannot be used with {}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*arg.to_string()),
|
||||
match other {
|
||||
Some(name) => {
|
||||
let n = name.into();
|
||||
v.push(n.clone());
|
||||
c.warning(format!("'{}'", n))
|
||||
}
|
||||
None => c.none("one or more of the other specified arguments".to_owned()),
|
||||
},
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::ArgumentConflict,
|
||||
info: Some(v),
|
||||
}
|
||||
|
@ -445,47 +445,49 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self
|
||||
where A: AnyArg<'a, 'b> + Display,
|
||||
U: Display
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' requires a value but none was supplied\
|
||||
\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The argument '{}' requires a value but none was supplied\
|
||||
\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::EmptyValue,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn invalid_value<'a, 'b, B, G, A, U>(bad_val: B,
|
||||
good_vals: &[G],
|
||||
arg: &A,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where B: AsRef<str>,
|
||||
G: AsRef<str> + Display,
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display
|
||||
pub fn invalid_value<'a, 'b, B, G, A, U>(
|
||||
bad_val: B,
|
||||
good_vals: &[G],
|
||||
arg: &A,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
B: AsRef<str>,
|
||||
G: AsRef<str> + Display,
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
let suffix =
|
||||
suggestions::did_you_mean_value_suffix(
|
||||
bad_val.as_ref(),
|
||||
good_vals.iter());
|
||||
let suffix = suggestions::did_you_mean_value_suffix(bad_val.as_ref(), good_vals.iter());
|
||||
|
||||
let mut sorted = vec![];
|
||||
for v in good_vals {
|
||||
|
@ -495,34 +497,38 @@ impl Error {
|
|||
sorted.sort();
|
||||
let valid_values = sorted.join(", ");
|
||||
Error {
|
||||
message: format!("{} '{}' isn't a valid value for '{}'\n\t\
|
||||
[values: {}]\n\
|
||||
{}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(bad_val.as_ref()),
|
||||
c.warning(arg.to_string()),
|
||||
valid_values,
|
||||
suffix.0,
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} '{}' isn't a valid value for '{}'\n\t\
|
||||
[values: {}]\n\
|
||||
{}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(bad_val.as_ref()),
|
||||
c.warning(arg.to_string()),
|
||||
valid_values,
|
||||
suffix.0,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::InvalidValue,
|
||||
info: Some(vec![arg.name().to_owned(), bad_val.as_ref().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn invalid_subcommand<S, D, N, U>(subcmd: S,
|
||||
did_you_mean: D,
|
||||
name: N,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where S: Into<String>,
|
||||
D: AsRef<str> + Display,
|
||||
N: Display,
|
||||
U: Display
|
||||
pub fn invalid_subcommand<S, D, N, U>(
|
||||
subcmd: S,
|
||||
did_you_mean: D,
|
||||
name: N,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
D: AsRef<str> + Display,
|
||||
N: Display,
|
||||
U: Display,
|
||||
{
|
||||
let s = subcmd.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
|
@ -530,20 +536,22 @@ impl Error {
|
|||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The subcommand '{}' wasn't recognized\n\t\
|
||||
Did you mean '{}'?\n\n\
|
||||
If you believe you received this message in error, try \
|
||||
re-running with '{} {} {}'\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*s),
|
||||
c.good(did_you_mean.as_ref()),
|
||||
name,
|
||||
c.good("--"),
|
||||
&*s,
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The subcommand '{}' wasn't recognized\n\t\
|
||||
Did you mean '{}'?\n\n\
|
||||
If you believe you received this message in error, try \
|
||||
re-running with '{} {} {}'\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*s),
|
||||
c.good(did_you_mean.as_ref()),
|
||||
name,
|
||||
c.good("--"),
|
||||
&*s,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::InvalidSubcommand,
|
||||
info: Some(vec![s]),
|
||||
}
|
||||
|
@ -551,8 +559,9 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self
|
||||
where S: Into<String>,
|
||||
N: Display
|
||||
where
|
||||
S: Into<String>,
|
||||
N: Display,
|
||||
{
|
||||
let s = subcmd.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
|
@ -560,15 +569,17 @@ impl Error {
|
|||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The subcommand '{}' wasn't recognized\n\n\
|
||||
{}\n\t\
|
||||
{} help <subcommands>...\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*s),
|
||||
c.warning("USAGE:"),
|
||||
name,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The subcommand '{}' wasn't recognized\n\n\
|
||||
{}\n\t\
|
||||
{} help <subcommands>...\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*s),
|
||||
c.warning("USAGE:"),
|
||||
name,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::UnrecognizedSubcommand,
|
||||
info: Some(vec![s]),
|
||||
}
|
||||
|
@ -576,21 +587,24 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self
|
||||
where R: Display,
|
||||
U: Display
|
||||
where
|
||||
R: Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The following required arguments were not provided:{}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
required,
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The following required arguments were not provided:{}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
required,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::MissingRequiredArgument,
|
||||
info: None,
|
||||
}
|
||||
|
@ -598,21 +612,24 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self
|
||||
where N: AsRef<str> + Display,
|
||||
U: Display
|
||||
where
|
||||
N: AsRef<str> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} '{}' requires a subcommand, but one was not provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(name),
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} '{}' requires a subcommand, but one was not provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(name),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::MissingSubcommand,
|
||||
info: None,
|
||||
}
|
||||
|
@ -621,33 +638,33 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn invalid_utf8<U>(usage: U, color: ColorWhen) -> Self
|
||||
where U: Display
|
||||
where
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} Invalid UTF-8 was detected in one or more arguments\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} Invalid UTF-8 was detected in one or more arguments\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::InvalidUtf8,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn too_many_values<'a, 'b, V, A, U>(val: V,
|
||||
arg: &A,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where V: AsRef<str> + Display + ToOwned,
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display
|
||||
pub fn too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
V: AsRef<str> + Display + ToOwned,
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let v = val.as_ref();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
|
@ -655,46 +672,52 @@ impl Error {
|
|||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The value '{}' was provided to '{}', but it wasn't expecting \
|
||||
any more values\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(v),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The value '{}' was provided to '{}', but it wasn't expecting \
|
||||
any more values\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(v),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::TooManyValues,
|
||||
info: Some(vec![arg.name().to_owned(), v.to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn too_few_values<'a, 'b, A, U>(arg: &A,
|
||||
min_vals: u64,
|
||||
curr_vals: usize,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where A: AnyArg<'a, 'b> + Display,
|
||||
U: Display
|
||||
pub fn too_few_values<'a, 'b, A, U>(
|
||||
arg: &A,
|
||||
min_vals: u64,
|
||||
curr_vals: usize,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' requires at least {} values, but only {} w{} \
|
||||
provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
c.warning(min_vals.to_string()),
|
||||
c.warning(curr_vals.to_string()),
|
||||
if curr_vals > 1 { "ere" } else { "as" },
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The argument '{}' requires at least {} values, but only {} w{} \
|
||||
provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
c.warning(min_vals.to_string()),
|
||||
c.warning(curr_vals.to_string()),
|
||||
if curr_vals > 1 { "ere" } else { "as" },
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::TooFewValues,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
|
@ -702,21 +725,24 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: ColorWhen) -> Self
|
||||
where A: AnyArg<'a, 'b> + Display
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} Invalid value{}: {}",
|
||||
c.error("error:"),
|
||||
if let Some(a) = arg {
|
||||
format!(" for '{}'", c.warning(a.to_string()))
|
||||
} else {
|
||||
"".to_string()
|
||||
},
|
||||
err),
|
||||
message: format!(
|
||||
"{} Invalid value{}: {}",
|
||||
c.error("error:"),
|
||||
if let Some(a) = arg {
|
||||
format!(" for '{}'", c.warning(a.to_string()))
|
||||
} else {
|
||||
"".to_string()
|
||||
},
|
||||
err
|
||||
),
|
||||
kind: ErrorKind::ValueValidation,
|
||||
info: None,
|
||||
}
|
||||
|
@ -724,38 +750,42 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn value_validation_auto(err: String) -> Self {
|
||||
let n: Option<&FlagBuilder> = None;
|
||||
let n: Option<&FlagBuilder> = None;
|
||||
Error::value_validation(n, err, ColorWhen::Auto)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn wrong_number_of_values<'a, 'b, A, S, U>(arg: &A,
|
||||
num_vals: u64,
|
||||
curr_vals: usize,
|
||||
suffix: S,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where A: AnyArg<'a, 'b> + Display,
|
||||
S: Display,
|
||||
U: Display
|
||||
pub fn wrong_number_of_values<'a, 'b, A, S, U>(
|
||||
arg: &A,
|
||||
num_vals: u64,
|
||||
curr_vals: usize,
|
||||
suffix: S,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
S: Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' requires {} values, but {} w{} \
|
||||
provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
c.warning(num_vals.to_string()),
|
||||
c.warning(curr_vals.to_string()),
|
||||
suffix,
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The argument '{}' requires {} values, but {} w{} \
|
||||
provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
c.warning(num_vals.to_string()),
|
||||
c.warning(curr_vals.to_string()),
|
||||
suffix,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::WrongNumberOfValues,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
|
@ -763,35 +793,35 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self
|
||||
where A: AnyArg<'a, 'b> + Display,
|
||||
U: Display
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' was provided more than once, but cannot \
|
||||
be used multiple times\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} The argument '{}' was provided more than once, but cannot \
|
||||
be used multiple times\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::UnexpectedMultipleUsage,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn unknown_argument<A, U>(arg: A,
|
||||
did_you_mean: &str,
|
||||
usage: U,
|
||||
color: ColorWhen)
|
||||
-> Self
|
||||
where A: Into<String>,
|
||||
U: Display
|
||||
pub fn unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
A: Into<String>,
|
||||
U: Display,
|
||||
{
|
||||
let a = arg.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
|
@ -799,19 +829,21 @@ impl Error {
|
|||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} Found argument '{}' which wasn't expected, or isn't valid in \
|
||||
this context{}\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*a),
|
||||
if did_you_mean.is_empty() {
|
||||
"\n".to_owned()
|
||||
} else {
|
||||
format!("{}\n", did_you_mean)
|
||||
},
|
||||
usage,
|
||||
c.good("--help")),
|
||||
message: format!(
|
||||
"{} Found argument '{}' which wasn't expected, or isn't valid in \
|
||||
this context{}\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*a),
|
||||
if did_you_mean.is_empty() {
|
||||
"\n".to_owned()
|
||||
} else {
|
||||
format!("{}\n", did_you_mean)
|
||||
},
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::UnknownArgument,
|
||||
info: Some(vec![a]),
|
||||
}
|
||||
|
@ -832,7 +864,8 @@ impl Error {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub fn argument_not_found_auto<A>(arg: A) -> Self
|
||||
where A: Into<String>
|
||||
where
|
||||
A: Into<String>,
|
||||
{
|
||||
let a = arg.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
|
@ -840,9 +873,11 @@ impl Error {
|
|||
when: ColorWhen::Auto,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' wasn't found",
|
||||
c.error("error:"),
|
||||
a.clone()),
|
||||
message: format!(
|
||||
"{} The argument '{}' wasn't found",
|
||||
c.error("error:"),
|
||||
a.clone()
|
||||
),
|
||||
kind: ErrorKind::ArgumentNotFound,
|
||||
info: Some(vec![a]),
|
||||
}
|
||||
|
|
26
src/fmt.rs
26
src/fmt.rs
|
@ -71,28 +71,32 @@ impl Colorizer {
|
|||
}
|
||||
|
||||
pub fn good<T>(&self, msg: T) -> Format<T>
|
||||
where T: fmt::Display + AsRef<str>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::good;");
|
||||
color!(self, Good, msg)
|
||||
}
|
||||
|
||||
pub fn warning<T>(&self, msg: T) -> Format<T>
|
||||
where T: fmt::Display + AsRef<str>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::warning;");
|
||||
color!(self, Warning, msg)
|
||||
}
|
||||
|
||||
pub fn error<T>(&self, msg: T) -> Format<T>
|
||||
where T: fmt::Display + AsRef<str>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::error;");
|
||||
color!(self, Error, msg)
|
||||
}
|
||||
|
||||
pub fn none<T>(&self, msg: T) -> Format<T>
|
||||
where T: fmt::Display + AsRef<str>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::none;");
|
||||
Format::None(msg)
|
||||
|
@ -136,7 +140,7 @@ impl<T: AsRef<str>> Format<T> {
|
|||
}
|
||||
|
||||
#[cfg(any(not(feature = "color"), target_os = "windows"))]
|
||||
#[cfg_attr(feature="lints", allow(match_same_arms))]
|
||||
#[cfg_attr(feature = "lints", allow(match_same_arms))]
|
||||
impl<T: fmt::Display> Format<T> {
|
||||
fn format(&self) -> &T {
|
||||
match *self {
|
||||
|
@ -168,14 +172,18 @@ mod test {
|
|||
#[test]
|
||||
fn colored_output() {
|
||||
let err = Format::Error("error");
|
||||
assert_eq!(&*format!("{}", err),
|
||||
&*format!("{}", Red.bold().paint("error")));
|
||||
assert_eq!(
|
||||
&*format!("{}", err),
|
||||
&*format!("{}", Red.bold().paint("error"))
|
||||
);
|
||||
let good = Format::Good("good");
|
||||
assert_eq!(&*format!("{}", good), &*format!("{}", Green.paint("good")));
|
||||
let warn = Format::Warning("warn");
|
||||
assert_eq!(&*format!("{}", warn), &*format!("{}", Yellow.paint("warn")));
|
||||
let none = Format::None("none");
|
||||
assert_eq!(&*format!("{}", none),
|
||||
&*format!("{}", ANSIString::from("none")));
|
||||
assert_eq!(
|
||||
&*format!("{}", none),
|
||||
&*format!("{}", ANSIString::from("none"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
50
src/lib.rs
50
src/lib.rs
|
@ -512,15 +512,10 @@
|
|||
//! `clap` is licensed under the MIT license. Please read the [LICENSE-MIT](LICENSE-MIT) file in
|
||||
//! this repository for more information.
|
||||
|
||||
#![crate_type= "lib"]
|
||||
#![crate_type = "lib"]
|
||||
#![doc(html_root_url = "https://docs.rs/clap/2.28.0")]
|
||||
#![deny(
|
||||
missing_docs,
|
||||
missing_debug_implementations,
|
||||
missing_copy_implementations,
|
||||
trivial_casts,
|
||||
unused_import_braces,
|
||||
unused_allocation)]
|
||||
#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
|
||||
unused_import_braces, unused_allocation)]
|
||||
// Lints we'd like to deny but are currently failing for upstream crates
|
||||
// unused_qualifications (bitflags, clippy)
|
||||
// trivial_numeric_casts (bitflags)
|
||||
|
@ -533,26 +528,26 @@
|
|||
#![cfg_attr(feature = "lints", allow(doc_markdown))]
|
||||
#![cfg_attr(feature = "lints", allow(explicit_iter_loop))]
|
||||
|
||||
#[cfg(feature = "suggestions")]
|
||||
extern crate strsim;
|
||||
#[cfg(feature = "color")]
|
||||
extern crate ansi_term;
|
||||
#[cfg(feature = "yaml")]
|
||||
extern crate yaml_rust;
|
||||
extern crate unicode_width;
|
||||
#[cfg(feature = "color")]
|
||||
extern crate atty;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[cfg(feature = "vec_map")]
|
||||
extern crate vec_map;
|
||||
#[cfg(feature = "suggestions")]
|
||||
extern crate strsim;
|
||||
#[cfg(feature = "wrap_help")]
|
||||
extern crate term_size;
|
||||
extern crate textwrap;
|
||||
#[cfg(feature = "color")]
|
||||
extern crate atty;
|
||||
extern crate unicode_width;
|
||||
#[cfg(feature = "vec_map")]
|
||||
extern crate vec_map;
|
||||
#[cfg(feature = "yaml")]
|
||||
extern crate yaml_rust;
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
pub use yaml_rust::YamlLoader;
|
||||
pub use args::{Arg, ArgGroup, ArgMatches, ArgSettings, SubCommand, Values, OsValues};
|
||||
pub use args::{Arg, ArgGroup, ArgMatches, ArgSettings, OsValues, SubCommand, Values};
|
||||
pub use app::{App, AppSettings};
|
||||
pub use fmt::Format;
|
||||
pub use errors::{Error, ErrorKind, Result};
|
||||
|
@ -576,22 +571,20 @@ const INTERNAL_ERROR_MSG: &'static str = "Fatal internal error. Please consider
|
|||
const INVALID_UTF8: &'static str = "unexpected invalid UTF-8 code point";
|
||||
|
||||
#[cfg(unstable)]
|
||||
pub use derive::{ArgEnum, ClapApp, IntoApp, FromArgMatches};
|
||||
pub use derive::{ArgEnum, ClapApp, FromArgMatches, IntoApp};
|
||||
|
||||
#[cfg(unstable)]
|
||||
mod derive {
|
||||
/// @TODO @release @docs
|
||||
pub trait ClapApp: IntoApp + FromArgMatches + Sized {
|
||||
|
||||
/// @TODO @release @docs
|
||||
fn parse() -> Self {
|
||||
Self::from_argmatches(Self::into_app().get_matches())
|
||||
}
|
||||
fn parse() -> Self { Self::from_argmatches(Self::into_app().get_matches()) }
|
||||
|
||||
/// @TODO @release @docs
|
||||
fn parse_from<I, T>(argv: I) -> Self
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
Self::from_argmatches(Self::into_app().get_matches_from(argv))
|
||||
}
|
||||
|
@ -604,8 +597,9 @@ mod derive {
|
|||
|
||||
/// @TODO @release @docs
|
||||
fn try_parse_from<I, T>(argv: I) -> Result<Self, clap::Error>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
Self::try_from_argmatches(Self::into_app().get_matches_from_safe(argv)?)
|
||||
}
|
||||
|
@ -627,5 +621,5 @@ mod derive {
|
|||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
pub trait ArgEnum { }
|
||||
pub trait ArgEnum {}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,8 @@ macro_rules! _clap_count_exprs {
|
|||
/// retrieve a `Vec<&'static str>` of the variant names, as well as implementing [`FromStr`] and
|
||||
/// [`Display`] automatically.
|
||||
///
|
||||
/// **NOTE:** Case insensitivity is supported for ASCII characters only
|
||||
/// **NOTE:** Case insensitivity is supported for ASCII characters only. It's highly recommended to
|
||||
/// use [`Arg::case_insensitive(true)`] for args that will be used with these enums
|
||||
///
|
||||
/// **NOTE:** This macro automatically implements [`std::str::FromStr`] and [`std::fmt::Display`]
|
||||
///
|
||||
|
@ -270,12 +271,12 @@ macro_rules! _clap_count_exprs {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # use clap::{App, Arg};
|
||||
/// arg_enum!{
|
||||
/// #[derive(Debug)]
|
||||
/// #[derive(PartialEq, Debug)]
|
||||
/// pub enum Foo {
|
||||
/// Bar,
|
||||
/// Baz,
|
||||
|
@ -286,17 +287,22 @@ macro_rules! _clap_count_exprs {
|
|||
/// // and implements std::str::FromStr to use with the value_t! macros
|
||||
/// fn main() {
|
||||
/// let m = App::new("app")
|
||||
/// .arg_from_usage("<foo> 'the foo'")
|
||||
/// .get_matches();
|
||||
/// .arg(Arg::from_usage("<foo> 'the foo'")
|
||||
/// .possible_values(&Foo::variants())
|
||||
/// .case_insensitive(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "app", "baz"
|
||||
/// ]);
|
||||
/// let f = value_t!(m, "foo", Foo).unwrap_or_else(|e| e.exit());
|
||||
///
|
||||
/// // Use f like any other Foo variant...
|
||||
/// assert_eq!(f, Foo::Baz);
|
||||
/// }
|
||||
/// ```
|
||||
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
|
||||
/// [`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
|
||||
/// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
|
||||
/// [`std::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
|
||||
/// [`Arg::case_insensitive(true)`]: ./struct.Arg.html#method.case_insensitive
|
||||
#[macro_export]
|
||||
macro_rules! arg_enum {
|
||||
(@as_item $($i:item)*) => ($($i)*);
|
||||
|
@ -386,7 +392,7 @@ macro_rules! arg_enum {
|
|||
/// .get_matches();
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature="no_cargo"))]
|
||||
#[cfg(not(feature = "no_cargo"))]
|
||||
#[macro_export]
|
||||
macro_rules! crate_version {
|
||||
() => {
|
||||
|
@ -415,7 +421,7 @@ macro_rules! crate_version {
|
|||
/// .get_matches();
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature="no_cargo"))]
|
||||
#[cfg(not(feature = "no_cargo"))]
|
||||
#[macro_export]
|
||||
macro_rules! crate_authors {
|
||||
($sep:expr) => {{
|
||||
|
@ -466,7 +472,7 @@ macro_rules! crate_authors {
|
|||
/// .get_matches();
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature="no_cargo"))]
|
||||
#[cfg(not(feature = "no_cargo"))]
|
||||
#[macro_export]
|
||||
macro_rules! crate_description {
|
||||
() => {
|
||||
|
@ -487,7 +493,7 @@ macro_rules! crate_description {
|
|||
/// .get_matches();
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature="no_cargo"))]
|
||||
#[cfg(not(feature = "no_cargo"))]
|
||||
#[macro_export]
|
||||
macro_rules! crate_name {
|
||||
() => {
|
||||
|
@ -518,7 +524,7 @@ macro_rules! crate_name {
|
|||
/// let m = app_from_crate!().get_matches();
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature="no_cargo"))]
|
||||
#[cfg(not(feature = "no_cargo"))]
|
||||
#[macro_export]
|
||||
macro_rules! app_from_crate {
|
||||
() => {
|
||||
|
|
40
src/map.rs
40
src/map.rs
|
@ -1,8 +1,8 @@
|
|||
#[cfg(feature = "vec_map")]
|
||||
pub use vec_map::{VecMap, Values};
|
||||
pub use vec_map::{Values, VecMap};
|
||||
|
||||
#[cfg(not(feature = "vec_map"))]
|
||||
pub use self::vec_map::{VecMap, Values};
|
||||
pub use self::vec_map::{Values, VecMap};
|
||||
|
||||
#[cfg(not(feature = "vec_map"))]
|
||||
mod vec_map {
|
||||
|
@ -17,40 +17,32 @@ mod vec_map {
|
|||
|
||||
impl<V> VecMap<V> {
|
||||
pub fn new() -> Self {
|
||||
VecMap { inner: Default::default() }
|
||||
VecMap {
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
pub fn len(&self) -> usize { self.inner.len() }
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.inner.is_empty()
|
||||
}
|
||||
pub fn is_empty(&self) -> bool { self.inner.is_empty() }
|
||||
|
||||
pub fn insert(&mut self, key: usize, value: V) -> Option<V> {
|
||||
self.inner.insert(key, value)
|
||||
}
|
||||
|
||||
pub fn values(&self) -> Values<V> {
|
||||
self.inner.values()
|
||||
}
|
||||
pub fn values(&self) -> Values<V> { self.inner.values() }
|
||||
|
||||
pub fn iter(&self) -> Iter<V> {
|
||||
Iter { inner: self.inner.iter() }
|
||||
Iter {
|
||||
inner: self.inner.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, key: usize) -> bool {
|
||||
self.inner.contains_key(&key)
|
||||
}
|
||||
pub fn contains_key(&self, key: usize) -> bool { self.inner.contains_key(&key) }
|
||||
|
||||
pub fn entry(&mut self, key: usize) -> Entry<V> {
|
||||
self.inner.entry(key)
|
||||
}
|
||||
pub fn entry(&mut self, key: usize) -> Entry<V> { self.inner.entry(key) }
|
||||
|
||||
pub fn get(&self, key: usize) -> Option<&V> {
|
||||
self.inner.get(&key)
|
||||
}
|
||||
pub fn get(&self, key: usize) -> Option<&V> { self.inner.get(&key) }
|
||||
}
|
||||
|
||||
pub type Values<'a, V> = btree_map::Values<'a, usize, V>;
|
||||
|
@ -71,9 +63,7 @@ mod vec_map {
|
|||
impl<'a, V: 'a> Iterator for Iter<'a, V> {
|
||||
type Item = (usize, &'a V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next().map(|(k, v)| (*k, v))
|
||||
}
|
||||
fn next(&mut self) -> Option<Self::Item> { self.inner.next().map(|(k, v)| (*k, v)) }
|
||||
}
|
||||
|
||||
impl<'a, V: 'a> DoubleEndedIterator for Iter<'a, V> {
|
||||
|
|
|
@ -48,11 +48,16 @@ impl OsStrExt2 for OsStr {
|
|||
fn split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr) {
|
||||
for (i, b) in self.as_bytes().iter().enumerate() {
|
||||
if b == &byte {
|
||||
return (OsStr::from_bytes(&self.as_bytes()[..i]),
|
||||
OsStr::from_bytes(&self.as_bytes()[i + 1..]));
|
||||
return (
|
||||
OsStr::from_bytes(&self.as_bytes()[..i]),
|
||||
OsStr::from_bytes(&self.as_bytes()[i + 1..]),
|
||||
);
|
||||
}
|
||||
}
|
||||
(&*self, OsStr::from_bytes(&self.as_bytes()[self.len_()..self.len_()]))
|
||||
(
|
||||
&*self,
|
||||
OsStr::from_bytes(&self.as_bytes()[self.len_()..self.len_()]),
|
||||
)
|
||||
}
|
||||
|
||||
fn trim_left_matches(&self, byte: u8) -> &OsStr {
|
||||
|
@ -71,7 +76,10 @@ impl OsStrExt2 for OsStr {
|
|||
}
|
||||
|
||||
fn split_at(&self, i: usize) -> (&OsStr, &OsStr) {
|
||||
(OsStr::from_bytes(&self.as_bytes()[..i]), OsStr::from_bytes(&self.as_bytes()[i..]))
|
||||
(
|
||||
OsStr::from_bytes(&self.as_bytes()[..i]),
|
||||
OsStr::from_bytes(&self.as_bytes()[i..]),
|
||||
)
|
||||
}
|
||||
|
||||
fn len_(&self) -> usize { self.as_bytes().len() }
|
||||
|
|
|
@ -13,15 +13,15 @@ use fmt::Format;
|
|||
#[cfg(feature = "suggestions")]
|
||||
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
|
||||
pub fn did_you_mean<'a, T: ?Sized, I>(v: &str, possible_values: I) -> Option<&'a str>
|
||||
where T: AsRef<str> + 'a,
|
||||
I: IntoIterator<Item = &'a T>
|
||||
where
|
||||
T: AsRef<str> + 'a,
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
{
|
||||
|
||||
let mut candidate: Option<(f64, &str)> = None;
|
||||
for pv in possible_values {
|
||||
let confidence = strsim::jaro_winkler(v, pv.as_ref());
|
||||
if confidence > 0.8 &&
|
||||
(candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) {
|
||||
if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
|
||||
{
|
||||
candidate = Some((confidence, pv.as_ref()));
|
||||
}
|
||||
}
|
||||
|
@ -33,47 +33,60 @@ pub fn did_you_mean<'a, T: ?Sized, I>(v: &str, possible_values: I) -> Option<&'a
|
|||
|
||||
#[cfg(not(feature = "suggestions"))]
|
||||
pub fn did_you_mean<'a, T: ?Sized, I>(_: &str, _: I) -> Option<&'a str>
|
||||
where T: AsRef<str> + 'a,
|
||||
I: IntoIterator<Item = &'a T>
|
||||
where
|
||||
T: AsRef<str> + 'a,
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
{
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
||||
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
|
||||
pub fn did_you_mean_flag_suffix<'z, T, I>(arg: &str, longs: I, subcommands: &'z [App])
|
||||
-> (String, Option<&'z str>)
|
||||
where T: AsRef<str> + 'z,
|
||||
I: IntoIterator<Item = &'z T>
|
||||
pub fn did_you_mean_flag_suffix<'z, T, I>(
|
||||
arg: &str,
|
||||
longs: I,
|
||||
subcommands: &'z [App],
|
||||
) -> (String, Option<&'z str>)
|
||||
where
|
||||
T: AsRef<str> + 'z,
|
||||
I: IntoIterator<Item = &'z T>,
|
||||
{
|
||||
match did_you_mean(arg, longs) {
|
||||
Some(candidate) => {
|
||||
let suffix = format!("\n\tDid you mean {}{}?", Format::Good("--"), Format::Good(candidate));
|
||||
return (suffix, Some(candidate))
|
||||
let suffix = format!(
|
||||
"\n\tDid you mean {}{}?",
|
||||
Format::Good("--"),
|
||||
Format::Good(candidate)
|
||||
);
|
||||
return (suffix, Some(candidate));
|
||||
}
|
||||
None => {
|
||||
for subcommand in subcommands {
|
||||
let opts = subcommand.p.flags.iter().filter_map(|f| f.s.long).chain(
|
||||
subcommand.p.opts.iter().filter_map(|o| o.s.long));
|
||||
None => for subcommand in subcommands {
|
||||
let opts = subcommand
|
||||
.p
|
||||
.flags
|
||||
.iter()
|
||||
.filter_map(|f| f.s.long)
|
||||
.chain(subcommand.p.opts.iter().filter_map(|o| o.s.long));
|
||||
|
||||
if let Some(candidate) = did_you_mean(arg, opts) {
|
||||
let suffix = format!(
|
||||
"\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
|
||||
Format::Good("--"),
|
||||
Format::Good(candidate),
|
||||
Format::Good(subcommand.get_name()));
|
||||
return (suffix, Some(candidate));
|
||||
}
|
||||
if let Some(candidate) = did_you_mean(arg, opts) {
|
||||
let suffix = format!(
|
||||
"\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
|
||||
Format::Good("--"),
|
||||
Format::Good(candidate),
|
||||
Format::Good(subcommand.get_name())
|
||||
);
|
||||
return (suffix, Some(candidate));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
(String::new(), None)
|
||||
}
|
||||
|
||||
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
||||
pub fn did_you_mean_value_suffix<'z, T, I>(arg: &str, values: I) -> (String, Option<&'z str>)
|
||||
where T: AsRef<str> + 'z,
|
||||
I: IntoIterator<Item = &'z T>
|
||||
where
|
||||
T: AsRef<str> + 'z,
|
||||
I: IntoIterator<Item = &'z T>,
|
||||
{
|
||||
match did_you_mean(arg, values) {
|
||||
Some(candidate) => {
|
||||
|
@ -104,13 +117,19 @@ mod test {
|
|||
fn suffix_long() {
|
||||
let p_vals = ["test", "possible", "values"];
|
||||
let suffix = "\n\tDid you mean \'--test\'?";
|
||||
assert_eq!(did_you_mean_flag_suffix("tst", p_vals.iter(), []), (suffix, Some("test")));
|
||||
assert_eq!(
|
||||
did_you_mean_flag_suffix("tst", p_vals.iter(), []),
|
||||
(suffix, Some("test"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn suffix_enum() {
|
||||
let p_vals = ["test", "possible", "values"];
|
||||
let suffix = "\n\tDid you mean \'test\'?";
|
||||
assert_eq!(did_you_mean_value_suffix("tst", p_vals.iter()), (suffix, Some("test")));
|
||||
assert_eq!(
|
||||
did_you_mean_value_suffix("tst", p_vals.iter()),
|
||||
(suffix, Some("test"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Internal
|
||||
use INTERNAL_ERROR_MSG;
|
||||
use args::Arg;
|
||||
|
@ -60,9 +59,13 @@ impl<'a> UsageParser<'a> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
debug_assert!(!arg.b.name.is_empty(),
|
||||
format!("No name found for Arg when parsing usage string: {}",
|
||||
self.usage));
|
||||
debug_assert!(
|
||||
!arg.b.name.is_empty(),
|
||||
format!(
|
||||
"No name found for Arg when parsing usage string: {}",
|
||||
self.usage
|
||||
)
|
||||
);
|
||||
arg.v.num_vals = match arg.v.val_names {
|
||||
Some(ref v) if v.len() >= 2 => Some(v.len() as u64),
|
||||
_ => None,
|
||||
|
@ -73,8 +76,11 @@ impl<'a> UsageParser<'a> {
|
|||
|
||||
fn name(&mut self, arg: &mut Arg<'a, 'a>) {
|
||||
debugln!("UsageParser::name;");
|
||||
if *self.usage.as_bytes().get(self.pos).expect(INTERNAL_ERROR_MSG) == b'<' &&
|
||||
!self.explicit_name_set {
|
||||
if *self.usage
|
||||
.as_bytes()
|
||||
.get(self.pos)
|
||||
.expect(INTERNAL_ERROR_MSG) == b'<' && !self.explicit_name_set
|
||||
{
|
||||
arg.setb(ArgSettings::Required);
|
||||
}
|
||||
self.pos += 1;
|
||||
|
@ -104,17 +110,25 @@ impl<'a> UsageParser<'a> {
|
|||
}
|
||||
|
||||
fn stop_at<F>(&mut self, f: F)
|
||||
where F: Fn(u8) -> bool
|
||||
where
|
||||
F: Fn(u8) -> bool,
|
||||
{
|
||||
debugln!("UsageParser::stop_at;");
|
||||
self.start = self.pos;
|
||||
self.pos += self.usage[self.start..].bytes().take_while(|&b| f(b)).count();
|
||||
self.pos += self.usage[self.start..]
|
||||
.bytes()
|
||||
.take_while(|&b| f(b))
|
||||
.count();
|
||||
}
|
||||
|
||||
fn short_or_long(&mut self, arg: &mut Arg<'a, 'a>) {
|
||||
debugln!("UsageParser::short_or_long;");
|
||||
self.pos += 1;
|
||||
if *self.usage.as_bytes().get(self.pos).expect(INTERNAL_ERROR_MSG) == b'-' {
|
||||
if *self.usage
|
||||
.as_bytes()
|
||||
.get(self.pos)
|
||||
.expect(INTERNAL_ERROR_MSG) == b'-'
|
||||
{
|
||||
self.pos += 1;
|
||||
self.long(arg);
|
||||
return;
|
||||
|
@ -181,9 +195,12 @@ impl<'a> UsageParser<'a> {
|
|||
self.stop_at(help_start);
|
||||
self.start = self.pos + 1;
|
||||
self.pos = self.usage.len() - 1;
|
||||
debugln!("UsageParser::help: setting help...{}", &self.usage[self.start..self.pos]);
|
||||
debugln!(
|
||||
"UsageParser::help: setting help...{}",
|
||||
&self.usage[self.start..self.pos]
|
||||
);
|
||||
arg.b.help = Some(&self.usage[self.start..self.pos]);
|
||||
self.pos += 1; // Move to next byte to keep from thinking ending ' is a start
|
||||
self.pos += 1; // Move to next byte to keep from thinking ending ' is a start
|
||||
self.prev = UsageToken::Help;
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +349,10 @@ mod test {
|
|||
assert!(!a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -346,7 +366,10 @@ mod test {
|
|||
assert!(!b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -360,7 +383,10 @@ mod test {
|
|||
assert!(!c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -374,7 +400,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -388,7 +417,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -402,7 +434,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -416,7 +451,10 @@ mod test {
|
|||
assert!(b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -430,7 +468,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -444,7 +485,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -458,7 +502,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -472,7 +519,10 @@ mod test {
|
|||
assert!(!a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -486,8 +536,10 @@ mod test {
|
|||
assert!(!b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -501,7 +553,10 @@ mod test {
|
|||
assert!(!c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -515,8 +570,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -530,7 +587,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -544,7 +604,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -558,8 +621,10 @@ mod test {
|
|||
assert!(b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -573,7 +638,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -587,7 +655,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -601,8 +672,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -616,7 +689,10 @@ mod test {
|
|||
assert!(!a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -630,8 +706,10 @@ mod test {
|
|||
assert!(!b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -645,7 +723,10 @@ mod test {
|
|||
assert!(!c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -659,8 +740,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -674,7 +757,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -688,7 +774,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -702,8 +791,10 @@ mod test {
|
|||
assert!(b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -717,7 +808,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -731,7 +825,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -745,8 +842,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -760,8 +859,10 @@ mod test {
|
|||
assert!(!a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -775,8 +876,10 @@ mod test {
|
|||
assert!(!b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -790,7 +893,10 @@ mod test {
|
|||
assert!(!c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -804,8 +910,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -819,8 +927,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -834,8 +944,10 @@ mod test {
|
|||
assert!(b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -849,7 +961,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -863,8 +978,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -878,8 +995,10 @@ mod test {
|
|||
assert!(!a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -893,8 +1012,10 @@ mod test {
|
|||
assert!(!b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -908,7 +1029,10 @@ mod test {
|
|||
assert!(!c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -922,8 +1046,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -937,8 +1063,10 @@ mod test {
|
|||
assert!(a.is_set(ArgSettings::Multiple));
|
||||
assert!(a.is_set(ArgSettings::TakesValue));
|
||||
assert!(!a.is_set(ArgSettings::Required));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(a.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -952,8 +1080,10 @@ mod test {
|
|||
assert!(b.is_set(ArgSettings::Multiple));
|
||||
assert!(b.is_set(ArgSettings::TakesValue));
|
||||
assert!(!b.is_set(ArgSettings::Required));
|
||||
assert_eq!(b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
b.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(b.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -967,7 +1097,10 @@ mod test {
|
|||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
assert!(c.is_set(ArgSettings::TakesValue));
|
||||
assert!(c.is_set(ArgSettings::Required));
|
||||
assert_eq!(c.v.val_names.unwrap().values().collect::<Vec<_>>(), [&"opt"]);
|
||||
assert_eq!(
|
||||
c.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"opt"]
|
||||
);
|
||||
assert!(c.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -981,8 +1114,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"option"]
|
||||
);
|
||||
assert!(d.v.num_vals.is_none());
|
||||
}
|
||||
|
||||
|
@ -996,8 +1131,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]
|
||||
);
|
||||
assert_eq!(d.v.num_vals.unwrap(), 2);
|
||||
}
|
||||
|
||||
|
@ -1011,8 +1148,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]
|
||||
);
|
||||
assert_eq!(d.v.num_vals.unwrap(), 2);
|
||||
}
|
||||
|
||||
|
@ -1026,8 +1165,10 @@ mod test {
|
|||
assert!(d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]
|
||||
);
|
||||
assert_eq!(d.v.num_vals.unwrap(), 2);
|
||||
}
|
||||
|
||||
|
@ -1041,8 +1182,10 @@ mod test {
|
|||
assert!(!d.is_set(ArgSettings::Multiple));
|
||||
assert!(d.is_set(ArgSettings::TakesValue));
|
||||
assert!(!d.is_set(ArgSettings::Required));
|
||||
assert_eq!(d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]);
|
||||
assert_eq!(
|
||||
d.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"file", &"mode"]
|
||||
);
|
||||
assert_eq!(d.v.num_vals.unwrap(), 2);
|
||||
}
|
||||
|
||||
|
@ -1116,8 +1259,10 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn pos_help_newline() {
|
||||
let c = Arg::from_usage("[pos]... 'some help{n}\
|
||||
info'");
|
||||
let c = Arg::from_usage(
|
||||
"[pos]... 'some help{n}\
|
||||
info'",
|
||||
);
|
||||
assert_eq!(c.b.name, "pos");
|
||||
assert_eq!(c.b.help.unwrap(), "some help{n}info");
|
||||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
|
@ -1128,8 +1273,10 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn pos_help_newline_lit_sq() {
|
||||
let c = Arg::from_usage("[pos]... 'some help\' stuff{n}\
|
||||
info'");
|
||||
let c = Arg::from_usage(
|
||||
"[pos]... 'some help\' stuff{n}\
|
||||
info'",
|
||||
);
|
||||
assert_eq!(c.b.name, "pos");
|
||||
assert_eq!(c.b.help.unwrap(), "some help' stuff{n}info");
|
||||
assert!(c.is_set(ArgSettings::Multiple));
|
||||
|
@ -1191,8 +1338,10 @@ mod test {
|
|||
let a = Arg::from_usage("[ñämê] --ôpt=[üñíčöĐ€] 'hælp'");
|
||||
assert_eq!(a.b.name, "ñämê");
|
||||
assert_eq!(a.s.long, Some("ôpt"));
|
||||
assert_eq!(a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"üñíčöĐ€"]);
|
||||
assert_eq!(
|
||||
a.v.val_names.unwrap().values().collect::<Vec<_>>(),
|
||||
[&"üñíčöĐ€"]
|
||||
);
|
||||
assert_eq!(a.b.help, Some("hælp"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,12 @@ extern crate regex;
|
|||
|
||||
include!("../clap-test.rs");
|
||||
|
||||
#[allow(unsused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
use clap::{App, Arg, ErrorKind};
|
||||
|
||||
#[cfg(feature="suggestions")]
|
||||
#[cfg(feature = "suggestions")]
|
||||
static PV_ERROR: &'static str = "error: 'slo' isn't a valid value for '--Option <option3>'
|
||||
\t[values: fast, slow]
|
||||
|
||||
|
@ -16,7 +19,7 @@ USAGE:
|
|||
|
||||
For more information try --help";
|
||||
|
||||
#[cfg(not(feature="suggestions"))]
|
||||
#[cfg(not(feature = "suggestions"))]
|
||||
static PV_ERROR: &'static str = "error: 'slo' isn't a valid value for '--Option <option3>'
|
||||
\t[values: fast, slow]
|
||||
|
||||
|
@ -29,9 +32,11 @@ For more information try --help";
|
|||
#[test]
|
||||
fn possible_values_of_positional() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123"))
|
||||
.arg(
|
||||
Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123"),
|
||||
)
|
||||
.get_matches_from_safe(vec!["myprog", "test123"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
|
@ -44,9 +49,11 @@ fn possible_values_of_positional() {
|
|||
#[test]
|
||||
fn possible_values_of_positional_fail() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123"))
|
||||
.arg(
|
||||
Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123"),
|
||||
)
|
||||
.get_matches_from_safe(vec!["myprog", "notest"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
|
@ -56,28 +63,35 @@ fn possible_values_of_positional_fail() {
|
|||
#[test]
|
||||
fn possible_values_of_positional_multiple() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true))
|
||||
.arg(
|
||||
Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["myprog", "test123", "test321"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
let m = m.unwrap();
|
||||
|
||||
assert!(m.is_present("positional"));
|
||||
assert_eq!(m.values_of("positional").unwrap().collect::<Vec<_>>(), vec!["test123", "test321"]);
|
||||
assert_eq!(
|
||||
m.values_of("positional").unwrap().collect::<Vec<_>>(),
|
||||
vec!["test123", "test321"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn possible_values_of_positional_multiple_fail() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true))
|
||||
.arg(
|
||||
Arg::with_name("positional")
|
||||
.index(1)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["myprog", "test123", "notest"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
|
@ -87,11 +101,13 @@ fn possible_values_of_positional_multiple_fail() {
|
|||
#[test]
|
||||
fn possible_values_of_option() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123"))
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123"),
|
||||
)
|
||||
.get_matches_from_safe(vec!["myprog", "--option", "test123"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
|
@ -104,11 +120,13 @@ fn possible_values_of_option() {
|
|||
#[test]
|
||||
fn possible_values_of_option_fail() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123"))
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123"),
|
||||
)
|
||||
.get_matches_from_safe(vec!["myprog", "--option", "notest"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
|
@ -118,41 +136,40 @@ fn possible_values_of_option_fail() {
|
|||
#[test]
|
||||
fn possible_values_of_option_multiple() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true))
|
||||
.get_matches_from_safe(vec![
|
||||
"",
|
||||
"--option", "test123",
|
||||
"--option", "test321",
|
||||
]);
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["", "--option", "test123", "--option", "test321"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
let m = m.unwrap();
|
||||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["test123", "test321"]);
|
||||
assert_eq!(
|
||||
m.values_of("option").unwrap().collect::<Vec<_>>(),
|
||||
vec!["test123", "test321"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn possible_values_of_option_multiple_fail() {
|
||||
let m = App::new("possible_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true))
|
||||
.get_matches_from_safe(vec![
|
||||
"",
|
||||
"--option", "test123",
|
||||
"--option", "notest",
|
||||
]);
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["", "--option", "test123", "--option", "notest"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
|
||||
|
@ -160,5 +177,90 @@ fn possible_values_of_option_multiple_fail() {
|
|||
|
||||
#[test]
|
||||
fn possible_values_output() {
|
||||
assert!(test::compare_output(test::complex_app(), "clap-test -O slo", PV_ERROR, true));
|
||||
assert!(test::compare_output(
|
||||
test::complex_app(),
|
||||
"clap-test -O slo",
|
||||
PV_ERROR,
|
||||
true
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn case_insensitive() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.case_insensitive(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["pv", "--option", "TeSt123"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
assert!(
|
||||
m.unwrap()
|
||||
.value_of("option")
|
||||
.unwrap()
|
||||
.eq_ignore_ascii_case("test123")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn case_insensitive_faili() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321"),
|
||||
)
|
||||
.get_matches_from_safe(vec!["pv", "--option", "TeSt123"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn case_insensitive_multiple() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true)
|
||||
.case_insensitive(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]);
|
||||
|
||||
assert!(m.is_ok());
|
||||
assert_eq!(
|
||||
m.unwrap().values_of("option").unwrap().collect::<Vec<_>>(),
|
||||
&["TeSt123", "teST123", "tESt321"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn case_insensitive_multiple_fail() {
|
||||
let m = App::new("pv")
|
||||
.arg(
|
||||
Arg::with_name("option")
|
||||
.short("-o")
|
||||
.long("--option")
|
||||
.takes_value(true)
|
||||
.possible_value("test123")
|
||||
.possible_value("test321")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec!["pv", "--option", "test123", "teST123", "test321"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue