mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 06:12:40 +00:00
feat(positionals): add support for multiple values
Add support for #44 (multiple values for positional arguments) when the positional argument is the last one (i.e. highest index)
This commit is contained in:
parent
f244ca6f9a
commit
8078400941
3 changed files with 50 additions and 23 deletions
33
src/app.rs
33
src/app.rs
|
@ -207,9 +207,9 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
|||
if a.short.is_some() || a.long.is_some() {
|
||||
panic!("Argument \"{}\" has conflicting requirements, both index() and short(), or long(), were supplied", a.name);
|
||||
}
|
||||
if a.multiple {
|
||||
panic!("Argument \"{}\" has conflicting requirements, both index() and multiple(true) were supplied",a.name);
|
||||
}
|
||||
// if a.multiple {
|
||||
// panic!("Argument \"{}\" has conflicting requirements, both index() and multiple(true) were supplied",a.name);
|
||||
// }
|
||||
if a.takes_value {
|
||||
panic!("Argument \"{}\" has conflicting requirements, both index() and takes_value(true) were supplied", a.name);
|
||||
}
|
||||
|
@ -218,6 +218,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
|||
name: a.name,
|
||||
index: i,
|
||||
required: a.required,
|
||||
multiple: a.multiple,
|
||||
blacklist: None,
|
||||
requires: None,
|
||||
possible_vals: None,
|
||||
|
@ -652,10 +653,27 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
|||
}
|
||||
}
|
||||
}
|
||||
matches.positionals.insert(p.name, PosArg{
|
||||
name: p.name.to_owned(),
|
||||
value: arg.clone(),
|
||||
});
|
||||
// Have we made the update yet?
|
||||
let mut done = false;
|
||||
if p.multiple {
|
||||
// Check if it's already existing and update if so...
|
||||
if let Some(ref mut pa) = matches.positionals.get_mut(p.name) {
|
||||
done = true;
|
||||
pa.occurrences += 1;
|
||||
pa.values.push(arg.clone());
|
||||
}
|
||||
} else {
|
||||
// Only increment the positional counter if it doesn't allow multiples
|
||||
pos_counter += 1;
|
||||
}
|
||||
// Was an update made, or is this the first occurrence?
|
||||
if !done {
|
||||
matches.positionals.insert(p.name, PosArg{
|
||||
name: p.name.to_owned(),
|
||||
occurrences: 1,
|
||||
values: vec![arg.clone()],
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ref bl) = p.blacklist {
|
||||
for name in bl {
|
||||
|
@ -676,7 +694,6 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
|||
self.required.insert(n);
|
||||
}
|
||||
}
|
||||
pos_counter += 1;
|
||||
} else {
|
||||
self.report_error(format!("Positional argument \"{}\" was found, but {} wasn't expecting any", arg, self.name), true, true);
|
||||
}
|
||||
|
|
|
@ -91,8 +91,8 @@ impl<'a> ArgMatches<'a> {
|
|||
/// an additional value at runtime). If the option wasn't present at runtime
|
||||
/// it returns `None`.
|
||||
///
|
||||
/// *NOTE:* If getting a value for an option argument that allows multiples, prefer `values_of()`
|
||||
/// as `value_of()` will only return the _*first*_ value.
|
||||
/// *NOTE:* If getting a value for an option or positional argument that allows multiples,
|
||||
/// prefer `values_of()` as `value_of()` will only return the _*first*_ value.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -105,21 +105,21 @@ impl<'a> ArgMatches<'a> {
|
|||
/// ```
|
||||
pub fn value_of<'n>(&self, name: &'n str) -> Option<&str> {
|
||||
if let Some(ref opt) = self.opts.get(name) {
|
||||
if !opt.values.is_empty() {
|
||||
if let Some(ref s) = opt.values.iter().nth(0) {
|
||||
return Some(&s[..]);
|
||||
}
|
||||
}
|
||||
if let Some(ref s) = opt.values.iter().nth(0) {
|
||||
return Some(&s[..]);
|
||||
}
|
||||
}
|
||||
if let Some(ref pos) = self.positionals.get(name) {
|
||||
return Some(&pos.value[..]);
|
||||
if let Some(ref s) = pos.values.iter().nth(0) {
|
||||
return Some(&s[..]);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Gets the values of a specific option in a vector (i.e. an argument that takes
|
||||
/// an additional value at runtime). If the option wasn't present at runtime
|
||||
/// it returns `None`
|
||||
/// Gets the values of a specific option or positional argument in a vector (i.e. an argument
|
||||
/// that takes an additional value at runtime). If the option wasn't present at runtime it
|
||||
/// returns `None`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -141,6 +141,11 @@ impl<'a> ArgMatches<'a> {
|
|||
|
||||
return Some(opt.values.iter().map(|s| &s[..]).collect::<Vec<_>>());
|
||||
}
|
||||
if let Some(ref pos) = self.positionals.get(name) {
|
||||
if pos.values.is_empty() { return None; }
|
||||
|
||||
return Some(pos.values.iter().map(|s| &s[..]).collect::<Vec<_>>());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -167,13 +172,11 @@ impl<'a> ArgMatches<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
/// Checks the number of occurrences of an option or flag at runtime.
|
||||
/// Checks the number of occurrences of an option, flag, or positional argument at runtime.
|
||||
/// If an option or flag isn't present it will return `0`, if the option or flag doesn't
|
||||
/// allow multiple occurrences, it will return `1` no matter how many times it occurred
|
||||
/// (unless it wasn't prsent) at all.
|
||||
///
|
||||
/// *NOTE:* This _*DOES NOT*_ work for positional arguments (use `.value_of()` instead).
|
||||
///
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -193,6 +196,9 @@ impl<'a> ArgMatches<'a> {
|
|||
if let Some(ref o) = self.opts.get(name) {
|
||||
return o.occurrences;
|
||||
}
|
||||
if let Some(ref p) = self.positionals.get(name) {
|
||||
return p.occurrences;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,10 @@ use std::collections::HashSet;
|
|||
pub struct PosArg {
|
||||
/// The unique name of the argument, required
|
||||
pub name: String,
|
||||
/// How many occurences of this option have been found when parsing
|
||||
pub occurrences: u8,
|
||||
/// The value provided to the argument by the user
|
||||
pub value: String,
|
||||
pub values: Vec<String>
|
||||
}
|
||||
|
||||
pub struct PosBuilder<'n> {
|
||||
|
@ -30,6 +32,8 @@ pub struct PosBuilder<'n> {
|
|||
/// **NOTE:** required by default means, it is required *until* mutually
|
||||
/// exclusive arguments are evaluated.
|
||||
pub required: bool,
|
||||
/// Allow multiple occurrences of an option argument such as "-c some -c other"
|
||||
pub multiple: bool,
|
||||
/// A list of names of other arguments that are *required* to be used when
|
||||
/// this flag is used
|
||||
pub requires: Option<HashSet<&'n str>>,
|
||||
|
|
Loading…
Reference in a new issue