Skip to content

Commit

Permalink
setting(AllArgsOverrideSelf): adds a new convenience setting to allow…
Browse files Browse the repository at this point in the history
… all args to override themselves

Relates to #976
  • Loading branch information
kbknapp committed Feb 4, 2018
1 parent 4846c1f commit 4670325
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 15 deletions.
24 changes: 21 additions & 3 deletions src/app/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"--") {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/app/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -165,6 +167,10 @@ pub enum AppSettings {
/// [`ArgMatches::lossy_values_of`]: ./struct.ArgMatches.html#method.lossy_values_of
AllowInvalidUtf8,

/// Essentially sets [`Arg::overrides_with("itself")`] for all 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)
///
Expand Down
36 changes: 24 additions & 12 deletions src/args/arg_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,16 @@ 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 overr == &aa.name() {
debugln!("ArgMatcher::process_arg_overrides:{:?}:iter:{}: overrides self", a.map_or(None, |a| Some(a.name())), overr);
if let Some(ma) = self.get_mut(overr) {
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;
}
}
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);
Expand All @@ -49,11 +41,31 @@ 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 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;
}
}
}
}

Expand Down

0 comments on commit 4670325

Please sign in to comment.