mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +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() {
|
if a.short.is_some() || a.long.is_some() {
|
||||||
panic!("Argument \"{}\" has conflicting requirements, both index() and short(), or long(), were supplied", a.name);
|
panic!("Argument \"{}\" has conflicting requirements, both index() and short(), or long(), were supplied", a.name);
|
||||||
}
|
}
|
||||||
if a.multiple {
|
// if a.multiple {
|
||||||
panic!("Argument \"{}\" has conflicting requirements, both index() and multiple(true) were supplied",a.name);
|
// panic!("Argument \"{}\" has conflicting requirements, both index() and multiple(true) were supplied",a.name);
|
||||||
}
|
// }
|
||||||
if a.takes_value {
|
if a.takes_value {
|
||||||
panic!("Argument \"{}\" has conflicting requirements, both index() and takes_value(true) were supplied", a.name);
|
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,
|
name: a.name,
|
||||||
index: i,
|
index: i,
|
||||||
required: a.required,
|
required: a.required,
|
||||||
|
multiple: a.multiple,
|
||||||
blacklist: None,
|
blacklist: None,
|
||||||
requires: None,
|
requires: None,
|
||||||
possible_vals: 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{
|
// Have we made the update yet?
|
||||||
name: p.name.to_owned(),
|
let mut done = false;
|
||||||
value: arg.clone(),
|
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 {
|
if let Some(ref bl) = p.blacklist {
|
||||||
for name in bl {
|
for name in bl {
|
||||||
|
@ -676,7 +694,6 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
self.required.insert(n);
|
self.required.insert(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos_counter += 1;
|
|
||||||
} else {
|
} else {
|
||||||
self.report_error(format!("Positional argument \"{}\" was found, but {} wasn't expecting any", arg, self.name), true, true);
|
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
|
/// an additional value at runtime). If the option wasn't present at runtime
|
||||||
/// it returns `None`.
|
/// it returns `None`.
|
||||||
///
|
///
|
||||||
/// *NOTE:* If getting a value for an option argument that allows multiples, prefer `values_of()`
|
/// *NOTE:* If getting a value for an option or positional argument that allows multiples,
|
||||||
/// as `value_of()` will only return the _*first*_ value.
|
/// prefer `values_of()` as `value_of()` will only return the _*first*_ value.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -105,21 +105,21 @@ impl<'a> ArgMatches<'a> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn value_of<'n>(&self, name: &'n str) -> Option<&str> {
|
pub fn value_of<'n>(&self, name: &'n str) -> Option<&str> {
|
||||||
if let Some(ref opt) = self.opts.get(name) {
|
if let Some(ref opt) = self.opts.get(name) {
|
||||||
if !opt.values.is_empty() {
|
if let Some(ref s) = opt.values.iter().nth(0) {
|
||||||
if let Some(ref s) = opt.values.iter().nth(0) {
|
return Some(&s[..]);
|
||||||
return Some(&s[..]);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Some(ref pos) = self.positionals.get(name) {
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the values of a specific option in a vector (i.e. an argument that takes
|
/// Gets the values of a specific option or positional argument in a vector (i.e. an argument
|
||||||
/// an additional value at runtime). If the option wasn't present at runtime
|
/// that takes an additional value at runtime). If the option wasn't present at runtime it
|
||||||
/// it returns `None`
|
/// returns `None`
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -141,6 +141,11 @@ impl<'a> ArgMatches<'a> {
|
||||||
|
|
||||||
return Some(opt.values.iter().map(|s| &s[..]).collect::<Vec<_>>());
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,13 +172,11 @@ impl<'a> ArgMatches<'a> {
|
||||||
false
|
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
|
/// 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
|
/// allow multiple occurrences, it will return `1` no matter how many times it occurred
|
||||||
/// (unless it wasn't prsent) at all.
|
/// (unless it wasn't prsent) at all.
|
||||||
///
|
///
|
||||||
/// *NOTE:* This _*DOES NOT*_ work for positional arguments (use `.value_of()` instead).
|
|
||||||
///
|
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -193,6 +196,9 @@ impl<'a> ArgMatches<'a> {
|
||||||
if let Some(ref o) = self.opts.get(name) {
|
if let Some(ref o) = self.opts.get(name) {
|
||||||
return o.occurrences;
|
return o.occurrences;
|
||||||
}
|
}
|
||||||
|
if let Some(ref p) = self.positionals.get(name) {
|
||||||
|
return p.occurrences;
|
||||||
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,10 @@ use std::collections::HashSet;
|
||||||
pub struct PosArg {
|
pub struct PosArg {
|
||||||
/// The unique name of the argument, required
|
/// The unique name of the argument, required
|
||||||
pub name: String,
|
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
|
/// The value provided to the argument by the user
|
||||||
pub value: String,
|
pub values: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PosBuilder<'n> {
|
pub struct PosBuilder<'n> {
|
||||||
|
@ -30,6 +32,8 @@ pub struct PosBuilder<'n> {
|
||||||
/// **NOTE:** required by default means, it is required *until* mutually
|
/// **NOTE:** required by default means, it is required *until* mutually
|
||||||
/// exclusive arguments are evaluated.
|
/// exclusive arguments are evaluated.
|
||||||
pub required: bool,
|
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
|
/// A list of names of other arguments that are *required* to be used when
|
||||||
/// this flag is used
|
/// this flag is used
|
||||||
pub requires: Option<HashSet<&'n str>>,
|
pub requires: Option<HashSet<&'n str>>,
|
||||||
|
|
Loading…
Reference in a new issue