Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 48 additions & 32 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,12 @@ impl App {
name: a.name,
short: a.short,
long: a.long,
multiple: a.multiple,
blacklist: a.blacklist,
help: a.help,
requires: a.requires,
required: a.required,
value: None
values: vec![]
});
} else {
if let Some(ref l) = a.long {
Expand Down Expand Up @@ -465,20 +466,23 @@ impl App {
self.report_error(format!("The argument --{} is mutually exclusive with one or more other arguments", arg),
true, true);
}

matches.opts.insert(k, OptArg{
name: v.name,
short: v.short,
long: v.long,
help: v.help,
required: v.required,
blacklist: None,
multiple: v.multiple,
requires: None,
value: arg_val.clone()
values: if arg_val.is_some() { vec![arg_val.clone().unwrap()]} else {vec![]}
});

match arg_val {
None => { return Some(v.name); },
_ => { return None; }
}
}
}
}
}
Expand Down Expand Up @@ -555,27 +559,29 @@ impl App {
true, true);
}
}
} else {
// Short flag or opt
let arg_c = arg.chars().nth(0).unwrap();
self.check_for_help_and_version(arg_c);

if ! self.parse_single_short_flag(matches, arg_c) {
for (k, v) in self.opts.iter() {
if let Some(s) = v.short {
if s == arg_c {
return Some(k)
}
}
}

self.report_error(
format!("Argument -{} isn't valid",arg_c),
true, true);
return None;
}
// Short flag or opt
let arg_c = arg.chars().nth(0).unwrap();

// Ensure the arg in question isn't a help or version flag
self.check_for_help_and_version(arg_c);

// Check for a matching flag, and return none if found
if self.parse_single_short_flag(matches, arg_c) { return None; }

// Check for matching short in options, and return the name
// (only ones with shorts, of course)
for v in self.opts.values().filter(|&v| v.short.is_some()) {
if v.short.unwrap() == arg_c {
return Some(v.name)
}
}

}
None
// Didn't match a flag or option, must be invalid
self.report_error( format!("Argument -{} isn't valid",arg_c), true, true);

unreachable!();
}

fn parse_single_short_flag(&mut self, matches: &mut ArgMatches, arg: char) -> bool {
Expand Down Expand Up @@ -719,16 +725,26 @@ impl App {
format!("-{}",opt.short.unwrap())
}),true, true);
}
matches.opts.insert(nvo, OptArg{
name: opt.name,
short: opt.short,
long: opt.long,
help: opt.help,
requires: None,
blacklist: None,
required: opt.required,
value: Some(arg.clone())
});
let mut done = false;
if opt.multiple {
if let Some(ref mut o) = matches.opts.get_mut(opt.name) {
done = true;
o.values.push(arg.clone());
}
}
if ! done {
matches.opts.insert(nvo, OptArg{
name: opt.name,
short: opt.short,
long: opt.long,
help: opt.help,
requires: None,
blacklist: None,
multiple: opt.multiple,
required: opt.required,
values: vec![arg.clone()]
});
}
if let Some(ref bl) = opt.blacklist {
if ! bl.is_empty() {
for name in bl.iter() {
Expand Down
38 changes: 35 additions & 3 deletions src/args/argmatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ impl ArgMatches {

/// Gets the value of a specific option or positional argument (i.e. an argument that takes
/// 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()`
/// as `value_of()` will only return the _*first*_ value.
///
/// # Example
///
Expand All @@ -99,8 +102,10 @@ impl ArgMatches {
/// ```
pub fn value_of(&self, name: &'static str) -> Option<&String> {
if let Some(ref opt) = self.opts.get(name) {
if let Some(ref v) = opt.value {
return Some(v);
if ! opt.values.is_empty() {
if let Some(ref s) = opt.values.iter().nth(0) {
return Some(s);
}
}
}
if let Some(ref pos) = self.positionals.get(name) {
Expand All @@ -111,6 +116,33 @@ impl ArgMatches {
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`
///
/// # Example
///
/// ```no_run
/// # use clap::{App, Arg};
/// # let matches = App::new("myapp").arg(Arg::new("output").takes_value(true)).get_matches();
/// // If the program had option "-c" that took a value and was run
/// // via "myapp -o some -o other -o file"
/// // values_of() would return a [&str; 3] ("some", "other", "file")
/// if let Some(os) = matches.values_of("output") {
/// for o in os {
/// println!("A value for output: {}", o);
/// }
/// }
/// ```
pub fn values_of(&self, name: &'static str) -> Option<Vec<&str>> {
if let Some(ref opt) = self.opts.get(name) {
if opt.values.is_empty() { return None; }

return Some(opt.values.iter().map(|s| &s[..]).collect::<Vec<_>>());
}
None
}

/// Checks if a flag was argument was supplied at runtime. **DOES NOT** work for
/// option or positional arguments (use `.value_of()` instead)
///
Expand Down
4 changes: 3 additions & 1 deletion src/args/optarg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub struct OptArg {
pub requires: Option<Vec<&'static str>>,
/// A list of names for other arguments that *may not* be used with this flag
pub blacklist: Option<Vec<&'static str>>,
/// Allow multiple occurrences of an option argument such as "-c some -c other"
pub multiple: bool,
/// The value provided to the argument by the user
pub value: Option<String>
pub values: Vec<String>
}