mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 23:04:23 +00:00
feat(arg): allow other types besides Vec for multiple value settings
Breaking Change Instead of requiring a Vec<&str> for various Arg::*_all() and Arg::possible_values() methods this commit now requires a generic IntoIterator<Item=AsRef<str>> which allows things such as constant arrays. This change requires that any Arg::*_all() methods be changed from vec!["val", "val"] -> let vals = ["val", "val"]; some_arg.possible_values(&vals) (or vals.iter()). Closes #87
This commit is contained in:
parent
9e6af520a3
commit
0cc2f69839
6 changed files with 49 additions and 34 deletions
|
@ -3,10 +3,13 @@ extern crate clap;
|
|||
|
||||
use clap::{App, Arg, SubCommand};
|
||||
|
||||
|
||||
fn main() {
|
||||
let args = "-f --flag... 'tests flags'
|
||||
-o --option=[opt]... 'tests options'
|
||||
[positional] 'tests positionals'";
|
||||
let opt3_vals = ["fast", "slow"];
|
||||
let pos3_vals = ["vi", "emacs"];
|
||||
let matches = App::new("claptests")
|
||||
// Test version from Cargo.toml
|
||||
.version(&crate_version!()[..])
|
||||
|
@ -17,8 +20,8 @@ fn main() {
|
|||
Arg::from_usage("[flag2] -F 'tests flags with exclusions'").mutually_excludes("flag").requires("option2"),
|
||||
Arg::from_usage("--long-option-2 [option2] 'tests long options with exclusions'").mutually_excludes("option").requires("positional2"),
|
||||
Arg::from_usage("[positional2] 'tests positionals with exclusions'"),
|
||||
Arg::from_usage("-O [option3] 'tests options with specific value sets'").possible_values(vec!["fast", "slow"]),
|
||||
Arg::from_usage("[positional3]... 'tests positionals with specific values'").possible_values(vec!["vi", "emacs"])
|
||||
Arg::from_usage("-O [option3] 'tests options with specific value sets'").possible_values(&opt3_vals),
|
||||
Arg::from_usage("[positional3]... 'tests positionals with specific values'").possible_values(&pos3_vals)
|
||||
])
|
||||
.subcommand(SubCommand::new("subcmd")
|
||||
.about("tests subcommands")
|
||||
|
|
|
@ -12,11 +12,12 @@ fn main() {
|
|||
//
|
||||
// For this example, assume you want one positional argument of either "fast" or "slow"
|
||||
// i.e. the only possible ways to run the program are "myprog fast" or "myprog slow"
|
||||
let mode_vals = ["fast", "slow"];
|
||||
let matches = App::new("myapp").about("does awesome things")
|
||||
.arg(Arg::with_name("MODE")
|
||||
.help("What mode to run the program in")
|
||||
.index(1)
|
||||
.possible_values(vec!["fast", "slow"])
|
||||
.possible_values(&mode_vals)
|
||||
.required(true))
|
||||
.get_matches();
|
||||
|
||||
|
|
|
@ -33,13 +33,14 @@ arg_enum!{
|
|||
|
||||
fn main() {
|
||||
// Create the application like normal
|
||||
let enum_vals = ["fast", "slow"];
|
||||
let m = App::new("myapp")
|
||||
// Use a single positional argument that is required
|
||||
.arg(Arg::from_usage("<type> 'The Foo to use'")
|
||||
// You can define a list of possible values if you want the values to be
|
||||
// displayed in the help information. Whether you use possible_values() or
|
||||
// not, the valid values will ALWAYS be displayed on a failed parse.
|
||||
.possible_values(vec!["Bar", "Baz", "Qux"]))
|
||||
.possible_values(&enum_vals))
|
||||
// For the second positional, lets not use possible_values() just to show the difference
|
||||
.arg_from_usage("<type2> 'The Oof to use'")
|
||||
.get_matches();
|
||||
|
|
|
@ -38,11 +38,12 @@ impl FromStr for Vals {
|
|||
|
||||
fn main() {
|
||||
// Create the application like normal
|
||||
let enum_vals = ["Foo", "Bar", "Baz", "Qux"];
|
||||
let m = App::new("myapp")
|
||||
// Use a single positional argument that is required
|
||||
.arg(Arg::from_usage("<type> 'The type to use'")
|
||||
// Define the list of possible values
|
||||
.possible_values(vec!["Foo", "Bar", "Baz", "Qux"]))
|
||||
.possible_values(&enum_vals))
|
||||
.get_matches();
|
||||
|
||||
let t = value_t_or_exit!(m.value_of("type"), Vals);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::iter::IntoIterator;
|
||||
|
||||
use usageparser::{UsageParser, UsageToken};
|
||||
|
||||
/// The abstract representation of a command line argument used by the consumer of the library.
|
||||
|
@ -379,7 +381,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
|||
if let Some(ref mut vec) = self.blacklist {
|
||||
vec.push(name);
|
||||
} else {
|
||||
self.blacklist = Some(vec![name]);
|
||||
let v = vec![name];
|
||||
self.blacklist = Some(v);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -398,17 +401,18 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
|||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// let conf_excludes = ["debug", "input"];
|
||||
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
||||
/// .mutually_excludes_all(
|
||||
/// vec!["debug", "input"])
|
||||
/// .mutually_excludes_all(&conf_excludes)
|
||||
/// # ).get_matches();
|
||||
pub fn mutually_excludes_all(mut self, names: Vec<&'r str>) -> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||
pub fn mutually_excludes_all<T, I>(mut self, names: I)
|
||||
-> Arg<'n, 'l, 'h, 'g, 'p, 'r>
|
||||
where T: AsRef<str> + 'r,
|
||||
I: IntoIterator<Item=&'r T> {
|
||||
if let Some(ref mut vec) = self.blacklist {
|
||||
for n in names {
|
||||
vec.push(n);
|
||||
}
|
||||
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||
} else {
|
||||
self.blacklist = Some(names);
|
||||
self.blacklist = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -449,17 +453,18 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
|||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// let config_conflicts = ["debug", "input"];
|
||||
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
||||
/// .conflicts_with_all(
|
||||
/// vec!["debug", "input"])
|
||||
/// .conflicts_with_all(&config_conflicts)
|
||||
/// # ).get_matches();
|
||||
pub fn conflicts_with_all(mut self, names: Vec<&'r str>) -> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||
pub fn conflicts_with_all<T, I>(mut self, names: I)
|
||||
-> Arg<'n, 'l, 'h, 'g, 'p, 'r>
|
||||
where T: AsRef<str> + 'r,
|
||||
I: IntoIterator<Item=&'r T> {
|
||||
if let Some(ref mut vec) = self.blacklist {
|
||||
for n in names {
|
||||
vec.push(n);
|
||||
}
|
||||
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||
} else {
|
||||
self.blacklist = Some(names);
|
||||
self.blacklist = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -497,17 +502,18 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
|||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// let config_reqs = ["debug", "input"];
|
||||
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
||||
/// .requires_all(
|
||||
/// vec!["debug", "input"])
|
||||
/// .requires_all(&config_reqs)
|
||||
/// # ).get_matches();
|
||||
pub fn requires_all(mut self, names: Vec<&'r str>) -> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||
pub fn requires_all<T, I>(mut self, names: I)
|
||||
-> Arg<'n, 'l, 'h, 'g, 'p, 'r>
|
||||
where T: AsRef<str> + 'r,
|
||||
I: IntoIterator<Item=&'r T> {
|
||||
if let Some(ref mut vec) = self.requires {
|
||||
for n in names {
|
||||
vec.push(n);
|
||||
}
|
||||
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||
} else {
|
||||
self.requires = Some(names);
|
||||
self.requires = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -587,18 +593,20 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
|||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// let mode_vals = ["fast", "slow"];
|
||||
/// # let matches = App::new("myprog")
|
||||
/// # .arg(
|
||||
/// # Arg::with_name("debug").index(1)
|
||||
/// .possible_values(vec!["fast", "slow"])
|
||||
/// .possible_values(&mode_vals)
|
||||
/// # ).get_matches();
|
||||
pub fn possible_values(mut self, names: Vec<&'p str>) -> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||
pub fn possible_values<T, I>(mut self, names: I)
|
||||
-> Arg<'n, 'l, 'h, 'g, 'p, 'r>
|
||||
where T: AsRef<str> + 'p,
|
||||
I: IntoIterator<Item=&'p T> {
|
||||
if let Some(ref mut vec) = self.possible_vals {
|
||||
for n in names {
|
||||
vec.push(n);
|
||||
}
|
||||
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||
} else {
|
||||
self.possible_vals = Some(names);
|
||||
self.possible_vals = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
@ -283,9 +283,10 @@ macro_rules! value_t_or_exit {
|
|||
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
|
||||
/// // and implements std::str::FromStr to use with the value_t! macros
|
||||
/// fn main() {
|
||||
/// let enum_vals = ["Bar", "Baz", "Qux"];
|
||||
/// let m = App::new("app")
|
||||
/// .arg(Arg::from_usage("<foo> 'the foo'")
|
||||
/// .possible_values(vec!["Bar", "Baz", "Qux"]))
|
||||
/// .possible_values(&enum_vals))
|
||||
/// .get_matches();
|
||||
/// let f = value_t_or_exit!(m.value_of("foo"), Foo);
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue