Skip to content
This repository was archived by the owner on Nov 9, 2022. It is now read-only.

Commit 031df5d

Browse files
committed
Auto merge of clap-rs#809 - kbknapp:issue-636, r=kbknapp
Issue 636
2 parents ce08391 + 9d88f19 commit 031df5d

File tree

7 files changed

+231
-59
lines changed

7 files changed

+231
-59
lines changed

CHANGELOG.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,57 @@
1+
<a name="v2.20.0"></a>
2+
3+
#### New Settings
4+
5+
* **ArgsNegateSubcommands:** disables args being allowed between subcommands ([5e2af8c9](https://github.com/kbknapp/clap-rs/commit/5e2af8c96adb5ab75fa2d1536237ebcb41869494), closes [#793](https://github.com/kbknapp/clap-rs/issues/793))
6+
* **DontCollapseArgsInUsage:** disables the collapsing of positional args into `[ARGS]` in the usage string ([c2978afc](https://github.com/kbknapp/clap-rs/commit/c2978afc61fb46d5263ab3b2d87ecde1c9ce1553), closes [#769](https://github.com/kbknapp/clap-rs/issues/769))
7+
* **DisableHelpSubcommand:** disables building the `help` subcommand ([a10fc859](https://github.com/kbknapp/clap-rs/commit/a10fc859ee20159fbd9ff4337be59b76467a64f2))
8+
* **AllowMissingPositional:** allows one to implement `$ prog [optional] <required>` style CLIs where the second postional argument is required, but the first is optional ([1110fdc7](https://github.com/kbknapp/clap-rs/commit/1110fdc7a345c108820dc45783a9bf893fa4c214), closes [#636](https://github.com/kbknapp/clap-rs/issues/636))
9+
* **PropagateGlobalValuesDown:** automatically propagats global arg's values down through *used* subcommands ([985536c8](https://github.com/kbknapp/clap-rs/commit/985536c8ebcc09af98aac835f42a8072ad58c262), closes [#694](https://github.com/kbknapp/clap-rs/issues/694))
10+
11+
#### API Additions
12+
13+
##### Arg
14+
15+
* **Arg::value_terminator:** adds the ability to terminate multiple values with a given string or char ([be64ce0c](https://github.com/kbknapp/clap-rs/commit/be64ce0c373efc106384baca3f487ea99fe7b8cf), closes [#782](https://github.com/kbknapp/clap-rs/issues/782))
16+
* **Arg::default_value_if[s]:** adds new methods for *conditional* default values (such as a particular value from another argument was used) ([eb4010e7](https://github.com/kbknapp/clap-rs/commit/eb4010e7b21724447ef837db11ac441915728f22))
17+
* **Arg::requires_if[s]:** adds the ability to *conditionally* require additional args (such as if a particular value was used) ([198449d6](https://github.com/kbknapp/clap-rs/commit/198449d64393c265f0bc327aaeac23ec4bb97226))
18+
* **Arg::required_if[s]:** adds the ability for an arg to be *conditionally* required (i.e. "arg X is only required if arg Y was used with value Z") ([ee9cfddf](https://github.com/kbknapp/clap-rs/commit/ee9cfddf345a6b5ae2af42ba72aa5c89e2ca7f59))
19+
* **Arg::validator_os:** adds ability to validate values which may contain invalid UTF-8 ([47232498](https://github.com/kbknapp/clap-rs/commit/47232498a813db4f3366ccd3e9faf0bff56433a4))
20+
21+
##### Macros
22+
23+
* **crate_description!:** Uses the `Cargo.toml` description field to fill in the `App::about` method at compile time ([4d9a82db](https://github.com/kbknapp/clap-rs/commit/4d9a82db8e875e9b64a9c2a5c6e22c25afc1279d), closes [#778](https://github.com/kbknapp/clap-rs/issues/778))
24+
* **crate_name!:** Uses the `Cargo.toml` name field to fill in the `App::new` method at compile time ([4d9a82db](https://github.com/kbknapp/clap-rs/commit/4d9a82db8e875e9b64a9c2a5c6e22c25afc1279d), closes [#778](https://github.com/kbknapp/clap-rs/issues/778))
25+
* **app_from_crate!:** Combines `crate_version!`, `crate_name!`, `crate_description!`, and `crate_authors!` into a single macro call to build a default `App` instance from the `Cargo.toml` fields ([4d9a82db](https://github.com/kbknapp/clap-rs/commit/4d9a82db8e875e9b64a9c2a5c6e22c25afc1279d), closes [#778](https://github.com/kbknapp/clap-rs/issues/778))
26+
27+
28+
#### Features
29+
30+
* **no_cargo:** adds a `no_cargo` feature to disable Cargo-env-var-dependent macros for those *not* using `cargo` to build their crates (#786) ([6fdd2f9d](https://github.com/kbknapp/clap-rs/commit/6fdd2f9d693aaf1118fc61bd362273950703f43d))
31+
32+
#### Bug Fixes
33+
34+
* **Options:** fixes a critical bug where options weren't forced to have a value ([5a5f2b1e](https://github.com/kbknapp/clap-rs/commit/5a5f2b1e9f598a0d0280ef3e98abbbba2bc41132), closes [#665](https://github.com/kbknapp/clap-rs/issues/665))
35+
* fixes a bug where calling the help of a subcommand wasn't ignoring required args of parent commands ([d3d34a2b](https://github.com/kbknapp/clap-rs/commit/d3d34a2b51ef31004055b0ab574f766d801c3adf), closes [#789](https://github.com/kbknapp/clap-rs/issues/789))
36+
* **Help Subcommand:** fixes a bug where the help subcommand couldn't be overriden ([d34ec3e0](https://github.com/kbknapp/clap-rs/commit/d34ec3e032d03e402d8e87af9b2942fe2819b2da), closes [#787](https://github.com/kbknapp/clap-rs/issues/787))
37+
* **Low Index Multiples:** fixes a bug which caused combinations of LowIndexMultiples and `Arg::allow_hyphen_values` to fail parsing ([26c670ca](https://github.com/kbknapp/clap-rs/commit/26c670ca16d2c80dc26d5c1ce83380ace6357318))
38+
39+
#### Improvements
40+
41+
* **Default Values:** improves the error message when default values are involved ([1f33de54](https://github.com/kbknapp/clap-rs/commit/1f33de545036e7fd2f80faba251fca009bd519b8), closes [#774](https://github.com/kbknapp/clap-rs/issues/774))
42+
* **YAML:** adds conditional requirements and conditional default values to YAML ([9a4df327](https://github.com/kbknapp/clap-rs/commit/9a4df327893486adb5558ffefba790c634ccdc6e), closes [#764](https://github.com/kbknapp/clap-rs/issues/764))
43+
* Support `--("some-arg-name")` syntax for defining long arg names when using `clap_app!` macro ([f41ec962](https://github.com/kbknapp/clap-rs/commit/f41ec962c243a5ffff8b1be1ae2ad63970d3d1d4))
44+
* Support `("some app name")` syntax for defining app names when using `clap_app!` macro ([9895b671](https://github.com/kbknapp/clap-rs/commit/9895b671cff784f35cf56abcd8270f7c2ba09699), closes [#759](https://github.com/kbknapp/clap-rs/issues/759))
45+
* **Help Wrapping:** long app names (with spaces), authors, and descriptions are now wrapped appropriately ([ad4691b7](https://github.com/kbknapp/clap-rs/commit/ad4691b71a63e951ace346318238d8834e04ad8a), closes [#777](https://github.com/kbknapp/clap-rs/issues/777))
46+
47+
48+
#### Documentation
49+
50+
* **Conditional Default Values:** fixes the failing doc tests of Arg::default_value_ifs ([4ef09101](https://github.com/kbknapp/clap-rs/commit/4ef091019c083b4db1a0c13f1c1e95ac363259f2))
51+
* **Conditional Requirements:** adds docs for Arg::requires_ifs ([7f296e29](https://github.com/kbknapp/clap-rs/commit/7f296e29db7d9036e76e5dbcc9c8b20dfe7b25bd))
52+
* **README.md:** fix some typos ([f22c21b4](https://github.com/kbknapp/clap-rs/commit/f22c21b422d5b287d1a1ac183a379ee02eebf54f))
53+
* **src/app/mod.rs:** fix some typos ([5c9b0d47](https://github.com/kbknapp/clap-rs/commit/5c9b0d47ca78dea285c5b9dec79063d24c3e451a))
54+
155
<a name="v2.19.3"></a>
256
### v2.19.3 (2016-12-28)
357

README.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,37 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
4545

4646
## What's New
4747

48-
Here's the highlights for v2.19.3
48+
Here's the highlights for v2.20.0
49+
50+
* **ArgsNegateSubcommands:** disables args being allowed between subcommands
51+
* **DontCollapseArgsInUsage:** disables the collapsing of positional args into `[ARGS]` in the usage string
52+
* **DisableHelpSubcommand:** disables building the `help` subcommand
53+
* **AllowMissingPositional:** allows one to implement `$ prog [optional] <required>` style CLIs where the second postional argument is required, but the first is optional
54+
* **PropagateGlobalValuesDown:** automatically propagats global arg's values down through *used* subcommands
55+
* **Arg::value_terminator:** adds the ability to terminate multiple values with a given string or char
56+
* **Arg::default_value_if[s]:** adds new methods for *conditional* default values (such as a particular value from another argument was used)
57+
* **Arg::requires_if[s]:** adds the ability to *conditionally* require additional args (such as if a particular value was used)
58+
* **Arg::required_if[s]:** adds the ability for an arg to be *conditionally* required (i.e. "arg X is only required if arg Y was used with value Z")
59+
* **Arg::validator_os:** adds ability to validate values which may contain invalid UTF-8
60+
* **crate_description!:** Uses the `Cargo.toml` description field to fill in the `App::about` method at compile time
61+
* **crate_name!:** Uses the `Cargo.toml` name field to fill in the `App::new` method at compile time
62+
* **app_from_crate!:** Combines `crate_version!`, `crate_name!`, `crate_description!`, and `crate_authors!` into a single macro call to build a default `App` instance from the `Cargo.toml` fields
63+
* **no_cargo:** adds a `no_cargo` feature to disable Cargo-env-var-dependent macros for those *not* using `cargo` to build their crates
64+
* **Options:** fixes a critical bug where options weren't forced to have a value
65+
* fixes a bug where calling the help of a subcommand wasn't ignoring required args of parent commands
66+
* **Help Subcommand:** fixes a bug where the help subcommand couldn't be overriden
67+
* **Low Index Multiples:** fixes a bug which caused combinations of LowIndexMultiples and `Arg::allow_hyphen_values` to fail parsing
68+
* **Default Values:** improves the error message when default values are involved
69+
* **YAML:** adds conditional requirements and conditional default values to YAML
70+
* Support `--("some-arg-name")` syntax for defining long arg names when using `clap_app!` macro
71+
* Support `("some app name")` syntax for defining app names when using `clap_app!` macro
72+
* **Help Wrapping:** long app names (with spaces), authors, and descriptions are now wrapped appropriately
73+
* **Conditional Default Values:** fixes the failing doc tests of Arg::default_value_ifs
74+
* **Conditional Requirements:** adds docs for Arg::requires_ifs
75+
76+
Here's the highlights from v2.0.0 to v2.19.3
4977

5078
* Fixes a bug where calling the help of a subcommand wasn't ignoring required args of parent commands
51-
52-
Here's the highlights from v2.0.0 to v2.19.2
53-
5479
* Fixes a bug by escaping square brackets in ZSH completions which were causing conflicts and errors.
5580
* **Bash Completion:** allows bash completion to fall back to traidtional bash completion upon no matching completing function
5681
* **Arg Setting**: Allows specifying an `AllowLeadingHyphen` style setting for values only for specific args, vice command wide

src/app/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,14 +1028,16 @@ impl<'a, 'b> App<'a, 'b> {
10281028
/// app.write_help(&mut out).expect("failed to write to stdout");
10291029
/// ```
10301030
/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
1031-
pub fn write_help<W: Write>(&mut self, w: &mut W) -> ClapResult<()> {
1031+
pub fn write_help<W: Write>(&self, w: &mut W) -> ClapResult<()> {
1032+
// PENDING ISSUE: 808
1033+
// https://github.com/kbknapp/clap-rs/issues/808
10321034
// If there are global arguments, or settings we need to propgate them down to subcommands
10331035
// before parsing incase we run into a subcommand
1034-
self.p.propogate_globals();
1035-
self.p.propogate_settings();
1036-
self.p.derive_display_order();
1036+
// self.p.propogate_globals();
1037+
// self.p.propogate_settings();
1038+
// self.p.derive_display_order();
1039+
// self.p.create_help_and_version();
10371040

1038-
self.p.create_help_and_version();
10391041
Help::write_app_help(w, self)
10401042
}
10411043

src/app/parser.rs

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -546,10 +546,6 @@ impl<'a, 'b> Parser<'a, 'b>
546546
a.b.settings.is_set(ArgSettings::Multiple) &&
547547
(a.index as usize != self.positionals.len())
548548
}) {
549-
debug_assert!(self.positionals.values()
550-
.filter(|p| p.b.settings.is_set(ArgSettings::Multiple)
551-
&& p.v.num_vals.is_none()).map(|_| 1).sum::<u64>() <= 1,
552-
"Only one positional argument with .multiple(true) set is allowed per command");
553549

554550
debug_assert!({
555551
let mut it = self.positionals.values().rev();
@@ -581,17 +577,42 @@ impl<'a, 'b> Parser<'a, 'b>
581577

582578
// If it's required we also need to ensure all previous positionals are
583579
// required too
584-
let mut found = false;
585-
for p in self.positionals.values().rev() {
586-
if found {
587-
debug_assert!(p.b.settings.is_set(ArgSettings::Required),
588-
"Found positional argument which is not required with a lower index \
589-
than a required positional argument: {:?} index {}",
590-
p.b.name,
591-
p.index);
592-
} else if p.b.settings.is_set(ArgSettings::Required) {
593-
found = true;
594-
continue;
580+
if self.is_set(AppSettings::AllowMissingPositional) {
581+
let mut found = false;
582+
let mut foundx2 = false;
583+
for p in self.positionals.values().rev() {
584+
if foundx2 && !p.b.settings.is_set(ArgSettings::Required) {
585+
// [arg1] <arg2> is Ok
586+
// [arg1] <arg2> <arg3> Is not
587+
debug_assert!(p.b.settings.is_set(ArgSettings::Required),
588+
"Found positional argument which is not required with a lower index \
589+
than a required positional argument by two or more: {:?} index {}",
590+
p.b.name,
591+
p.index);
592+
} else if p.b.settings.is_set(ArgSettings::Required) {
593+
if found {
594+
foundx2 = true;
595+
continue;
596+
}
597+
found = true;
598+
continue;
599+
} else {
600+
found = false;
601+
}
602+
}
603+
} else {
604+
let mut found = false;
605+
for p in self.positionals.values().rev() {
606+
if found {
607+
debug_assert!(p.b.settings.is_set(ArgSettings::Required),
608+
"Found positional argument which is not required with a lower index \
609+
than a required positional argument: {:?} index {}",
610+
p.b.name,
611+
p.index);
612+
} else if p.b.settings.is_set(ArgSettings::Required) {
613+
found = true;
614+
continue;
615+
}
595616
}
596617
}
597618
}
@@ -861,12 +882,15 @@ impl<'a, 'b> Parser<'a, 'b>
861882
let low_index_mults = self.is_set(AppSettings::LowIndexMultiplePositional) &&
862883
!self.positionals.is_empty() &&
863884
pos_counter == (self.positionals.len() - 1);
885+
let missing_pos = self.is_set(AppSettings::AllowMissingPositional) &&
886+
!self.positionals.is_empty() &&
887+
pos_counter == (self.positionals.len() - 1);
864888
debugln!("Parser::get_matches_with: Low index multiples...{:?}", low_index_mults);
865889
debugln!("Parser::get_matches_with: Positional counter...{}", pos_counter);
866-
if low_index_mults {
890+
if low_index_mults || missing_pos {
867891
if let Some(na) = it.peek() {
868892
let n = (*na).clone().into();
869-
needs_val_of = if let None = needs_val_of {
893+
needs_val_of = if needs_val_of.is_none() {
870894
if let Some(p) = self.positionals.get(pos_counter) {
871895
Some(p.b.name)
872896
} else {

0 commit comments

Comments
 (0)