mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
imp(Traits): refactoring some configuration into traits
There is now an AnyArg trait which lets you (clap dev, not consumer) get info about certain args regardless of their type. Allows more generic and de-duplicated code
This commit is contained in:
parent
1fdecfd519
commit
5800cdec6d
4 changed files with 80 additions and 45 deletions
|
@ -10,6 +10,7 @@ use std::path::Path;
|
|||
use std::process;
|
||||
use std::ffi::OsStr;
|
||||
use std::borrow::Borrow;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::Yaml;
|
||||
|
@ -18,7 +19,7 @@ use vec_map::VecMap;
|
|||
use args::{Arg, ArgMatches, MatchedArg, SubCommand};
|
||||
use args::{FlagBuilder, OptBuilder, PosBuilder};
|
||||
use args::settings::{ArgFlags, ArgSettings};
|
||||
use args::ArgGroup;
|
||||
use args::{ArgGroup, AnyArg};
|
||||
use fmt::Format;
|
||||
use self::settings::AppFlags;
|
||||
use suggestions;
|
||||
|
@ -3059,43 +3060,12 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
|||
matches: &mut ArgMatches<'ar, 'ar>,
|
||||
arg: char)
|
||||
-> ClapResult<bool> {
|
||||
if let Some(v) = self.flags
|
||||
.iter()
|
||||
.filter(|&v| v.short.is_some() && v.short.unwrap() == arg)
|
||||
.next() {
|
||||
// Ensure this flag isn't on the mutually excludes list
|
||||
if self.blacklist.contains(&v.name) {
|
||||
matches.args.remove(v.name);
|
||||
return Err(error_builder::ArgumentConflict(
|
||||
v.to_string(),
|
||||
self.blacklisted_from(v.name, &matches),
|
||||
try!(self.create_current_usage(matches))));
|
||||
}
|
||||
if self.overrides.contains(&v.name) {
|
||||
debugln!("it is...");
|
||||
debugln!("checking who defined it...");
|
||||
if let Some(ref name) = self.overriden_from(v.name, matches) {
|
||||
debugln!("found {}", name);
|
||||
matches.args.remove(name);
|
||||
remove_overriden!(self, name);
|
||||
}
|
||||
}
|
||||
if let Some(ref or) = v.overrides {
|
||||
for pa in or {
|
||||
matches.args.remove(pa);
|
||||
remove_overriden!(self, pa);
|
||||
self.overrides.push(pa);
|
||||
}
|
||||
}
|
||||
let v = self.flags.iter().filter(|&v| v.short.is_some() && v.short.unwrap() == arg).next();
|
||||
if v.is_some() {
|
||||
let flag = v.unwrap();
|
||||
try!(self.validate_arg(flag, matches));
|
||||
|
||||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
||||
if matches.args.contains_key(v.name) && !v.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(error_builder::UnexpectedMultipleUsage(
|
||||
&*format!("-{}", arg),
|
||||
&*try!(self.create_current_usage(matches))));
|
||||
}
|
||||
|
||||
if let Some(ref vec) = self.groups_for_arg(v.name) {
|
||||
if let Some(ref vec) = self.groups_for_arg(flag.name) {
|
||||
for grp in vec {
|
||||
if let Some(ref mut f) = matches.args.get_mut(grp) {
|
||||
f.occurrences = if v.settings.is_set(&ArgSettings::Multiple) {
|
||||
|
@ -3159,6 +3129,40 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
|||
Ok(false)
|
||||
}
|
||||
|
||||
fn validate_arg<A>(&mut self, arg: &A, matches: &mut ArgMatches<'ar, 'ar>) -> ClapResult<()>
|
||||
where A: AnyArg<'ar> + Display {
|
||||
// Ensure this arg isn't on the mutually excludes list
|
||||
if self.blacklist.contains(&arg.name()) {
|
||||
matches.args.remove(arg.name());
|
||||
return Err(error_builder::ArgumentConflict(
|
||||
arg.to_string(),
|
||||
self.blacklisted_from(arg.name(), &matches),
|
||||
try!(self.create_current_usage(matches))));
|
||||
}
|
||||
if self.overrides.contains(&arg.name()) {
|
||||
if let Some(ref name) = self.overriden_from(arg.name(), matches) {
|
||||
matches.args.remove(name);
|
||||
remove_overriden!(self, name);
|
||||
}
|
||||
}
|
||||
if let Some(or) = arg.overrides() {
|
||||
for pa in or {
|
||||
matches.args.remove(pa);
|
||||
remove_overriden!(self, pa);
|
||||
self.overrides.push(pa);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
||||
if matches.args.contains_key(arg.name()) && !arg.is_set(&ArgSettings::Multiple) {
|
||||
return Err(error_builder::UnexpectedMultipleUsage(
|
||||
&*format!("-{}", arg),
|
||||
&*try!(self.create_current_usage(matches))));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_blacklist(&self, matches: &mut ArgMatches<'ar, 'ar>) -> ClapResult<()> {
|
||||
for name in self.blacklist.iter() {
|
||||
if matches.args.contains_key(name) {
|
||||
|
@ -3254,8 +3258,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
|||
return Err(error_builder::TooManyValues(
|
||||
vals.get(vals.keys()
|
||||
.last()
|
||||
.expect("error getting last key. This is a bug"))
|
||||
.expect("failed to retrieve last value. This is a bug"),
|
||||
.expect(INTERNAL_ERROR_MSG))
|
||||
.expect(INTERNAL_ERROR_MSG),
|
||||
&f.to_string(),
|
||||
&try!(self.create_current_usage(matches))));
|
||||
}
|
||||
|
|
8
src/args/any_arg.rs
Normal file
8
src/args/any_arg.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use args::settings::ArgSettings;
|
||||
|
||||
pub trait AnyArg<'n> {
|
||||
fn name(&self) -> &'n str;
|
||||
fn overrides(&self) -> Option<&[&'n str]>;
|
||||
fn is_set(&self, &ArgSettings) -> bool;
|
||||
fn set(&mut self, &ArgSettings);
|
||||
}
|
|
@ -4,6 +4,7 @@ use std::convert::From;
|
|||
use std::io;
|
||||
|
||||
use Arg;
|
||||
use args::AnyArg;
|
||||
use args::settings::{ArgFlags, ArgSettings};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -167,6 +168,25 @@ impl<'n> Display for FlagBuilder<'n> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n> AnyArg<'n> for FlagBuilder<'n> {
|
||||
fn name(&self) -> &'n str {
|
||||
self.name
|
||||
}
|
||||
|
||||
fn overrides(&self) -> Option<&[&'n str]> {
|
||||
self.overrides.as_ref().map(|o| &o[..])
|
||||
}
|
||||
|
||||
fn is_set(&self, s: &ArgSettings) -> bool {
|
||||
self.settings.is_set(s)
|
||||
}
|
||||
|
||||
fn set(&mut self, s: &ArgSettings) {
|
||||
self.settings.set(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::FlagBuilder;
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
pub use self::arg::Arg;
|
||||
pub use self::argmatches::ArgMatches;
|
||||
pub use self::arg_matches::ArgMatches;
|
||||
pub use self::subcommand::SubCommand;
|
||||
pub use self::argbuilder::{FlagBuilder, OptBuilder, PosBuilder};
|
||||
pub use self::matchedarg::MatchedArg;
|
||||
pub use self::arg_builder::{FlagBuilder, OptBuilder, PosBuilder};
|
||||
pub use self::matched_arg::MatchedArg;
|
||||
pub use self::group::ArgGroup;
|
||||
pub use self::any_arg::AnyArg;
|
||||
|
||||
mod arg;
|
||||
mod argmatches;
|
||||
pub mod any_arg;
|
||||
mod arg_matches;
|
||||
mod arg_matcher;
|
||||
mod subcommand;
|
||||
mod argbuilder;
|
||||
mod matchedarg;
|
||||
mod arg_builder;
|
||||
mod matched_arg;
|
||||
mod group;
|
||||
#[allow(dead_code)]
|
||||
pub mod settings;
|
||||
|
|
Loading…
Reference in a new issue