diff --git a/CHANGELOG.md b/CHANGELOG.md
index 844dc5b8cd3..63a525f5c8f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+
+### v2.29.3 (2018-02-05)
+
+
+#### Improvements
+
+* **Overrides:** clap now supports arguments which override with themselves ([6c7a0010](https://github.com/kbknapp/clap-rs/commit/6c7a001023ca1eac1cc6ffe6c936b4c4a2aa3c45), closes [#976](https://github.com/kbknapp/clap-rs/issues/976))
+
+#### Bug Fixes
+
+* **Requirements:** fixes an issue where conflicting args would still show up as required ([e06cefac](https://github.com/kbknapp/clap-rs/commit/e06cefac97083838c0a4e1444dcad02a5c3f911e), closes [#1158](https://github.com/kbknapp/clap-rs/issues/1158))
+* Fixes a bug which disallows proper nesting of `--` ([73993fe](https://github.com/kbknapp/clap-rs/commit/73993fe30d135f682e763ec93dcb0814ed518011), closes [#1161](https://github.com/kbknapp/clap-rs/issues/1161))
+
+#### New Settings
+
+* **AllArgsOverrideSelf:** adds a new convenience setting to allow all args to override themselves ([4670325d](https://github.com/kbknapp/clap-rs/commit/4670325d1bf0369addec2ae2bcb56f1be054c924))
+
+
+
### v2.29.2 (2018-01-16)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 8899cd36e96..50e7235d790 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,85 +1,89 @@
the following is a list of contributors:
-[
](https://github.com/kbknapp) |[
](https://github.com/homu) |[
](https://github.com/Vinatorul) |[
](https://github.com/tormol) |[
](https://github.com/little-dude) |[
](https://github.com/sru) |
+[
](https://github.com/kbknapp) |[
](https://github.com/homu) |[
](https://github.com/Vinatorul) |[
](https://github.com/tormol) |[
](https://github.com/willmurphyscode) |[
](https://github.com/little-dude) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[kbknapp](https://github.com/kbknapp) |[homu](https://github.com/homu) |[Vinatorul](https://github.com/Vinatorul) |[tormol](https://github.com/tormol) |[little-dude](https://github.com/little-dude) |[sru](https://github.com/sru) |
+[kbknapp](https://github.com/kbknapp) |[homu](https://github.com/homu) |[Vinatorul](https://github.com/Vinatorul) |[tormol](https://github.com/tormol) |[willmurphyscode](https://github.com/willmurphyscode) |[little-dude](https://github.com/little-dude) |
-[
](https://github.com/willmurphyscode) |[
](https://github.com/mgeisler) |[
](https://github.com/nabijaczleweli) |[
](https://github.com/Byron) |[
](https://github.com/hgrecco) |[
](https://github.com/bluejekyll) |
+[
](https://github.com/sru) |[
](https://github.com/mgeisler) |[
](https://github.com/nabijaczleweli) |[
](https://github.com/Byron) |[
](https://github.com/hgrecco) |[
](https://github.com/bluejekyll) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[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) |
+[sru](https://github.com/sru) |[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) |
[
](https://github.com/segevfiner) |[
](https://github.com/ignatenkobrain) |[
](https://github.com/james-darkfox) |[
](https://github.com/H2CO3) |[
](https://github.com/nateozem) |[
](https://github.com/glowing-chemist) |
:---: |:---: |:---: |:---: |:---: |:---: |
[segevfiner](https://github.com/segevfiner) |[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) |
-[
](https://github.com/rtaycher) |[
](https://github.com/Arnavion) |[
](https://github.com/japaric) |[
](https://github.com/untitaker) |[
](https://github.com/afiune) |[
](https://github.com/crazymerlyn) |
+[
](https://github.com/discosultan) |[
](https://github.com/rtaycher) |[
](https://github.com/Arnavion) |[
](https://github.com/japaric) |[
](https://github.com/untitaker) |[
](https://github.com/afiune) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[rtaycher](https://github.com/rtaycher) |[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) |
+[discosultan](https://github.com/discosultan) |[rtaycher](https://github.com/rtaycher) |[Arnavion](https://github.com/Arnavion) |[japaric](https://github.com/japaric) |[untitaker](https://github.com/untitaker) |[afiune](https://github.com/afiune) |
-[
](https://github.com/SuperFluffy) |[
](https://github.com/matthiasbeyer) |[
](https://github.com/malbarbo) |[
](https://github.com/tshepang) |[
](https://github.com/golem131) |[
](https://github.com/jimmycuadra) |
+[
](https://github.com/crazymerlyn) |[
](https://github.com/SuperFluffy) |[
](https://github.com/matthiasbeyer) |[
](https://github.com/malbarbo) |[
](https://github.com/tshepang) |[
](https://github.com/golem131) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[SuperFluffy](https://github.com/SuperFluffy) |[matthiasbeyer](https://github.com/matthiasbeyer) |[malbarbo](https://github.com/malbarbo) |[tshepang](https://github.com/tshepang) |[golem131](https://github.com/golem131) |[jimmycuadra](https://github.com/jimmycuadra) |
+[crazymerlyn](https://github.com/crazymerlyn) |[SuperFluffy](https://github.com/SuperFluffy) |[matthiasbeyer](https://github.com/matthiasbeyer) |[malbarbo](https://github.com/malbarbo) |[tshepang](https://github.com/tshepang) |[golem131](https://github.com/golem131) |
-[
](https://github.com/Nemo157) |[
](https://github.com/severen) |[
](https://github.com/Eijebong) |[
](https://github.com/cstorey) |[
](https://github.com/wdv4758h) |[
](https://github.com/frewsxcv) |
+[
](https://github.com/jimmycuadra) |[
](https://github.com/Nemo157) |[
](https://github.com/severen) |[
](https://github.com/Eijebong) |[
](https://github.com/cstorey) |[
](https://github.com/wdv4758h) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[Nemo157](https://github.com/Nemo157) |[severen](https://github.com/severen) |[Eijebong](https://github.com/Eijebong) |[cstorey](https://github.com/cstorey) |[wdv4758h](https://github.com/wdv4758h) |[frewsxcv](https://github.com/frewsxcv) |
+[jimmycuadra](https://github.com/jimmycuadra) |[Nemo157](https://github.com/Nemo157) |[severen](https://github.com/severen) |[Eijebong](https://github.com/Eijebong) |[cstorey](https://github.com/cstorey) |[wdv4758h](https://github.com/wdv4758h) |
-[
](https://github.com/hoodie) |[
](https://github.com/huonw) |[
](https://github.com/GrappigPanda) |[
](https://github.com/shepmaster) |[
](https://github.com/starkat99) |[
](https://github.com/porglezomp) |
+[
](https://github.com/frewsxcv) |[
](https://github.com/hoodie) |[
](https://github.com/huonw) |[
](https://github.com/GrappigPanda) |[
](https://github.com/shepmaster) |[
](https://github.com/starkat99) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[GrappigPanda](https://github.com/GrappigPanda) |[shepmaster](https://github.com/shepmaster) |[starkat99](https://github.com/starkat99) |[porglezomp](https://github.com/porglezomp) |
+[frewsxcv](https://github.com/frewsxcv) |[hoodie](https://github.com/hoodie) |[huonw](https://github.com/huonw) |[GrappigPanda](https://github.com/GrappigPanda) |[shepmaster](https://github.com/shepmaster) |[starkat99](https://github.com/starkat99) |
-[
](https://github.com/kraai) |[
](https://github.com/musoke) |[
](https://github.com/nelsonjchen) |[
](https://github.com/pkgw) |[
](https://github.com/Deedasmi) |[
](https://github.com/vmchale) |
+[
](https://github.com/porglezomp) |[
](https://github.com/kraai) |[
](https://github.com/musoke) |[
](https://github.com/nelsonjchen) |[
](https://github.com/pkgw) |[
](https://github.com/Deedasmi) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[kraai](https://github.com/kraai) |[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) |
+[porglezomp](https://github.com/porglezomp) |[kraai](https://github.com/kraai) |[musoke](https://github.com/musoke) |[nelsonjchen](https://github.com/nelsonjchen) |[pkgw](https://github.com/pkgw) |[Deedasmi](https://github.com/Deedasmi) |
-[
](https://github.com/messense) |[
](https://github.com/Keats) |[
](https://github.com/kieraneglin) |[
](https://github.com/durka) |[
](https://github.com/alex-gulyas) |[
](https://github.com/cite-reader) |
+[
](https://github.com/vmchale) |[
](https://github.com/messense) |[
](https://github.com/Keats) |[
](https://github.com/kieraneglin) |[
](https://github.com/durka) |[
](https://github.com/alex-gulyas) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[messense](https://github.com/messense) |[Keats](https://github.com/Keats) |[kieraneglin](https://github.com/kieraneglin) |[durka](https://github.com/durka) |[alex-gulyas](https://github.com/alex-gulyas) |[cite-reader](https://github.com/cite-reader) |
+[vmchale](https://github.com/vmchale) |[messense](https://github.com/messense) |[Keats](https://github.com/Keats) |[kieraneglin](https://github.com/kieraneglin) |[durka](https://github.com/durka) |[alex-gulyas](https://github.com/alex-gulyas) |
-[
](https://github.com/alexbool) |[
](https://github.com/AluisioASG) |[
](https://github.com/BurntSushi) |[
](https://github.com/nox) |[
](https://github.com/mitsuhiko) |[
](https://github.com/brennie) |
+[
](https://github.com/cite-reader) |[
](https://github.com/alexbool) |[
](https://github.com/AluisioASG) |[
](https://github.com/BurntSushi) |[
](https://github.com/nox) |[
](https://github.com/mitsuhiko) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[alexbool](https://github.com/alexbool) |[AluisioASG](https://github.com/AluisioASG) |[BurntSushi](https://github.com/BurntSushi) |[nox](https://github.com/nox) |[mitsuhiko](https://github.com/mitsuhiko) |[brennie](https://github.com/brennie) |
+[cite-reader](https://github.com/cite-reader) |[alexbool](https://github.com/alexbool) |[AluisioASG](https://github.com/AluisioASG) |[BurntSushi](https://github.com/BurntSushi) |[nox](https://github.com/nox) |[mitsuhiko](https://github.com/mitsuhiko) |
-[
](https://github.com/pixelistik) |[
](https://github.com/Bilalh) |[
](https://github.com/dotdash) |[
](https://github.com/bradurani) |[
](https://github.com/Seeker14491) |[
](https://github.com/brianp) |
+[
](https://github.com/brennie) |[
](https://github.com/pixelistik) |[
](https://github.com/Bilalh) |[
](https://github.com/dotdash) |[
](https://github.com/bradurani) |[
](https://github.com/Seeker14491) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[pixelistik](https://github.com/pixelistik) |[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) |
+[brennie](https://github.com/brennie) |[pixelistik](https://github.com/pixelistik) |[Bilalh](https://github.com/Bilalh) |[dotdash](https://github.com/dotdash) |[bradurani](https://github.com/bradurani) |[Seeker14491](https://github.com/Seeker14491) |
-[
](https://github.com/cldershem) |[
](https://github.com/casey) |[
](https://github.com/volks73) |[
](https://github.com/daboross) |[
](https://github.com/mernen) |[
](https://github.com/dguo) |
+[
](https://github.com/brianp) |[
](https://github.com/cldershem) |[
](https://github.com/casey) |[
](https://github.com/volks73) |[
](https://github.com/daboross) |[
](https://github.com/da-x) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[cldershem](https://github.com/cldershem) |[casey](https://github.com/casey) |[volks73](https://github.com/volks73) |[daboross](https://github.com/daboross) |[mernen](https://github.com/mernen) |[dguo](https://github.com/dguo) |
+[brianp](https://github.com/brianp) |[cldershem](https://github.com/cldershem) |[casey](https://github.com/casey) |[volks73](https://github.com/volks73) |[daboross](https://github.com/daboross) |[da-x](https://github.com/da-x) |
-[
](https://github.com/davidszotten) |[
](https://github.com/drusellers) |[
](https://github.com/eddyb) |[
](https://github.com/Enet4) |[
](https://github.com/Fraser999) |[
](https://github.com/birkenfeld) |
+[
](https://github.com/mernen) |[
](https://github.com/dguo) |[
](https://github.com/davidszotten) |[
](https://github.com/drusellers) |[
](https://github.com/eddyb) |[
](https://github.com/Enet4) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[davidszotten](https://github.com/davidszotten) |[drusellers](https://github.com/drusellers) |[eddyb](https://github.com/eddyb) |[Enet4](https://github.com/Enet4) |[Fraser999](https://github.com/Fraser999) |[birkenfeld](https://github.com/birkenfeld) |
+[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) |[Enet4](https://github.com/Enet4) |
-[
](https://github.com/guanqun) |[
](https://github.com/tanakh) |[
](https://github.com/SirVer) |[
](https://github.com/idmit) |[
](https://github.com/archer884) |[
](https://github.com/discosultan) |
+[
](https://github.com/Fraser999) |[
](https://github.com/birkenfeld) |[
](https://github.com/guanqun) |[
](https://github.com/tanakh) |[
](https://github.com/SirVer) |[
](https://github.com/idmit) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[guanqun](https://github.com/guanqun) |[tanakh](https://github.com/tanakh) |[SirVer](https://github.com/SirVer) |[idmit](https://github.com/idmit) |[archer884](https://github.com/archer884) |[discosultan](https://github.com/discosultan) |
+[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) |
-[
](https://github.com/jacobmischka) |[
](https://github.com/jespino) |[
](https://github.com/jfrankenau) |[
](https://github.com/jtdowney) |[
](https://github.com/andete) |[
](https://github.com/joshtriplett) |
+[
](https://github.com/archer884) |[
](https://github.com/jacobmischka) |[
](https://github.com/jespino) |[
](https://github.com/jfrankenau) |[
](https://github.com/jtdowney) |[
](https://github.com/andete) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[jacobmischka](https://github.com/jacobmischka) |[jespino](https://github.com/jespino) |[jfrankenau](https://github.com/jfrankenau) |[jtdowney](https://github.com/jtdowney) |[andete](https://github.com/andete) |[joshtriplett](https://github.com/joshtriplett) |
+[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) |[andete](https://github.com/andete) |
-[
](https://github.com/Kalwyn) |[
](https://github.com/manuel-rhdt) |[
](https://github.com/Marwes) |[
](https://github.com/mdaffin) |[
](https://github.com/iliekturtles) |[
](https://github.com/nicompte) |
+[
](https://github.com/joshtriplett) |[
](https://github.com/Kalwyn) |[
](https://github.com/manuel-rhdt) |[
](https://github.com/Marwes) |[
](https://github.com/mdaffin) |[
](https://github.com/iliekturtles) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[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) |
+[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) |[iliekturtles](https://github.com/iliekturtles) |
-[
](https://github.com/NickeZ) |[
](https://github.com/nvzqz) |[
](https://github.com/nuew) |[
](https://github.com/Geogi) |[
](https://github.com/focusaurus) |[
](https://github.com/flying-sheep) |
+[
](https://github.com/nicompte) |[
](https://github.com/NickeZ) |[
](https://github.com/nvzqz) |[
](https://github.com/nuew) |[
](https://github.com/Geogi) |[
](https://github.com/focusaurus) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[NickeZ](https://github.com/NickeZ) |[nvzqz](https://github.com/nvzqz) |[nuew](https://github.com/nuew) |[Geogi](https://github.com/Geogi) |[focusaurus](https://github.com/focusaurus) |[flying-sheep](https://github.com/flying-sheep) |
+[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) |[focusaurus](https://github.com/focusaurus) |
-[
](https://github.com/Phlosioneer) |[
](https://github.com/peppsac) |[
](https://github.com/golddranks) |[
](https://github.com/hexjelly) |[
](https://github.com/rom1v) |[
](https://github.com/rnelson) |
+[
](https://github.com/flying-sheep) |[
](https://github.com/Phlosioneer) |[
](https://github.com/peppsac) |[
](https://github.com/golddranks) |[
](https://github.com/hexjelly) |[
](https://github.com/rom1v) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[Phlosioneer](https://github.com/Phlosioneer) |[peppsac](https://github.com/peppsac) |[golddranks](https://github.com/golddranks) |[hexjelly](https://github.com/hexjelly) |[rom1v](https://github.com/rom1v) |[rnelson](https://github.com/rnelson) |
+[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) |[rom1v](https://github.com/rom1v) |
-[
](https://github.com/swatteau) |[
](https://github.com/tspiteri) |[
](https://github.com/siiptuo) |[
](https://github.com/vks) |[
](https://github.com/vsupalov) |[
](https://github.com/mineo) |
+[
](https://github.com/rnelson) |[
](https://github.com/swatteau) |[
](https://github.com/tchajed) |[
](https://github.com/tspiteri) |[
](https://github.com/siiptuo) |[
](https://github.com/vks) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[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) |[mineo](https://github.com/mineo) |
+[rnelson](https://github.com/rnelson) |[swatteau](https://github.com/swatteau) |[tchajed](https://github.com/tchajed) |[tspiteri](https://github.com/tspiteri) |[siiptuo](https://github.com/siiptuo) |[vks](https://github.com/vks) |
-[
](https://github.com/wabain) |[
](https://github.com/grossws) |[
](https://github.com/kennytm) |[
](https://github.com/mvaude) |[
](https://github.com/panicbit) |[
](https://github.com/ogham) |
+[
](https://github.com/vsupalov) |[
](https://github.com/mineo) |[
](https://github.com/wabain) |[
](https://github.com/grossws) |[
](https://github.com/kennytm) |[
](https://github.com/mvaude) |
:---: |:---: |:---: |:---: |:---: |:---: |
-[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) |[ogham](https://github.com/ogham) |
+[vsupalov](https://github.com/vsupalov) |[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) |
+
+[
](https://github.com/panicbit) |[
](https://github.com/ogham) |
+:---: |:---: |
+[panicbit](https://github.com/panicbit) |[ogham](https://github.com/ogham) |
diff --git a/Cargo.toml b/Cargo.toml
index e2b252115c6..f659c47121b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "clap"
-version = "2.29.2"
+version = "2.29.3"
authors = ["Kevin K. "]
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
repository = "https://github.com/kbknapp/clap-rs"
diff --git a/README.md b/README.md
index 9601aaf3317..de44e2bb766 100644
--- a/README.md
+++ b/README.md
@@ -42,25 +42,32 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
## What's New
+Here's whats new in 2.29.3:
+
+* **Self Overrides:** now supports arguments which override themselves (Allows true shell aliases, config files, etc!)
+* **Requirements:** fixes an issue where conflicting args would still show up as required and missing
+* Fixes a bug which disallows proper nesting of `--` for args that capture all values after the first `--`
+* **AppSettings::AllArgsOverrideSelf:** adds a new convenience setting to allow all args to override themselves
+
Here's whats new in 2.29.2:
* **Many ZSH Completions Improvements** (Thanks to @segevfiner)
* Positional arguments will default to file completion when not using specific values!
- * Implement postional argument possible values completion
- * Removes redundant code from output
- * Don't pass `-S` to `_arguments` if Zsh is too old
- * Fix completions with mixed positionals and subcommands
- * String escape possible values for options
+ * Implement postional argument possible values completion
+ * Removes redundant code from output
+ * Don't pass `-S` to `_arguments` if Zsh is too old
+ * Fix completions with mixed positionals and subcommands
+ * String escape possible values for options
Here's whats new in 2.29.1:
* Debloats clap by deduplicating logic and refactors for a ~57% decrease in code size! This is with zero functinoality lost, and a slight perf increase!
-* Change the bash completion script code generation to support hyphens.
+* Change the bash completion script code generation to support hyphens.
* Fix completion of long option values in ZSH completions
* Fixes broken links in docs
* Updates contributors list
-* Fixes the ripgrep benchmark by adding a value to a flag that expects it
+* Fixes the ripgrep benchmark by adding a value to a flag that expects it
Here's whats new in 2.29.0:
diff --git a/src/app/parser.rs b/src/app/parser.rs
index 96d4493e959..29c624d4595 100644
--- a/src/app/parser.rs
+++ b/src/app/parser.rs
@@ -251,6 +251,7 @@ where
fn add_reqs(&mut self, a: &Arg<'a, 'b>) {
if a.is_set(ArgSettings::Required) {
// If the arg is required, add all it's requirements to master required list
+ self.required.push(a.b.name);
if let Some(ref areqs) = a.b.requires {
for name in areqs
.iter()
@@ -260,7 +261,6 @@ where
self.required.push(name);
}
}
- self.required.push(a.b.name);
}
}
@@ -909,9 +909,15 @@ where
}
if starts_new_arg {
+ let check_all = self.is_set(AS::AllArgsOverrideSelf);
{
let any_arg = find_any_by_name!(self, self.cache.unwrap_or(""));
- matcher.process_arg_overrides(any_arg, &mut self.overrides, &mut self.required);
+ matcher.process_arg_overrides(
+ any_arg,
+ &mut self.overrides,
+ &mut self.required,
+ check_all
+ );
}
if arg_os.starts_with(b"--") {
@@ -1039,9 +1045,15 @@ where
self.settings.set(AS::TrailingValues);
}
if self.cache.map_or(true, |name| name != p.b.name) {
+ let check_all = self.is_set(AS::AllArgsOverrideSelf);
{
let any_arg = find_any_by_name!(self, self.cache.unwrap_or(""));
- matcher.process_arg_overrides(any_arg, &mut self.overrides, &mut self.required);
+ matcher.process_arg_overrides(
+ any_arg,
+ &mut self.overrides,
+ &mut self.required,
+ check_all
+ );
}
self.cache = Some(p.b.name);
}
@@ -1157,9 +1169,15 @@ where
}
// In case the last arg was new, we need to process it's overrides
+ let check_all = self.is_set(AS::AllArgsOverrideSelf);
{
let any_arg = find_any_by_name!(self, self.cache.unwrap_or(""));
- matcher.process_arg_overrides(any_arg, &mut self.overrides, &mut self.required);
+ matcher.process_arg_overrides(
+ any_arg,
+ &mut self.overrides,
+ &mut self.required,
+ check_all
+ );
}
self.remove_overrides(matcher);
diff --git a/src/app/settings.rs b/src/app/settings.rs
index 1b304225ab3..840d77585c5 100644
--- a/src/app/settings.rs
+++ b/src/app/settings.rs
@@ -46,6 +46,7 @@ bitflags! {
const VALID_ARG_FOUND = 1 << 37;
const INFER_SUBCOMMANDS = 1 << 38;
const CONTAINS_LAST = 1 << 39;
+ const ARGS_OVERRIDE_SELF = 1 << 40;
}
}
@@ -75,6 +76,7 @@ impl AppFlags {
impl_settings! { AppSettings,
ArgRequiredElseHelp => Flags::A_REQUIRED_ELSE_HELP,
ArgsNegateSubcommands => Flags::ARGS_NEGATE_SCS,
+ AllArgsOverrideSelf => Flags::ARGS_OVERRIDE_SELF,
AllowExternalSubcommands => Flags::ALLOW_UNK_SC,
AllowInvalidUtf8 => Flags::UTF8_NONE,
AllowLeadingHyphen => Flags::LEADING_HYPHEN,
@@ -165,6 +167,13 @@ pub enum AppSettings {
/// [`ArgMatches::lossy_values_of`]: ./struct.ArgMatches.html#method.lossy_values_of
AllowInvalidUtf8,
+ /// Essentially sets [`Arg::overrides_with("itself")`] for all arguments.
+ ///
+ /// **WARNING:** Positional arguments cannot override themselves (or we would never be able
+ /// to advance to the next positional). This setting ignores positional arguments.
+ /// [`Arg::overrides_with("itself")`]: ./struct.Arg.html#method.overrides_with
+ AllArgsOverrideSelf,
+
/// Specifies that leading hyphens are allowed in argument *values*, such as negative numbers
/// like `-10`. (which would otherwise be parsed as another flag or option)
///
diff --git a/src/app/validator.rs b/src/app/validator.rs
index 9751321a149..448a8fc7edb 100644
--- a/src/app/validator.rs
+++ b/src/app/validator.rs
@@ -36,11 +36,14 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
self.0.add_defaults(matcher)?;
if let ParseResult::Opt(a) = needs_val_of {
debugln!("Validator::validate: needs_val_of={:?}", a);
- let o = self.0
+ let o = {
+ self.0
.opts
.iter()
.find(|o| o.b.name == a)
- .expect(INTERNAL_ERROR_MSG);
+ .expect(INTERNAL_ERROR_MSG)
+ .clone()
+ };
self.validate_required(matcher)?;
reqs_validated = true;
let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) {
@@ -50,7 +53,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
};
if should_err {
return Err(Error::empty_value(
- o,
+ &o,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
));
@@ -336,7 +339,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
where
A: AnyArg<'a, 'b> + Display,
{
- debugln!("Validator::validate_arg_num_vals;");
+ debugln!("Validator::validate_arg_num_vals:{}", a.name());
if let Some(num) = a.num_vals() {
debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num);
let should_err = if a.is_set(ArgSettings::Multiple) {
@@ -438,20 +441,46 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
Ok(())
}
- fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> {
+ fn validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()> {
debugln!(
"Validator::validate_required: required={:?};",
self.0.required
);
- 'outer: for name in &self.0.required {
+ let mut should_err = false;
+ let mut to_rem = Vec::new();
+ for name in &self.0.required {
debugln!("Validator::validate_required:iter:{}:", name);
if matcher.contains(name) {
- continue 'outer;
+ continue;
}
- if let Some(a) = find_any_by_name!(self.0, *name) {
+ if to_rem.contains(name) {
+ continue;
+ } else if let Some(a) = find_any_by_name!(self.0, *name) {
if self.is_missing_required_ok(a, matcher) {
- continue 'outer;
+ to_rem.push(a.name());
+ if let Some(reqs) = a.requires() {
+ for r in reqs
+ .iter()
+ .filter(|&&(val, _)| val.is_none())
+ .map(|&(_, name)| name)
+ {
+ to_rem.push(r);
+ }
+ }
+ continue;
+ }
+ }
+ should_err = true;
+ break;
+ }
+ if should_err {
+ for r in &to_rem {
+ 'inner: for i in (0 .. self.0.required.len()).rev() {
+ if &self.0.required[i] == r {
+ self.0.required.swap_remove(i);
+ break 'inner;
+ }
}
}
return self.missing_required_error(matcher, None);
diff --git a/src/args/arg.rs b/src/args/arg.rs
index bdcd63a5ec4..6cbf3a76612 100644
--- a/src/args/arg.rs
+++ b/src/args/arg.rs
@@ -1203,6 +1203,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// **NOTE:** When an argument is overridden it is essentially as if it never was used, any
/// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed
///
+ /// **WARNING:** Positional arguments cannot override themselves (or we would never be able
+ /// to advance to the next positional). If a positional agument lists itself as an override,
+ /// it is simply ignored.
+ ///
/// # Examples
///
/// ```rust
@@ -1222,6 +1226,74 @@ impl<'a, 'b> Arg<'a, 'b> {
/// // was never used because it was overridden with color
/// assert!(!m.is_present("flag"));
/// ```
+ /// Care must be taken when using this setting, and having an arg override with itself. This
+ /// is common practice when supporting things like shell aliases, config files, etc.
+ /// However, when combined with multiple values, it can get dicy.
+ /// Here is how clap handles such situations:
+ ///
+ /// When a flag overrides itself, it's as if the flag was only ever used once (essentially
+ /// preventing a "Unexpected multiple usage" error):
+ ///
+ /// ```rust
+ /// # use clap::{App, Arg};
+ /// let m = App::new("posix")
+ /// .arg(Arg::from_usage("--flag 'some flag'").overrides_with("flag"))
+ /// .get_matches_from(vec!["posix", "--flag", "--flag"]);
+ /// assert!(m.is_present("flag"));
+ /// assert_eq!(m.occurrences_of("flag"), 1);
+ /// ```
+ /// Making a flag `multiple(true)` and override itself is essentially meaningless. Therefore
+ /// clap ignores an override of self if it's a flag and it already accepts multiple occurrences.
+ ///
+ /// ```
+ /// # use clap::{App, Arg};
+ /// let m = App::new("posix")
+ /// .arg(Arg::from_usage("--flag... 'some flag'").overrides_with("flag"))
+ /// .get_matches_from(vec!["", "--flag", "--flag", "--flag", "--flag"]);
+ /// assert!(m.is_present("flag"));
+ /// assert_eq!(m.occurrences_of("flag"), 4);
+ /// ```
+ /// Now notice with options, it's as if only the last occurrence mattered
+ ///
+ /// ```
+ /// # use clap::{App, Arg};
+ /// let m = App::new("posix")
+ /// .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("opt"))
+ /// .get_matches_from(vec!["", "--opt=some", "--opt=other"]);
+ /// assert!(m.is_present("opt"));
+ /// assert_eq!(m.occurrences_of("opt"), 1);
+ /// assert_eq!(m.value_of("opt"), Some("other"));
+ /// ```
+ ///
+ /// Here is where it gets interesting. If an option is declared as `multiple(true)` and it also
+ /// overrides with itself, only the last *set* of values will be saved.
+ ///
+ /// ```
+ /// # use clap::{App, Arg};
+ /// let m = App::new("posix")
+ /// .arg(Arg::from_usage("--opt [val]... 'some option'")
+ /// .overrides_with("opt"))
+ /// .get_matches_from(vec!["", "--opt", "first", "over", "--opt", "other", "val"]);
+ /// assert!(m.is_present("opt"));
+ /// assert_eq!(m.occurrences_of("opt"), 1);
+ /// assert_eq!(m.values_of("opt").unwrap().collect::>(), &["other", "val"]);
+ /// ```
+ ///
+ /// A safe thing to do, to ensure there is no confusion is to require an argument delimiter and
+ /// and only one "value set" per instance of the option.
+ ///
+ /// ```
+ /// # use clap::{App, Arg};
+ /// let m = App::new("posix")
+ /// .arg(Arg::from_usage("--opt [val]... 'some option'")
+ /// .overrides_with("opt")
+ /// .number_of_values(1)
+ /// .require_delimiter(true))
+ /// .get_matches_from(vec!["", "--opt=some,other", "--opt=one,two"]);
+ /// assert!(m.is_present("opt"));
+ /// assert_eq!(m.occurrences_of("opt"), 1);
+ /// assert_eq!(m.values_of("opt").unwrap().collect::>(), &["one", "two"]);
+ /// ```
pub fn overrides_with(mut self, name: &'a str) -> Self {
if let Some(ref mut vec) = self.b.overrides {
vec.push(name.as_ref());
diff --git a/src/args/arg_matcher.rs b/src/args/arg_matcher.rs
index 25f3fc5d749..16ea79b1312 100644
--- a/src/args/arg_matcher.rs
+++ b/src/args/arg_matcher.rs
@@ -21,13 +21,17 @@ impl<'a> Default for ArgMatcher<'a> {
impl<'a> ArgMatcher<'a> {
pub fn new() -> Self { ArgMatcher::default() }
- pub fn process_arg_overrides<'b>(&mut self, a: Option<&AnyArg<'a, 'b>>, overrides: &mut Vec<(&'b str, &'a str)>, required: &mut Vec<&'a str>) {
+ pub fn process_arg_overrides<'b>(&mut self, a: Option<&AnyArg<'a, 'b>>, overrides: &mut Vec<(&'b str, &'a str)>, required: &mut Vec<&'a str>, check_all: bool) {
debugln!("ArgMatcher::process_arg_overrides:{:?};", a.map_or(None, |a| Some(a.name())));
if let Some(aa) = a {
+ let mut self_done = false;
if let Some(a_overrides) = aa.overrides() {
for overr in a_overrides {
debugln!("ArgMatcher::process_arg_overrides:iter:{};", overr);
- if self.is_present(overr) {
+ if overr == &aa.name() {
+ self_done = true;
+ self.handle_self_overrides(a);
+ } else if self.is_present(overr) {
debugln!("ArgMatcher::process_arg_overrides:iter:{}: removing from matches;", overr);
self.remove(overr);
for i in (0 .. required.len()).rev() {
@@ -37,11 +41,38 @@ impl<'a> ArgMatcher<'a> {
break;
}
}
+ overrides.push((overr, aa.name()));
} else {
overrides.push((overr, aa.name()));
}
}
}
+ if check_all && !self_done {
+ self.handle_self_overrides(a);
+ }
+ }
+ }
+
+ pub fn handle_self_overrides<'b>(&mut self, a: Option<&AnyArg<'a, 'b>>) {
+ debugln!("ArgMatcher::handle_self_overrides:{:?};", a.map_or(None, |a| Some(a.name())));
+ if let Some(aa) = a {
+ if !aa.has_switch() || (!aa.takes_value() && aa.is_set(ArgSettings::Multiple)) {
+ // positional args can't override self or else we would never advance to the next
+
+ // Also flags with --multiple set are ignored otherwise we could never have more
+ // than one
+ return;
+ }
+ if let Some(ma) = self.get_mut(aa.name()) {
+ if ma.vals.len() > 1 {
+ // swap_remove(0) would be O(1) but does not preserve order, which
+ // we need
+ ma.vals.remove(0);
+ ma.occurs = 1;
+ } else if !aa.takes_value() && ma.occurs > 1 {
+ ma.occurs = 1;
+ }
+ }
}
}
@@ -143,7 +174,6 @@ impl<'a> ArgMatcher<'a> {
occurs: 0,
vals: Vec::with_capacity(1),
});
- // let len = ma.vals.len() + 1;
ma.vals.push(val.to_owned());
}
diff --git a/src/lib.rs b/src/lib.rs
index 128bd443231..3651344ec4e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -513,7 +513,7 @@
//! this repository for more information.
#![crate_type = "lib"]
-#![doc(html_root_url = "https://docs.rs/clap/2.29.2")]
+#![doc(html_root_url = "https://docs.rs/clap/2.29.3")]
#![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
diff --git a/tests/app_settings.rs b/tests/app_settings.rs
index 258ebd7025a..cbba0f060ba 100644
--- a/tests/app_settings.rs
+++ b/tests/app_settings.rs
@@ -668,4 +668,150 @@ fn issue_1093_allow_ext_sc() {
.version("v1.4.8")
.setting(AppSettings::AllowExternalSubcommands);
assert!(test::compare_output(app, "clap-test --help", ALLOW_EXT_SC, false));
+}
+
+#[test]
+fn aaos_flags() {
+ // flags
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--flag 'some flag'"))
+ .get_matches_from_safe(vec!["", "--flag", "--flag"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 1);
+}
+
+#[test]
+fn aaos_flags_mult() {
+ // flags with multiple
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--flag... 'some flag'"))
+ .get_matches_from_safe(vec!["", "--flag", "--flag", "--flag", "--flag"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 4);
+}
+
+#[test]
+fn aaos_opts() {
+ // opts
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val] 'some option'"))
+ .get_matches_from_safe(vec!["", "--opt=some", "--opt=other"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.value_of("opt"), Some("other"));
+}
+
+#[test]
+fn aaos_opts_w_other_overrides() {
+ // opts with other overrides
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val] 'some option'"))
+ .arg(Arg::from_usage("--other [val] 'some other option'").overrides_with("opt"))
+ .get_matches_from_safe(vec!["", "--opt=some", "--other=test", "--opt=other"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert!(!m.is_present("other"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.value_of("opt"), Some("other"));
+}
+
+#[test]
+fn aaos_opts_w_other_overrides_rev() {
+ // opts with other overrides, rev
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val] 'some option'"))
+ .arg(Arg::from_usage("--other [val] 'some other option'").overrides_with("opt"))
+ .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--other=val"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(!m.is_present("opt"));
+ assert!(m.is_present("other"));
+ assert_eq!(m.value_of("other"), Some("val"));
+}
+
+#[test]
+fn aaos_opts_w_other_overrides_2() {
+ // opts with other overrides
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("other"))
+ .arg(Arg::from_usage("--other [val] 'some other option'"))
+ .get_matches_from_safe(vec!["", "--opt=some", "--other=test", "--opt=other"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert!(!m.is_present("other"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.value_of("opt"), Some("other"));
+}
+
+#[test]
+fn aaos_opts_w_other_overrides_rev_2() {
+ // opts with other overrides, rev
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("other"))
+ .arg(Arg::from_usage("--other [val] 'some other option'"))
+ .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--other=val"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(!m.is_present("opt"));
+ assert!(m.is_present("other"));
+ assert_eq!(m.value_of("other"), Some("val"));
+}
+
+#[test]
+fn aaos_opts_mult() {
+ // opts with multiple
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val]... 'some option'")
+ .number_of_values(1)
+ .require_delimiter(true))
+ .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.values_of("opt").unwrap().collect::>(), &["one", "two"]);
+}
+
+#[test]
+fn aaos_opts_mult_req_delims() {
+ // opts with multiple and require delims
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("--opt [val]... 'some option'"))
+ .get_matches_from_safe(vec!["", "--opt", "first", "overides", "--opt", "some", "other", "val"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.values_of("opt").unwrap().collect::>(), &["some", "other", "val"]);
+}
+
+#[test]
+fn aaos_pos_mult() {
+ // opts with multiple
+ let res = App::new("posix")
+ .setting(AppSettings::AllArgsOverrideSelf)
+ .arg(Arg::from_usage("[val]... 'some pos'"))
+ .get_matches_from_safe(vec!["", "some", "other", "value"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("val"));
+ assert_eq!(m.occurrences_of("val"), 3);
+ assert_eq!(m.values_of("val").unwrap().collect::>(), &["some", "other", "value"]);
}
\ No newline at end of file
diff --git a/tests/posix_compatible.rs b/tests/posix_compatible.rs
index 83f14481239..0a790c2cb87 100644
--- a/tests/posix_compatible.rs
+++ b/tests/posix_compatible.rs
@@ -2,6 +2,81 @@ extern crate clap;
use clap::{App, Arg, ErrorKind};
+#[test]
+fn flag_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--flag 'some flag'").overrides_with("flag"))
+ .get_matches_from_safe(vec!["", "--flag", "--flag"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 1);
+}
+
+#[test]
+fn mult_flag_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--flag... 'some flag'").overrides_with("flag"))
+ .get_matches_from_safe(vec!["", "--flag", "--flag", "--flag", "--flag"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 4);
+}
+
+#[test]
+fn option_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("opt"))
+ .get_matches_from_safe(vec!["", "--opt=some", "--opt=other"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.value_of("opt"), Some("other"));
+}
+
+#[test]
+fn mult_option_require_delim_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--opt [val]... 'some option'")
+ .overrides_with("opt")
+ .number_of_values(1)
+ .require_delimiter(true))
+ .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.values_of("opt").unwrap().collect::>(), &["one", "two"]);
+}
+
+#[test]
+fn mult_option_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--opt [val]... 'some option'")
+ .overrides_with("opt"))
+ .get_matches_from_safe(vec!["", "--opt", "first", "overides", "--opt", "some", "other", "val"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.occurrences_of("opt"), 1);
+ assert_eq!(m.values_of("opt").unwrap().collect::>(), &["some", "other", "val"]);
+}
+
+#[test]
+fn aaos_pos_mult() {
+ // opts with multiple
+ let res = App::new("posix")
+ .arg(Arg::from_usage("[val]... 'some pos'").overrides_with("val"))
+ .get_matches_from_safe(vec!["", "some", "other", "value"]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("val"));
+ assert_eq!(m.occurrences_of("val"), 3);
+ assert_eq!(m.values_of("val").unwrap().collect::>(), &["some", "other", "value"]);
+}
+
#[test]
fn posix_compatible_flags_long() {
let m = App::new("posix")
diff --git a/tests/require.rs b/tests/require.rs
index 5dbf2dc17ed..a0a658eaa57 100644
--- a/tests/require.rs
+++ b/tests/require.rs
@@ -30,6 +30,51 @@ USAGE:
For more information try --help";
+static ISSUE_1158: &'static str = "error: The following required arguments were not provided:
+ -x
+ -y
+ -z
+
+USAGE:
+ example [OPTIONS] -x -y -z
+
+For more information try --help";
+
+#[test]
+fn issue_1158_conflicting_requirements() {
+ let app = App::new("example")
+ .arg(Arg::from_usage("-c, --config [FILE] 'Custom config file.'")
+ .required_unless("ID")
+ .conflicts_with("ID"))
+ .arg(Arg::from_usage("[ID] 'ID'")
+ .required_unless("config")
+ .conflicts_with("config")
+ .requires_all(&["x", "y", "z"]))
+ .arg(Arg::from_usage("-x [X] 'X'"))
+ .arg(Arg::from_usage("-y [Y] 'Y'"))
+ .arg(Arg::from_usage("-z [Z] 'Z'"));
+
+ assert!(test::compare_output(app, "example id", ISSUE_1158, true));
+}
+
+#[test]
+fn issue_1158_conflicting_requirements_rev() {
+ let res = App::new("example")
+ .arg(Arg::from_usage("-c, --config [FILE] 'Custom config file.'")
+ .required_unless("ID")
+ .conflicts_with("ID"))
+ .arg(Arg::from_usage("[ID] 'ID'")
+ .required_unless("config")
+ .conflicts_with("config")
+ .requires_all(&["x", "y", "z"]))
+ .arg(Arg::from_usage("-x [X] 'X'"))
+ .arg(Arg::from_usage("-y [Y] 'Y'"))
+ .arg(Arg::from_usage("-z [Z] 'Z'"))
+ .get_matches_from_safe(vec!["example", "--config", "some"]);
+
+ assert!(res.is_ok());
+}
+
#[test]
fn flag_required() {
let result = App::new("flag_required")