mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
setting(AllowMissingPositional): allows one to implement $ prog [optional] <required>
Closes #636
This commit is contained in:
parent
ce083919be
commit
6edde30b8e
2 changed files with 109 additions and 50 deletions
|
@ -546,10 +546,6 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
a.b.settings.is_set(ArgSettings::Multiple) &&
|
||||
(a.index as usize != self.positionals.len())
|
||||
}) {
|
||||
debug_assert!(self.positionals.values()
|
||||
.filter(|p| p.b.settings.is_set(ArgSettings::Multiple)
|
||||
&& p.v.num_vals.is_none()).map(|_| 1).sum::<u64>() <= 1,
|
||||
"Only one positional argument with .multiple(true) set is allowed per command");
|
||||
|
||||
debug_assert!({
|
||||
let mut it = self.positionals.values().rev();
|
||||
|
@ -581,17 +577,42 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
|
||||
// If it's required we also need to ensure all previous positionals are
|
||||
// required too
|
||||
let mut found = false;
|
||||
for p in self.positionals.values().rev() {
|
||||
if found {
|
||||
debug_assert!(p.b.settings.is_set(ArgSettings::Required),
|
||||
"Found positional argument which is not required with a lower index \
|
||||
than a required positional argument: {:?} index {}",
|
||||
p.b.name,
|
||||
p.index);
|
||||
} else if p.b.settings.is_set(ArgSettings::Required) {
|
||||
found = true;
|
||||
continue;
|
||||
if self.is_set(AppSettings::AllowMissingPositional) {
|
||||
let mut found = false;
|
||||
let mut foundx2 = false;
|
||||
for p in self.positionals.values().rev() {
|
||||
if foundx2 && !p.b.settings.is_set(ArgSettings::Required) {
|
||||
// [arg1] <arg2> is Ok
|
||||
// [arg1] <arg2> <arg3> Is not
|
||||
debug_assert!(p.b.settings.is_set(ArgSettings::Required),
|
||||
"Found positional argument which is not required with a lower index \
|
||||
than a required positional argument by two or more: {:?} index {}",
|
||||
p.b.name,
|
||||
p.index);
|
||||
} else if p.b.settings.is_set(ArgSettings::Required) {
|
||||
if found {
|
||||
foundx2 = true;
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
continue;
|
||||
} else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut found = false;
|
||||
for p in self.positionals.values().rev() {
|
||||
if found {
|
||||
debug_assert!(p.b.settings.is_set(ArgSettings::Required),
|
||||
"Found positional argument which is not required with a lower index \
|
||||
than a required positional argument: {:?} index {}",
|
||||
p.b.name,
|
||||
p.index);
|
||||
} else if p.b.settings.is_set(ArgSettings::Required) {
|
||||
found = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -861,12 +882,15 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let low_index_mults = self.is_set(AppSettings::LowIndexMultiplePositional) &&
|
||||
!self.positionals.is_empty() &&
|
||||
pos_counter == (self.positionals.len() - 1);
|
||||
let missing_pos = self.is_set(AppSettings::AllowMissingPositional) &&
|
||||
!self.positionals.is_empty() &&
|
||||
pos_counter == (self.positionals.len() - 1);
|
||||
debugln!("Parser::get_matches_with: Low index multiples...{:?}", low_index_mults);
|
||||
debugln!("Parser::get_matches_with: Positional counter...{}", pos_counter);
|
||||
if low_index_mults {
|
||||
if low_index_mults || missing_pos {
|
||||
if let Some(na) = it.peek() {
|
||||
let n = (*na).clone().into();
|
||||
needs_val_of = if let None = needs_val_of {
|
||||
needs_val_of = if needs_val_of.is_none() {
|
||||
if let Some(p) = self.positionals.get(pos_counter) {
|
||||
Some(p.b.name)
|
||||
} else {
|
||||
|
|
|
@ -5,39 +5,40 @@ use std::ops::BitOr;
|
|||
|
||||
bitflags! {
|
||||
flags Flags: u64 {
|
||||
const SC_NEGATE_REQS = 0b000000000000000000000000000000001,
|
||||
const SC_REQUIRED = 0b000000000000000000000000000000010,
|
||||
const A_REQUIRED_ELSE_HELP = 0b000000000000000000000000000000100,
|
||||
const GLOBAL_VERSION = 0b000000000000000000000000000001000,
|
||||
const VERSIONLESS_SC = 0b000000000000000000000000000010000,
|
||||
const UNIFIED_HELP = 0b000000000000000000000000000100000,
|
||||
const WAIT_ON_ERROR = 0b000000000000000000000000001000000,
|
||||
const SC_REQUIRED_ELSE_HELP= 0b000000000000000000000000010000000,
|
||||
const NEEDS_LONG_HELP = 0b000000000000000000000000100000000,
|
||||
const NEEDS_LONG_VERSION = 0b000000000000000000000001000000000,
|
||||
const NEEDS_SC_HELP = 0b000000000000000000000010000000000,
|
||||
const DISABLE_VERSION = 0b000000000000000000000100000000000,
|
||||
const HIDDEN = 0b000000000000000000001000000000000,
|
||||
const TRAILING_VARARG = 0b000000000000000000010000000000000,
|
||||
const NO_BIN_NAME = 0b000000000000000000100000000000000,
|
||||
const ALLOW_UNK_SC = 0b000000000000000001000000000000000,
|
||||
const UTF8_STRICT = 0b000000000000000010000000000000000,
|
||||
const UTF8_NONE = 0b000000000000000100000000000000000,
|
||||
const LEADING_HYPHEN = 0b000000000000001000000000000000000,
|
||||
const NO_POS_VALUES = 0b000000000000010000000000000000000,
|
||||
const NEXT_LINE_HELP = 0b000000000000100000000000000000000,
|
||||
const DERIVE_DISP_ORDER = 0b000000000001000000000000000000000,
|
||||
const COLORED_HELP = 0b000000000010000000000000000000000,
|
||||
const COLOR_ALWAYS = 0b000000000100000000000000000000000,
|
||||
const COLOR_AUTO = 0b000000001000000000000000000000000,
|
||||
const COLOR_NEVER = 0b000000010000000000000000000000000,
|
||||
const DONT_DELIM_TRAIL = 0b000000100000000000000000000000000,
|
||||
const ALLOW_NEG_NUMS = 0b000001000000000000000000000000000,
|
||||
const LOW_INDEX_MUL_POS = 0b000010000000000000000000000000000,
|
||||
const DISABLE_HELP_SC = 0b000100000000000000000000000000000,
|
||||
const DONT_COLLAPSE_ARGS = 0b001000000000000000000000000000000,
|
||||
const ARGS_NEGATE_SCS = 0b010000000000000000000000000000000,
|
||||
const PROPAGATE_VALS_DOWN = 0b100000000000000000000000000000000,
|
||||
const SC_NEGATE_REQS = 0b0000000000000000000000000000000001,
|
||||
const SC_REQUIRED = 0b0000000000000000000000000000000010,
|
||||
const A_REQUIRED_ELSE_HELP = 0b0000000000000000000000000000000100,
|
||||
const GLOBAL_VERSION = 0b0000000000000000000000000000001000,
|
||||
const VERSIONLESS_SC = 0b0000000000000000000000000000010000,
|
||||
const UNIFIED_HELP = 0b0000000000000000000000000000100000,
|
||||
const WAIT_ON_ERROR = 0b0000000000000000000000000001000000,
|
||||
const SC_REQUIRED_ELSE_HELP= 0b0000000000000000000000000010000000,
|
||||
const NEEDS_LONG_HELP = 0b0000000000000000000000000100000000,
|
||||
const NEEDS_LONG_VERSION = 0b0000000000000000000000001000000000,
|
||||
const NEEDS_SC_HELP = 0b0000000000000000000000010000000000,
|
||||
const DISABLE_VERSION = 0b0000000000000000000000100000000000,
|
||||
const HIDDEN = 0b0000000000000000000001000000000000,
|
||||
const TRAILING_VARARG = 0b0000000000000000000010000000000000,
|
||||
const NO_BIN_NAME = 0b0000000000000000000100000000000000,
|
||||
const ALLOW_UNK_SC = 0b0000000000000000001000000000000000,
|
||||
const UTF8_STRICT = 0b0000000000000000010000000000000000,
|
||||
const UTF8_NONE = 0b0000000000000000100000000000000000,
|
||||
const LEADING_HYPHEN = 0b0000000000000001000000000000000000,
|
||||
const NO_POS_VALUES = 0b0000000000000010000000000000000000,
|
||||
const NEXT_LINE_HELP = 0b0000000000000100000000000000000000,
|
||||
const DERIVE_DISP_ORDER = 0b0000000000001000000000000000000000,
|
||||
const COLORED_HELP = 0b0000000000010000000000000000000000,
|
||||
const COLOR_ALWAYS = 0b0000000000100000000000000000000000,
|
||||
const COLOR_AUTO = 0b0000000001000000000000000000000000,
|
||||
const COLOR_NEVER = 0b0000000010000000000000000000000000,
|
||||
const DONT_DELIM_TRAIL = 0b0000000100000000000000000000000000,
|
||||
const ALLOW_NEG_NUMS = 0b0000001000000000000000000000000000,
|
||||
const LOW_INDEX_MUL_POS = 0b0000010000000000000000000000000000,
|
||||
const DISABLE_HELP_SC = 0b0000100000000000000000000000000000,
|
||||
const DONT_COLLAPSE_ARGS = 0b0001000000000000000000000000000000,
|
||||
const ARGS_NEGATE_SCS = 0b0010000000000000000000000000000000,
|
||||
const PROPAGATE_VALS_DOWN = 0b0100000000000000000000000000000000,
|
||||
const ALLOW_MISSING_POS = 0b1000000000000000000000000000000000,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +73,7 @@ impl AppFlags {
|
|||
AllowInvalidUtf8 => UTF8_NONE,
|
||||
AllowLeadingHyphen => LEADING_HYPHEN,
|
||||
AllowNegativeNumbers => ALLOW_NEG_NUMS,
|
||||
AllowMissingPositional => ALLOW_MISSING_POS,
|
||||
ColoredHelp => COLORED_HELP,
|
||||
ColorAlways => COLOR_ALWAYS,
|
||||
ColorAuto => COLOR_AUTO,
|
||||
|
@ -199,6 +201,39 @@ pub enum AppSettings {
|
|||
/// [`AllowLeadingHyphen`]: ./enum.AppSettings.html#variant.AllowLeadingHyphen
|
||||
AllowNegativeNumbers,
|
||||
|
||||
/// Allows one to implement a CLI where the second to last positional argument is optional, but
|
||||
/// the final positional argument is required. Such as `$ prog [optional] <required>` where one
|
||||
/// of the two following usages is allowed:
|
||||
///
|
||||
/// * `$ prog [optional] <required>`
|
||||
/// * `$ prog <required>`
|
||||
///
|
||||
/// This would otherwise not be allowed. This is useful when `[optional]` has a default value.
|
||||
///
|
||||
/// **Note:** In addition to using this setting, the second positional argument *must* be
|
||||
/// [required]
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, AppSettings};
|
||||
/// // Assume there is an external subcommand named "subcmd"
|
||||
/// let m = App::new("myprog")
|
||||
/// .setting(AppSettings::AllowMissingPositional)
|
||||
/// .arg(Arg::with_name("arg1")
|
||||
/// .default_value("something"))
|
||||
/// .arg(Arg::with_name("arg2")
|
||||
/// .required(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "myprog", "other"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.value_of("arg1"), Some("something"));
|
||||
/// assert_eq!(m.value_of("arg2"), Some("other"));
|
||||
/// ```
|
||||
/// [required]: ./struct.Arg.html#method.required
|
||||
AllowMissingPositional,
|
||||
|
||||
/// Specifies that an unexpected positional argument,
|
||||
/// which would otherwise cause a [`ErrorKind::UnknownArgument`] error,
|
||||
/// should instead be treated as a [`SubCommand`] within the [`ArgMatches`] struct.
|
||||
|
|
Loading…
Reference in a new issue