mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42: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::process;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
use yaml_rust::Yaml;
|
use yaml_rust::Yaml;
|
||||||
|
@ -18,7 +19,7 @@ use vec_map::VecMap;
|
||||||
use args::{Arg, ArgMatches, MatchedArg, SubCommand};
|
use args::{Arg, ArgMatches, MatchedArg, SubCommand};
|
||||||
use args::{FlagBuilder, OptBuilder, PosBuilder};
|
use args::{FlagBuilder, OptBuilder, PosBuilder};
|
||||||
use args::settings::{ArgFlags, ArgSettings};
|
use args::settings::{ArgFlags, ArgSettings};
|
||||||
use args::ArgGroup;
|
use args::{ArgGroup, AnyArg};
|
||||||
use fmt::Format;
|
use fmt::Format;
|
||||||
use self::settings::AppFlags;
|
use self::settings::AppFlags;
|
||||||
use suggestions;
|
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>,
|
matches: &mut ArgMatches<'ar, 'ar>,
|
||||||
arg: char)
|
arg: char)
|
||||||
-> ClapResult<bool> {
|
-> ClapResult<bool> {
|
||||||
if let Some(v) = self.flags
|
let v = self.flags.iter().filter(|&v| v.short.is_some() && v.short.unwrap() == arg).next();
|
||||||
.iter()
|
if v.is_some() {
|
||||||
.filter(|&v| v.short.is_some() && v.short.unwrap() == arg)
|
let flag = v.unwrap();
|
||||||
.next() {
|
try!(self.validate_arg(flag, matches));
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
if let Some(ref vec) = self.groups_for_arg(flag.name) {
|
||||||
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) {
|
|
||||||
for grp in vec {
|
for grp in vec {
|
||||||
if let Some(ref mut f) = matches.args.get_mut(grp) {
|
if let Some(ref mut f) = matches.args.get_mut(grp) {
|
||||||
f.occurrences = if v.settings.is_set(&ArgSettings::Multiple) {
|
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)
|
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<()> {
|
fn validate_blacklist(&self, matches: &mut ArgMatches<'ar, 'ar>) -> ClapResult<()> {
|
||||||
for name in self.blacklist.iter() {
|
for name in self.blacklist.iter() {
|
||||||
if matches.args.contains_key(name) {
|
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(
|
return Err(error_builder::TooManyValues(
|
||||||
vals.get(vals.keys()
|
vals.get(vals.keys()
|
||||||
.last()
|
.last()
|
||||||
.expect("error getting last key. This is a bug"))
|
.expect(INTERNAL_ERROR_MSG))
|
||||||
.expect("failed to retrieve last value. This is a bug"),
|
.expect(INTERNAL_ERROR_MSG),
|
||||||
&f.to_string(),
|
&f.to_string(),
|
||||||
&try!(self.create_current_usage(matches))));
|
&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 std::io;
|
||||||
|
|
||||||
use Arg;
|
use Arg;
|
||||||
|
use args::AnyArg;
|
||||||
use args::settings::{ArgFlags, ArgSettings};
|
use args::settings::{ArgFlags, ArgSettings};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::FlagBuilder;
|
use super::FlagBuilder;
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
pub use self::arg::Arg;
|
pub use self::arg::Arg;
|
||||||
pub use self::argmatches::ArgMatches;
|
pub use self::arg_matches::ArgMatches;
|
||||||
pub use self::subcommand::SubCommand;
|
pub use self::subcommand::SubCommand;
|
||||||
pub use self::argbuilder::{FlagBuilder, OptBuilder, PosBuilder};
|
pub use self::arg_builder::{FlagBuilder, OptBuilder, PosBuilder};
|
||||||
pub use self::matchedarg::MatchedArg;
|
pub use self::matched_arg::MatchedArg;
|
||||||
pub use self::group::ArgGroup;
|
pub use self::group::ArgGroup;
|
||||||
|
pub use self::any_arg::AnyArg;
|
||||||
|
|
||||||
mod arg;
|
mod arg;
|
||||||
mod argmatches;
|
pub mod any_arg;
|
||||||
|
mod arg_matches;
|
||||||
|
mod arg_matcher;
|
||||||
mod subcommand;
|
mod subcommand;
|
||||||
mod argbuilder;
|
mod arg_builder;
|
||||||
mod matchedarg;
|
mod matched_arg;
|
||||||
mod group;
|
mod group;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
Loading…
Reference in a new issue