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};
|
use clap::{App, Arg, SubCommand};
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = "-f --flag... 'tests flags'
|
let args = "-f --flag... 'tests flags'
|
||||||
-o --option=[opt]... 'tests options'
|
-o --option=[opt]... 'tests options'
|
||||||
[positional] 'tests positionals'";
|
[positional] 'tests positionals'";
|
||||||
|
let opt3_vals = ["fast", "slow"];
|
||||||
|
let pos3_vals = ["vi", "emacs"];
|
||||||
let matches = App::new("claptests")
|
let matches = App::new("claptests")
|
||||||
// Test version from Cargo.toml
|
// Test version from Cargo.toml
|
||||||
.version(&crate_version!()[..])
|
.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("[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("--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("[positional2] 'tests positionals with exclusions'"),
|
||||||
Arg::from_usage("-O [option3] 'tests options with specific value sets'").possible_values(vec!["fast", "slow"]),
|
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(vec!["vi", "emacs"])
|
Arg::from_usage("[positional3]... 'tests positionals with specific values'").possible_values(&pos3_vals)
|
||||||
])
|
])
|
||||||
.subcommand(SubCommand::new("subcmd")
|
.subcommand(SubCommand::new("subcmd")
|
||||||
.about("tests subcommands")
|
.about("tests subcommands")
|
||||||
|
|
|
@ -12,11 +12,12 @@ fn main() {
|
||||||
//
|
//
|
||||||
// For this example, assume you want one positional argument of either "fast" or "slow"
|
// 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"
|
// 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")
|
let matches = App::new("myapp").about("does awesome things")
|
||||||
.arg(Arg::with_name("MODE")
|
.arg(Arg::with_name("MODE")
|
||||||
.help("What mode to run the program in")
|
.help("What mode to run the program in")
|
||||||
.index(1)
|
.index(1)
|
||||||
.possible_values(vec!["fast", "slow"])
|
.possible_values(&mode_vals)
|
||||||
.required(true))
|
.required(true))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,14 @@ arg_enum!{
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create the application like normal
|
// Create the application like normal
|
||||||
|
let enum_vals = ["fast", "slow"];
|
||||||
let m = App::new("myapp")
|
let m = App::new("myapp")
|
||||||
// Use a single positional argument that is required
|
// Use a single positional argument that is required
|
||||||
.arg(Arg::from_usage("<type> 'The Foo to use'")
|
.arg(Arg::from_usage("<type> 'The Foo to use'")
|
||||||
// You can define a list of possible values if you want the values to be
|
// 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
|
// displayed in the help information. Whether you use possible_values() or
|
||||||
// not, the valid values will ALWAYS be displayed on a failed parse.
|
// 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
|
// For the second positional, lets not use possible_values() just to show the difference
|
||||||
.arg_from_usage("<type2> 'The Oof to use'")
|
.arg_from_usage("<type2> 'The Oof to use'")
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
|
@ -38,11 +38,12 @@ impl FromStr for Vals {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create the application like normal
|
// Create the application like normal
|
||||||
|
let enum_vals = ["Foo", "Bar", "Baz", "Qux"];
|
||||||
let m = App::new("myapp")
|
let m = App::new("myapp")
|
||||||
// Use a single positional argument that is required
|
// Use a single positional argument that is required
|
||||||
.arg(Arg::from_usage("<type> 'The type to use'")
|
.arg(Arg::from_usage("<type> 'The type to use'")
|
||||||
// Define the list of possible values
|
// Define the list of possible values
|
||||||
.possible_values(vec!["Foo", "Bar", "Baz", "Qux"]))
|
.possible_values(&enum_vals))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let t = value_t_or_exit!(m.value_of("type"), Vals);
|
let t = value_t_or_exit!(m.value_of("type"), Vals);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::iter::IntoIterator;
|
||||||
|
|
||||||
use usageparser::{UsageParser, UsageToken};
|
use usageparser::{UsageParser, UsageToken};
|
||||||
|
|
||||||
/// The abstract representation of a command line argument used by the consumer of the library.
|
/// 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 {
|
if let Some(ref mut vec) = self.blacklist {
|
||||||
vec.push(name);
|
vec.push(name);
|
||||||
} else {
|
} else {
|
||||||
self.blacklist = Some(vec![name]);
|
let v = vec![name];
|
||||||
|
self.blacklist = Some(v);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -398,17 +401,18 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use clap::{App, Arg};
|
/// # use clap::{App, Arg};
|
||||||
|
/// let conf_excludes = ["debug", "input"];
|
||||||
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
||||||
/// .mutually_excludes_all(
|
/// .mutually_excludes_all(&conf_excludes)
|
||||||
/// vec!["debug", "input"])
|
|
||||||
/// # ).get_matches();
|
/// # ).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 {
|
if let Some(ref mut vec) = self.blacklist {
|
||||||
for n in names {
|
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||||
vec.push(n);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.blacklist = Some(names);
|
self.blacklist = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -449,17 +453,18 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use clap::{App, Arg};
|
/// # use clap::{App, Arg};
|
||||||
|
/// let config_conflicts = ["debug", "input"];
|
||||||
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
||||||
/// .conflicts_with_all(
|
/// .conflicts_with_all(&config_conflicts)
|
||||||
/// vec!["debug", "input"])
|
|
||||||
/// # ).get_matches();
|
/// # ).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 {
|
if let Some(ref mut vec) = self.blacklist {
|
||||||
for n in names {
|
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||||
vec.push(n);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.blacklist = Some(names);
|
self.blacklist = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -497,17 +502,18 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use clap::{App, Arg};
|
/// # use clap::{App, Arg};
|
||||||
|
/// let config_reqs = ["debug", "input"];
|
||||||
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
/// # let myprog = App::new("myprog").arg(Arg::with_name("conifg")
|
||||||
/// .requires_all(
|
/// .requires_all(&config_reqs)
|
||||||
/// vec!["debug", "input"])
|
|
||||||
/// # ).get_matches();
|
/// # ).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 {
|
if let Some(ref mut vec) = self.requires {
|
||||||
for n in names {
|
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||||
vec.push(n);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.requires = Some(names);
|
self.requires = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -587,18 +593,20 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use clap::{App, Arg};
|
/// # use clap::{App, Arg};
|
||||||
|
/// let mode_vals = ["fast", "slow"];
|
||||||
/// # let matches = App::new("myprog")
|
/// # let matches = App::new("myprog")
|
||||||
/// # .arg(
|
/// # .arg(
|
||||||
/// # Arg::with_name("debug").index(1)
|
/// # Arg::with_name("debug").index(1)
|
||||||
/// .possible_values(vec!["fast", "slow"])
|
/// .possible_values(&mode_vals)
|
||||||
/// # ).get_matches();
|
/// # ).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 {
|
if let Some(ref mut vec) = self.possible_vals {
|
||||||
for n in names {
|
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
|
||||||
vec.push(n);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.possible_vals = Some(names);
|
self.possible_vals = Some(names.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,9 +283,10 @@ macro_rules! value_t_or_exit {
|
||||||
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
|
/// // 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
|
/// // and implements std::str::FromStr to use with the value_t! macros
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
|
/// let enum_vals = ["Bar", "Baz", "Qux"];
|
||||||
/// let m = App::new("app")
|
/// let m = App::new("app")
|
||||||
/// .arg(Arg::from_usage("<foo> 'the foo'")
|
/// .arg(Arg::from_usage("<foo> 'the foo'")
|
||||||
/// .possible_values(vec!["Bar", "Baz", "Qux"]))
|
/// .possible_values(&enum_vals))
|
||||||
/// .get_matches();
|
/// .get_matches();
|
||||||
/// let f = value_t_or_exit!(m.value_of("foo"), Foo);
|
/// let f = value_t_or_exit!(m.value_of("foo"), Foo);
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue