refactor: Clarify intent behind requires

This is based on the work in #3384
This commit is contained in:
Ed Page 2022-02-01 16:51:53 -06:00
parent f6005052a9
commit d376865c18
3 changed files with 34 additions and 19 deletions

View file

@ -24,7 +24,7 @@ use yaml_rust::Yaml;
// Internal
use crate::{
build::{arg::ArgProvider, Arg, ArgGroup, ArgSettings},
build::{arg::ArgProvider, Arg, ArgGroup, ArgPredicate, ArgSettings},
mkeymap::MKeyMap,
output::{fmt::Colorizer, Help, HelpWriter, Usage},
parse::{ArgMatcher, ArgMatches, Input, Parser},
@ -3239,19 +3239,20 @@ impl<'help> App<'help> {
}
pub(crate) fn unroll_requirements_for_arg(&self, arg: &Id, matcher: &ArgMatcher) -> Vec<Id> {
let requires_if_or_not = |(val, req_arg): &(Option<&str>, Id)| -> Option<Id> {
if let Some(v) = val {
let requires_if_or_not = |(val, req_arg): &(ArgPredicate<'_>, Id)| -> Option<Id> {
match val {
ArgPredicate::Equals(v) => {
if matcher
.get(arg)
.map(|ma| ma.contains_val(v))
.map(|ma| ma.contains_val_os(v))
.unwrap_or(false)
{
Some(req_arg.clone())
} else {
None
}
} else {
Some(req_arg.clone())
}
ArgPredicate::IsPresent => Some(req_arg.clone()),
}
};

View file

@ -74,7 +74,7 @@ pub struct Arg<'help> {
pub(crate) settings: ArgFlags,
pub(crate) overrides: Vec<Id>,
pub(crate) groups: Vec<Id>,
pub(crate) requires: Vec<(Option<&'help str>, Id)>,
pub(crate) requires: Vec<(ArgPredicate<'help>, Id)>,
pub(crate) r_ifs: Vec<(Id, &'help str)>,
pub(crate) r_ifs_all: Vec<(Id, &'help str)>,
pub(crate) r_unless: Vec<Id>,
@ -681,7 +681,7 @@ impl<'help> Arg<'help> {
/// [override]: Arg::overrides_with()
#[must_use]
pub fn requires<T: Key>(mut self, arg_id: T) -> Self {
self.requires.push((None, arg_id.into()));
self.requires.push((ArgPredicate::IsPresent, arg_id.into()));
self
}
@ -4111,7 +4111,8 @@ impl<'help> Arg<'help> {
/// [override]: Arg::overrides_with()
#[must_use]
pub fn requires_if<T: Key>(mut self, val: &'help str, arg_id: T) -> Self {
self.requires.push((Some(val), arg_id.into()));
self.requires
.push((ArgPredicate::Equals(OsStr::new(val)), arg_id.into()));
self
}
@ -4163,8 +4164,10 @@ impl<'help> Arg<'help> {
/// [override]: Arg::overrides_with()
#[must_use]
pub fn requires_ifs<T: Key>(mut self, ifs: &[(&'help str, T)]) -> Self {
self.requires
.extend(ifs.iter().map(|(val, arg)| (Some(*val), Id::from(arg))));
self.requires.extend(
ifs.iter()
.map(|(val, arg)| (ArgPredicate::Equals(OsStr::new(*val)), Id::from(arg))),
);
self
}
@ -4234,7 +4237,8 @@ impl<'help> Arg<'help> {
/// [override]: Arg::overrides_with()
#[must_use]
pub fn requires_all<T: Key>(mut self, names: &[T]) -> Self {
self.requires.extend(names.iter().map(|s| (None, s.into())));
self.requires
.extend(names.iter().map(|s| (ArgPredicate::IsPresent, s.into())));
self
}

View file

@ -127,6 +127,16 @@ impl MatchedArg {
})
}
pub(crate) fn contains_val_os(&self, val: &OsStr) -> bool {
self.vals_flatten().any(|v| {
if self.ignore_case {
eq_ignore_case(&v.to_string_lossy(), &val.to_string_lossy())
} else {
v.as_os_str() == val
}
})
}
pub(crate) fn source(&self) -> ValueType {
self.ty
}