for (arg_id, _) in matcher
.args()
.filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
.filter(|(arg_id, _)| self.cmd.find(arg_id).is_some())
{
debug!("Validator::validate_conflicts::iter: id={arg_id:?}"); let conflicts = conflicts.gather_conflicts(self.cmd, arg_id);
ok!(self.build_conflict_err(arg_id, &conflicts, matcher));
}
Ok(())
}
fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> {
debug!("Validator::validate_exclusive"); let args_count = matcher
.args()
.filter(|(arg_id, matched)| {
matched.check_explicit(&ArgPredicate::IsPresent) // Avoid including our own groups by checking none of them. If a group is present, the // args for the group will be.
&& self.cmd.find(arg_id).is_some()
})
.count(); if args_count <= 1 { // Nothing present to conflict with return Ok(());
}
matcher
.args()
.filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
.find_map(|(id, _)| {
debug!("Validator::validate_exclusive:iter:{id:?}"); self.cmd
.find(id) // Find `arg`s which are exclusive but also appear with other args.
.filter(|&arg| arg.is_exclusive_set() && args_count > 1)
})
.map(|arg| { // Throw an error for the first conflict found.
Err(Error::argument_conflict( self.cmd,
arg.to_string(),
Vec::new(),
Usage::new(self.cmd)
.required(&self.required)
.create_usage_with_title(&[]),
))
})
.unwrap_or(Ok(()))
}
fn gather_requires(&mutself, matcher: &ArgMatcher) {
debug!("Validator::gather_requires");
for (name, matched) in matcher
.args()
.filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
{
debug!("Validator::gather_requires:iter:{name:?}"); iflet Some(arg) = self.cmd.find(name) { let is_relevant = |(val, req_arg): &(ArgPredicate, Id)| -> Option<Id> { let required = matched.check_explicit(val);
required.then(|| req_arg.clone())
};
for req in self.cmd.unroll_arg_requires(is_relevant, arg.get_id()) { self.required.insert(req);
}
} elseiflet Some(g) = self.cmd.find_group(name) {
debug!("Validator::gather_requires:iter:{name:?}:group");
for r in &g.requires { self.required.insert(r.clone());
}
}
}
}
for arg_or_group in self
.required
.iter()
.filter(|r| !matcher.check_explicit(r, &ArgPredicate::IsPresent))
{
debug!("Validator::validate_required:iter:aog={arg_or_group:?}"); iflet Some(arg) = self.cmd.find(arg_or_group) {
debug!("Validator::validate_required:iter: This is an arg"); if !is_exclusive_present && !self.is_missing_required_ok(arg, conflicts) {
debug!( "Validator::validate_required:iter: Missing {:?}",
arg.get_id()
);
missing_required.push(arg.get_id().clone()); if !arg.is_last_set() {
highest_index = highest_index.max(arg.get_index().unwrap_or(0));
}
}
} elseiflet Some(group) = self.cmd.find_group(arg_or_group) {
debug!("Validator::validate_required:iter: This is a group"); if !self
.cmd
.unroll_args_in_group(&group.id)
.iter()
.any(|a| matcher.check_explicit(a, &ArgPredicate::IsPresent))
{
debug!( "Validator::validate_required:iter: Missing {:?}",
group.get_id()
);
missing_required.push(group.get_id().clone());
}
}
}
// Validate the conditionally required args
for a in self
.cmd
.get_arguments()
.filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent))
{ letmut required = false;
for (other, val) in &a.r_ifs { if matcher.check_explicit(other, &ArgPredicate::Equals(val.into())) {
debug!( "Validator::validate_required:iter: Missing {:?}",
a.get_id()
);
required = true;
}
}
if !is_exclusive_present && required {
missing_required.push(a.get_id().clone()); if !a.is_last_set() {
highest_index = highest_index.max(a.get_index().unwrap_or(0));
}
}
}
// For display purposes, include all of the preceding positional arguments if !self.cmd.is_allow_missing_positional_set() {
for pos in self
.cmd
.get_positionals()
.filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent))
{ if pos.get_index() < Some(highest_index) {
debug!( "Validator::validate_required:iter: Missing {:?}",
pos.get_id()
);
missing_required.push(pos.get_id().clone());
}
}
}
if !missing_required.is_empty() {
ok!(self.missing_required_error(matcher, missing_required));
}
Ok(())
}
fn is_missing_required_ok(&self, a: &Arg, conflicts: &Conflicts) -> bool {
debug!("Validator::is_missing_required_ok: {}", a.get_id()); if !conflicts.gather_conflicts(self.cmd, a.get_id()).is_empty() {
debug!("Validator::is_missing_required_ok: true (self)"); returntrue;
}
for group_id in self.cmd.groups_for_arg(a.get_id()) { if !conflicts.gather_conflicts(self.cmd, &group_id).is_empty() {
debug!("Validator::is_missing_required_ok: true ({group_id})"); returntrue;
}
} false
}
// Failing a required unless means, the arg's "unless" wasn't present, and neither were they
fn fails_arg_required_unless(&self, a: &Arg, matcher: &ArgMatcher) -> bool {
debug!("Validator::fails_arg_required_unless: a={:?}", a.get_id()); let exists = |id| matcher.check_explicit(id, &ArgPredicate::IsPresent);
// `req_args`: an arg to include in the error even if not used
fn missing_required_error(
&self,
matcher: &ArgMatcher,
raw_req_args: Vec<Id>,
) -> ClapResult<()> {
debug!("Validator::missing_required_error; incl={raw_req_args:?}");
debug!( "Validator::missing_required_error: reqs={:?}", self.required
);
let usg = Usage::new(self.cmd).required(&self.required);
let arg_id_conflicts_storage; let arg_id_conflicts = iflet Some(arg_id_conflicts) = self.get_direct_conflicts(arg_id) {
arg_id_conflicts
} else { // `is_missing_required_ok` is a case where we check not-present args for conflicts
arg_id_conflicts_storage = gather_direct_conflicts(cmd, arg_id);
&arg_id_conflicts_storage
};
for (other_arg_id, other_arg_id_conflicts) in self.potential.iter() { if arg_id == other_arg_id { continue;
}
if arg_id_conflicts.contains(other_arg_id) {
conflicts.push(other_arg_id.clone());
} if other_arg_id_conflicts.contains(arg_id) {
conflicts.push(other_arg_id.clone());
}
}
fn gather_arg_direct_conflicts(cmd: &Command, arg: &Arg) -> Vec<Id> { letmut conf = arg.blacklist.clone();
for group_id in cmd.groups_for_arg(arg.get_id()) { let group = cmd.find_group(&group_id).expect(INTERNAL_ERROR_MSG);
conf.extend(group.conflicts.iter().cloned()); if !group.multiple {
for member_id in &group.args { if member_id != arg.get_id() {
conf.push(member_id.clone());
}
}
}
}
// Overrides are implicitly conflicts
conf.extend(arg.overrides.iter().cloned());
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.