mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
parent
7b0ff38fe7
commit
35ad17a282
3 changed files with 96 additions and 20 deletions
|
@ -1058,24 +1058,34 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
where A: AnyArg<'a, 'b> + Display {
|
||||
debugln!("fn=add_val_to_arg;");
|
||||
let mut ret = None;
|
||||
for v in val.split(arg.val_delim().unwrap_or(',') as u32 as u8) {
|
||||
debugln!("adding val: {:?}", v);
|
||||
matcher.add_val_to(&*arg.name(), v);
|
||||
|
||||
// Increment or create the group "args"
|
||||
if let Some(grps) = self.groups_for_arg(&*arg.name()) {
|
||||
for grp in grps {
|
||||
matcher.add_val_to(&*grp, v);
|
||||
}
|
||||
if let Some(delim) = arg.val_delim() {
|
||||
for v in val.split(delim as u32 as u8) {
|
||||
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
|
||||
}
|
||||
|
||||
// The validation must come AFTER inserting into 'matcher' or the usage string
|
||||
// can't be built
|
||||
ret = try!(self.validate_value(arg, v, matcher));
|
||||
} else {
|
||||
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn add_single_val_to_arg<A>(&self, arg: &A, v: &OsStr, matcher: &mut ArgMatcher<'a>) -> ClapResult<Option<&'a str>>
|
||||
where A: AnyArg<'a, 'b>
|
||||
{
|
||||
debugln!("adding val: {:?}", v);
|
||||
matcher.add_val_to(arg.name(), v);
|
||||
|
||||
// Increment or create the group "args"
|
||||
if let Some(grps) = self.groups_for_arg(arg.name()) {
|
||||
for grp in grps {
|
||||
matcher.add_val_to(&*grp, v);
|
||||
}
|
||||
}
|
||||
|
||||
// The validation must come AFTER inserting into 'matcher' or the usage string
|
||||
// can't be built
|
||||
self.validate_value(arg, v, matcher)
|
||||
}
|
||||
|
||||
fn validate_value<A>(&self, arg: &A, val: &OsStr, matcher: &ArgMatcher<'a>) -> ClapResult<Option<&'a str>>
|
||||
where A: AnyArg<'a, 'b> {
|
||||
debugln!("fn=validate_value; val={:?}", val);
|
||||
|
|
|
@ -179,6 +179,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
"max_values" => a.max_values(v.as_i64().unwrap() as u8),
|
||||
"min_values" => a.min_values(v.as_i64().unwrap() as u8),
|
||||
"value_name" => a.value_name(v.as_str().unwrap()),
|
||||
"use_delimiter" => a.use_delimiter(v.as_bool().unwrap()),
|
||||
"value_delimiter" => a.value_delimiter(v.as_str().unwrap()),
|
||||
"value_names" => {
|
||||
for ys in v.as_vec().unwrap() {
|
||||
|
@ -815,8 +816,65 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Specifies whether or not an arugment should allow grouping of multiple values via a
|
||||
/// delimter. I.e. shoulde `--option=val1,val2,val3` be parsed as three values (`val1`, `val2`,
|
||||
/// and `val3`) or as a single value (`val1,val2,val3`). Defaults to using `,` (comma) as the
|
||||
/// value delimiter for all arguments that accept values (options and positional arguments)
|
||||
///
|
||||
/// **NOTE:** The defalt is `true`. Setting the value to `true` will reset any previous use of
|
||||
/// `Arg::value_delimiter` back to the default of `,` (comma).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The following example shows the default behavior.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// let delims = App::new("delims")
|
||||
/// .arg(Arg::with_name("option")
|
||||
/// .long("option")
|
||||
/// .takes_value(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "delims",
|
||||
/// "--option=val1,val2,val3",
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(delims.is_present("option"));
|
||||
/// assert_eq!(delims.occurrences_of("option"), 1);
|
||||
/// assert_eq!(delims.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
|
||||
/// ```
|
||||
/// The next example shows the difference when turning delimiters off.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// let nodelims = App::new("nodelims")
|
||||
/// .arg(Arg::with_name("option")
|
||||
/// .long("option")
|
||||
/// .use_delimiter(false)
|
||||
/// .takes_value(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "nodelims",
|
||||
/// "--option=val1,val2,val3",
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(nodelims.is_present("option"));
|
||||
/// assert_eq!(nodelims.occurrences_of("option"), 1);
|
||||
/// assert_eq!(nodelims.value_of("option").unwrap(), "val1,val2,val3");
|
||||
/// ```
|
||||
pub fn use_delimiter(mut self, d: bool) -> Self {
|
||||
if d {
|
||||
self.val_delim = Some(',');
|
||||
self.set(ArgSettings::UseValueDelimiter)
|
||||
} else {
|
||||
self.val_delim = None;
|
||||
self.unset(ArgSettings::UseValueDelimiter)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the separator to use when values are clumped together, defaults to `,` (comma).
|
||||
///
|
||||
/// **NOTE:** implicitly sets `Arg::use_delimiter(true)`
|
||||
///
|
||||
/// **NOTE:** implicitly sets `Arg::takes_value(true)`
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -837,6 +895,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// ```
|
||||
pub fn value_delimiter(mut self, d: &str) -> Self {
|
||||
self = self.set(ArgSettings::TakesValue);
|
||||
self = self.set(ArgSettings::UseValueDelimiter);
|
||||
self.val_delim = Some(d.chars()
|
||||
.nth(0)
|
||||
.expect("Failed to get value_delimiter from arg"));
|
||||
|
|
|
@ -3,12 +3,13 @@ use std::ascii::AsciiExt;
|
|||
|
||||
bitflags! {
|
||||
flags Flags: u8 {
|
||||
const REQUIRED = 0b000001,
|
||||
const MULTIPLE = 0b000010,
|
||||
const EMPTY_VALS = 0b000100,
|
||||
const GLOBAL = 0b001000,
|
||||
const HIDDEN = 0b010000,
|
||||
const TAKES_VAL = 0b100000,
|
||||
const REQUIRED = 0b0000001,
|
||||
const MULTIPLE = 0b0000010,
|
||||
const EMPTY_VALS = 0b0000100,
|
||||
const GLOBAL = 0b0001000,
|
||||
const HIDDEN = 0b0010000,
|
||||
const TAKES_VAL = 0b0100000,
|
||||
const USE_DELIM = 0b1000000,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +18,7 @@ pub struct ArgFlags(Flags);
|
|||
|
||||
impl ArgFlags {
|
||||
pub fn new() -> Self {
|
||||
ArgFlags(EMPTY_VALS)
|
||||
ArgFlags(EMPTY_VALS | USE_DELIM)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, s: ArgSettings) {
|
||||
|
@ -28,6 +29,7 @@ impl ArgFlags {
|
|||
ArgSettings::Global => self.0.insert(GLOBAL),
|
||||
ArgSettings::Hidden => self.0.insert(HIDDEN),
|
||||
ArgSettings::TakesValue => self.0.insert(TAKES_VAL),
|
||||
ArgSettings::UseValueDelimiter => self.0.insert(USE_DELIM),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +41,7 @@ impl ArgFlags {
|
|||
ArgSettings::Global => self.0.remove(GLOBAL),
|
||||
ArgSettings::Hidden => self.0.remove(HIDDEN),
|
||||
ArgSettings::TakesValue => self.0.remove(TAKES_VAL),
|
||||
ArgSettings::UseValueDelimiter => self.0.remove(USE_DELIM),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +53,7 @@ impl ArgFlags {
|
|||
ArgSettings::Global => self.0.contains(GLOBAL),
|
||||
ArgSettings::Hidden => self.0.contains(HIDDEN),
|
||||
ArgSettings::TakesValue => self.0.contains(TAKES_VAL),
|
||||
ArgSettings::UseValueDelimiter => self.0.contains(USE_DELIM),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +80,8 @@ pub enum ArgSettings {
|
|||
Hidden,
|
||||
/// The argument accepts a value, such as `--option <value>`
|
||||
TakesValue,
|
||||
/// Determines if the argument allows values to be grouped via a delimter
|
||||
UseValueDelimiter,
|
||||
}
|
||||
|
||||
impl FromStr for ArgSettings {
|
||||
|
@ -88,6 +94,7 @@ impl FromStr for ArgSettings {
|
|||
"emptyvalues" => Ok(ArgSettings::EmptyValues),
|
||||
"hidden" => Ok(ArgSettings::Hidden),
|
||||
"takesvalue" => Ok(ArgSettings::TakesValue),
|
||||
"usevaluedelimiter" => Ok(ArgSettings::UseValueDelimiter),
|
||||
_ => Err("unknown ArgSetting, cannot convert from str".to_owned()),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue