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 // Internal
use crate::{ use crate::{
build::{arg::ArgProvider, Arg, ArgGroup, ArgSettings}, build::{arg::ArgProvider, Arg, ArgGroup, ArgPredicate, ArgSettings},
mkeymap::MKeyMap, mkeymap::MKeyMap,
output::{fmt::Colorizer, Help, HelpWriter, Usage}, output::{fmt::Colorizer, Help, HelpWriter, Usage},
parse::{ArgMatcher, ArgMatches, Input, Parser}, 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> { 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> { let requires_if_or_not = |(val, req_arg): &(ArgPredicate<'_>, Id)| -> Option<Id> {
if let Some(v) = val { match val {
if matcher ArgPredicate::Equals(v) => {
.get(arg) if matcher
.map(|ma| ma.contains_val(v)) .get(arg)
.unwrap_or(false) .map(|ma| ma.contains_val_os(v))
{ .unwrap_or(false)
Some(req_arg.clone()) {
} else { Some(req_arg.clone())
None } else {
None
}
} }
} else { ArgPredicate::IsPresent => Some(req_arg.clone()),
Some(req_arg.clone())
} }
}; };

View file

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