mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
commit
1ff9791fb4
8 changed files with 375 additions and 105 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
|||
<a name="v2.17.0"></a>
|
||||
## v2.17.0 (2016-11-01)
|
||||
|
||||
|
||||
#### Features
|
||||
|
||||
* **Positional Args:** allows specifying the second to last positional argument as multiple(true) ([1ced2a74](https://github.com/kbknapp/clap-rs/commit/1ced2a7433ea8937a1b260ea65d708f32ca7c95e), closes [#725](https://github.com/kbknapp/clap-rs/issues/725))
|
||||
|
||||
|
||||
|
||||
<a name="v2.16.4"></a>
|
||||
### v2.16.4 (2016-10-31)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
|
||||
name = "clap"
|
||||
version = "2.16.4"
|
||||
version = "2.17.0"
|
||||
authors = ["Kevin K. <kbknapp@gmail.com>"]
|
||||
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
|
||||
repository = "https://github.com/kbknapp/clap-rs.git"
|
||||
|
|
|
@ -41,6 +41,11 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
|
|||
|
||||
## What's New
|
||||
|
||||
Here's what's new in v2.17.0
|
||||
|
||||
* Allows specifying the second to last positional argument as `multiple(true)` (i.e. things such as `mv <files>... <target>`)
|
||||
* Adds an `App::get_name` and `App::get_bin_name`
|
||||
|
||||
Here's what's new in v2.16.4
|
||||
|
||||
* Fixes bug that caused panic on subcommands with aliases
|
||||
|
|
|
@ -131,7 +131,7 @@ macro_rules! validate_multiples {
|
|||
($_self:ident, $a:ident, $m:ident) => {
|
||||
debugln!("macro=validate_multiples!;");
|
||||
if $m.contains(&$a.name) && !$a.settings.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, and we don't allow multiples
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage($a,
|
||||
&*$_self.create_current_usage($m),
|
||||
$_self.color()))
|
||||
|
|
|
@ -1250,7 +1250,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`AppSettings::NoBinaryName`]: ./enum.AppSettings.html#variant.NoBinaryName
|
||||
pub fn get_matches_from<I, T>(mut self, itr: I) -> ArgMatches<'a>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString>
|
||||
T: Into<OsString> + Clone
|
||||
{
|
||||
self.get_matches_from_safe_borrow(itr).unwrap_or_else(|e| {
|
||||
// Otherwise, write to stderr and exit
|
||||
|
@ -1292,7 +1292,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`AppSettings::NoBinaryName`]: ./enum.AppSettings.html#variant.NoBinaryName
|
||||
pub fn get_matches_from_safe<I, T>(mut self, itr: I) -> ClapResult<ArgMatches<'a>>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString>
|
||||
T: Into<OsString> + Clone
|
||||
{
|
||||
self.get_matches_from_safe_borrow(itr)
|
||||
}
|
||||
|
@ -1320,7 +1320,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// [`AppSettings::NoBinaryName`]: ./enum.AppSettings.html#variant.NoBinaryName
|
||||
pub fn get_matches_from_safe_borrow<I, T>(&mut self, itr: I) -> ClapResult<ArgMatches<'a>>
|
||||
where I: IntoIterator<Item = T>,
|
||||
T: Into<OsString>
|
||||
T: Into<OsString> + Clone
|
||||
{
|
||||
// Verify all positional assertions pass
|
||||
self.p.verify_positionals();
|
||||
|
@ -1355,7 +1355,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
}
|
||||
|
||||
// do the real parsing
|
||||
if let Err(e) = self.p.get_matches_with(&mut matcher, &mut it) {
|
||||
if let Err(e) = self.p.get_matches_with(&mut matcher, &mut it.peekable()) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::io::{self, BufWriter, Write};
|
|||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::PathBuf;
|
||||
use std::slice::Iter;
|
||||
use std::iter::Peekable;
|
||||
|
||||
// Third Party
|
||||
use vec_map::{self, VecMap};
|
||||
|
@ -118,15 +119,14 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let out_dir = PathBuf::from(od);
|
||||
let name = &*self.meta.bin_name.as_ref().unwrap().clone();
|
||||
let file_name = match for_shell {
|
||||
|
||||
|
||||
Shell::Bash => format!("{}.bash-completion", name),
|
||||
Shell::Fish => format!("{}.fish", name),
|
||||
Shell::Zsh => format!("_{}", name)
|
||||
Shell::Zsh => format!("_{}", name),
|
||||
};
|
||||
|
||||
let mut file = match File::create(out_dir.join(file_name)) {
|
||||
Err(why) => panic!("couldn't create bash completion file: {}",
|
||||
why.description()),
|
||||
Err(why) => panic!("couldn't create completion file: {}", why.description()),
|
||||
Ok(file) => file,
|
||||
};
|
||||
self.gen_completions_to(for_shell, &mut file)
|
||||
|
@ -266,10 +266,16 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
for (i, o) in self.opts.iter_mut().enumerate().filter(|&(_, ref o)| o.disp_ord == 999) {
|
||||
o.disp_ord = if unified { o.unified_ord } else { i };
|
||||
}
|
||||
for (i, f) in self.flags.iter_mut().enumerate().filter(|&(_, ref f)| f.disp_ord == 999) {
|
||||
for (i, f) in self.flags
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref f)| f.disp_ord == 999) {
|
||||
f.disp_ord = if unified { f.unified_ord } else { i };
|
||||
}
|
||||
for (i, sc) in &mut self.subcommands.iter_mut().enumerate().filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) {
|
||||
for (i, sc) in &mut self.subcommands
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) {
|
||||
sc.p.meta.disp_ord = i;
|
||||
}
|
||||
}
|
||||
|
@ -517,12 +523,40 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
|
||||
// Next we verify that only the highest index has a .multiple(true) (if any)
|
||||
debug_assert!(!self.positionals
|
||||
.values()
|
||||
.any(|a| a.settings.is_set(ArgSettings::Multiple) &&
|
||||
(a.index as usize != self.positionals.len())
|
||||
),
|
||||
"Only the positional argument with the highest index may accept multiple values");
|
||||
if self.positionals()
|
||||
.any(|a| {
|
||||
a.settings.is_set(ArgSettings::Multiple) &&
|
||||
(a.index as usize != self.positionals.len())
|
||||
}) {
|
||||
debug_assert!(self.positionals()
|
||||
.filter(|p| p.settings.is_set(ArgSettings::Multiple)
|
||||
&& p.num_vals.is_none()).map(|_| 1).sum::<u64>() <= 1,
|
||||
"Only one positional argument with .multiple(true) set is allowed per command");
|
||||
|
||||
debug_assert!(self.positionals()
|
||||
.rev()
|
||||
.next()
|
||||
.unwrap()
|
||||
.is_set(ArgSettings::Required),
|
||||
"When using a positional argument with .multiple(true) that is *not the last* \
|
||||
positional argument, the last positional argument (i.e the one with the highest \
|
||||
index) *must* have .required(true) set.");
|
||||
|
||||
debug_assert!({
|
||||
let num = self.positionals.len() - 1;
|
||||
self.positionals.get(num).unwrap().is_set(ArgSettings::Multiple)
|
||||
},
|
||||
"Only the last positional argument, or second to last positional argument may be set to .multiple(true)");
|
||||
|
||||
self.set(AppSettings::LowIndexMultiplePositional);
|
||||
}
|
||||
|
||||
debug_assert!(self.positionals()
|
||||
.filter(|p| p.settings.is_set(ArgSettings::Multiple)
|
||||
&& p.num_vals.is_none())
|
||||
.map(|_| 1)
|
||||
.sum::<u64>() <= 1,
|
||||
"Only one positional argument with .multiple(true) set is allowed per command");
|
||||
|
||||
// If it's required we also need to ensure all previous positionals are
|
||||
// required too
|
||||
|
@ -666,10 +700,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
#[cfg_attr(feature = "lints", allow(while_let_on_iterator))]
|
||||
pub fn get_matches_with<I, T>(&mut self,
|
||||
matcher: &mut ArgMatcher<'a>,
|
||||
it: &mut I)
|
||||
it: &mut Peekable<I>)
|
||||
-> ClapResult<()>
|
||||
where I: Iterator<Item = T>,
|
||||
T: Into<OsString>
|
||||
T: Into<OsString> + Clone
|
||||
{
|
||||
debugln!("fn=get_matches_with;");
|
||||
// First we create the `--help` and `--version` arguments and add them if
|
||||
|
@ -684,15 +718,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
debugln!("Begin parsing '{:?}' ({:?})", arg_os, &*arg_os.as_bytes());
|
||||
|
||||
// Is this a new argument, or values from a previous option?
|
||||
debug!("Starts new arg...");
|
||||
let starts_new_arg = if arg_os.starts_with(b"-") {
|
||||
sdebugln!("Maybe");
|
||||
// a singe '-' by itself is a value and typically means "stdin" on unix systems
|
||||
!(arg_os.len_() == 1)
|
||||
} else {
|
||||
sdebugln!("No");
|
||||
false
|
||||
};
|
||||
let starts_new_arg = is_new_arg(&arg_os);
|
||||
|
||||
// Has the user already passed '--'? Meaning only positional args follow
|
||||
if !self.trailing_vals {
|
||||
|
@ -739,7 +765,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
arg_os.to_string_lossy().parse::<f64>().is_ok()));
|
||||
if needs_val_of.is_none() {
|
||||
if self.is_set(AppSettings::AllowNegativeNumbers) {
|
||||
if !(arg_os.to_string_lossy().parse::<i64>().is_ok() || arg_os.to_string_lossy().parse::<f64>().is_ok()) {
|
||||
if !(arg_os.to_string_lossy().parse::<i64>().is_ok() ||
|
||||
arg_os.to_string_lossy().parse::<f64>().is_ok()) {
|
||||
return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
|
||||
"",
|
||||
&*self.create_current_usage(matcher),
|
||||
|
@ -747,7 +774,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
} else if !self.is_set(AppSettings::AllowLeadingHyphen) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
@ -775,6 +802,26 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
}
|
||||
|
||||
debugln!("Positional counter...{}", pos_counter);
|
||||
debug!("Checking for low index multiples...");
|
||||
if self.is_set(AppSettings::LowIndexMultiplePositional) && pos_counter == (self.positionals.len() - 1) {
|
||||
sdebugln!("Found");
|
||||
if let Some(na) = it.peek() {
|
||||
let n = (*na).clone().into();
|
||||
if is_new_arg(&n) || self.possible_subcommand(&n) || suggestions::did_you_mean(&n.to_string_lossy(),
|
||||
self.subcommands
|
||||
.iter()
|
||||
.map(|s| &s.p.meta.name)).is_some() {
|
||||
debugln!("Bumping the positional counter...");
|
||||
pos_counter += 1;
|
||||
}
|
||||
} else {
|
||||
debugln!("Bumping the positional counter...");
|
||||
pos_counter += 1;
|
||||
}
|
||||
} else {
|
||||
sdebugln!("None");
|
||||
}
|
||||
if let Some(p) = self.positionals.get(pos_counter) {
|
||||
parse_positional!(self, p, arg_os, pos_counter, matcher);
|
||||
} else if self.settings.is_set(AppSettings::AllowExternalSubcommands) {
|
||||
|
@ -953,10 +1000,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
fn parse_subcommand<I, T>(&mut self,
|
||||
sc_name: String,
|
||||
matcher: &mut ArgMatcher<'a>,
|
||||
it: &mut I)
|
||||
it: &mut Peekable<I>)
|
||||
-> ClapResult<()>
|
||||
where I: Iterator<Item = T>,
|
||||
T: Into<OsString>
|
||||
T: Into<OsString> + Clone
|
||||
{
|
||||
use std::fmt::Write;
|
||||
debugln!("fn=parse_subcommand;");
|
||||
|
@ -1949,10 +1996,11 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
fn find_flag(&self, name: &str) -> Option<&FlagBuilder<'a, 'b>> {
|
||||
for f in self.flags() {
|
||||
if f.name == name || f.aliases.as_ref().unwrap_or(&vec![("",false)]).iter().any(|&(n,_)| n == name) {
|
||||
if f.name == name ||
|
||||
f.aliases.as_ref().unwrap_or(&vec![("",false)]).iter().any(|&(n, _)| n == name) {
|
||||
return Some(f);
|
||||
}
|
||||
}
|
||||
|
@ -1961,7 +2009,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
|
||||
fn find_option(&self, name: &str) -> Option<&OptBuilder<'a, 'b>> {
|
||||
for o in self.opts() {
|
||||
if o.name == name || o.aliases.as_ref().unwrap_or(&vec![("",false)]).iter().any(|&(n,_)| n == name) {
|
||||
if o.name == name ||
|
||||
o.aliases.as_ref().unwrap_or(&vec![("",false)]).iter().any(|&(n, _)| n == name) {
|
||||
return Some(o);
|
||||
}
|
||||
}
|
||||
|
@ -1983,7 +2032,15 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
debugln!("Looking for sc...{}", sc);
|
||||
debugln!("Currently in Parser...{}", self.meta.bin_name.as_ref().unwrap());
|
||||
for s in self.subcommands.iter() {
|
||||
if s.p.meta.bin_name.as_ref().unwrap_or(&String::new()) == sc || (s.p.meta.aliases.is_some() && s.p.meta.aliases.as_ref().unwrap().iter().any(|&(s,_)| s == sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG))) {
|
||||
if s.p.meta.bin_name.as_ref().unwrap_or(&String::new()) == sc ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
s.p
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(s, _)| s == sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG))) {
|
||||
return Some(s);
|
||||
}
|
||||
if let Some(app) = s.p.find_subcommand(sc) {
|
||||
|
@ -2019,3 +2076,17 @@ impl<'a, 'b> Clone for Parser<'a, 'b>
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new_arg(arg_os: &OsStr) -> bool {
|
||||
// Is this a new argument, or values from a previous option?
|
||||
debug!("Starts new arg...");
|
||||
if arg_os.starts_with(b"-") {
|
||||
sdebugln!("Maybe");
|
||||
// a singe '-' by itself is a value and typically means "stdin" on unix systems
|
||||
!(arg_os.len_() == 1)
|
||||
} else {
|
||||
sdebugln!("No");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,34 +4,35 @@ use std::str::FromStr;
|
|||
|
||||
bitflags! {
|
||||
flags Flags: u32 {
|
||||
const SC_NEGATE_REQS = 0b0000000000000000000000000001,
|
||||
const SC_REQUIRED = 0b0000000000000000000000000010,
|
||||
const A_REQUIRED_ELSE_HELP = 0b0000000000000000000000000100,
|
||||
const GLOBAL_VERSION = 0b0000000000000000000000001000,
|
||||
const VERSIONLESS_SC = 0b0000000000000000000000010000,
|
||||
const UNIFIED_HELP = 0b0000000000000000000000100000,
|
||||
const WAIT_ON_ERROR = 0b0000000000000000000001000000,
|
||||
const SC_REQUIRED_ELSE_HELP= 0b0000000000000000000010000000,
|
||||
const NEEDS_LONG_HELP = 0b0000000000000000000100000000,
|
||||
const NEEDS_LONG_VERSION = 0b0000000000000000001000000000,
|
||||
const NEEDS_SC_HELP = 0b0000000000000000010000000000,
|
||||
const DISABLE_VERSION = 0b0000000000000000100000000000,
|
||||
const HIDDEN = 0b0000000000000001000000000000,
|
||||
const TRAILING_VARARG = 0b0000000000000010000000000000,
|
||||
const NO_BIN_NAME = 0b0000000000000100000000000000,
|
||||
const ALLOW_UNK_SC = 0b0000000000001000000000000000,
|
||||
const UTF8_STRICT = 0b0000000000010000000000000000,
|
||||
const UTF8_NONE = 0b0000000000100000000000000000,
|
||||
const LEADING_HYPHEN = 0b0000000001000000000000000000,
|
||||
const NO_POS_VALUES = 0b0000000010000000000000000000,
|
||||
const NEXT_LINE_HELP = 0b0000000100000000000000000000,
|
||||
const DERIVE_DISP_ORDER = 0b0000001000000000000000000000,
|
||||
const COLORED_HELP = 0b0000010000000000000000000000,
|
||||
const COLOR_ALWAYS = 0b0000100000000000000000000000,
|
||||
const COLOR_AUTO = 0b0001000000000000000000000000,
|
||||
const COLOR_NEVER = 0b0010000000000000000000000000,
|
||||
const DONT_DELIM_TRAIL = 0b0100000000000000000000000000,
|
||||
const ALLOW_NEG_NUMS = 0b1000000000000000000000000000,
|
||||
const SC_NEGATE_REQS = 0b00000000000000000000000000001,
|
||||
const SC_REQUIRED = 0b00000000000000000000000000010,
|
||||
const A_REQUIRED_ELSE_HELP = 0b00000000000000000000000000100,
|
||||
const GLOBAL_VERSION = 0b00000000000000000000000001000,
|
||||
const VERSIONLESS_SC = 0b00000000000000000000000010000,
|
||||
const UNIFIED_HELP = 0b00000000000000000000000100000,
|
||||
const WAIT_ON_ERROR = 0b00000000000000000000001000000,
|
||||
const SC_REQUIRED_ELSE_HELP= 0b00000000000000000000010000000,
|
||||
const NEEDS_LONG_HELP = 0b00000000000000000000100000000,
|
||||
const NEEDS_LONG_VERSION = 0b00000000000000000001000000000,
|
||||
const NEEDS_SC_HELP = 0b00000000000000000010000000000,
|
||||
const DISABLE_VERSION = 0b00000000000000000100000000000,
|
||||
const HIDDEN = 0b00000000000000001000000000000,
|
||||
const TRAILING_VARARG = 0b00000000000000010000000000000,
|
||||
const NO_BIN_NAME = 0b00000000000000100000000000000,
|
||||
const ALLOW_UNK_SC = 0b00000000000001000000000000000,
|
||||
const UTF8_STRICT = 0b00000000000010000000000000000,
|
||||
const UTF8_NONE = 0b00000000000100000000000000000,
|
||||
const LEADING_HYPHEN = 0b00000000001000000000000000000,
|
||||
const NO_POS_VALUES = 0b00000000010000000000000000000,
|
||||
const NEXT_LINE_HELP = 0b00000000100000000000000000000,
|
||||
const DERIVE_DISP_ORDER = 0b00000001000000000000000000000,
|
||||
const COLORED_HELP = 0b00000010000000000000000000000,
|
||||
const COLOR_ALWAYS = 0b00000100000000000000000000000,
|
||||
const COLOR_AUTO = 0b00001000000000000000000000000,
|
||||
const COLOR_NEVER = 0b00010000000000000000000000000,
|
||||
const DONT_DELIM_TRAIL = 0b00100000000000000000000000000,
|
||||
const ALLOW_NEG_NUMS = 0b01000000000000000000000000000,
|
||||
const LOW_INDEX_MUL_POS = 0b10000000000000000000000000000,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +73,7 @@ impl AppFlags {
|
|||
GlobalVersion => GLOBAL_VERSION,
|
||||
HidePossibleValuesInHelp => NO_POS_VALUES,
|
||||
Hidden => HIDDEN,
|
||||
LowIndexMultiplePositional => LOW_INDEX_MUL_POS,
|
||||
NeedsLongHelp => NEEDS_LONG_HELP,
|
||||
NeedsLongVersion => NEEDS_LONG_VERSION,
|
||||
NeedsSubcommandHelp => NEEDS_SC_HELP,
|
||||
|
@ -663,6 +665,9 @@ pub enum AppSettings {
|
|||
#[doc(hidden)]
|
||||
NeedsSubcommandHelp,
|
||||
|
||||
#[doc(hidden)]
|
||||
LowIndexMultiplePositional,
|
||||
|
||||
}
|
||||
|
||||
impl FromStr for AppSettings {
|
||||
|
@ -684,6 +689,7 @@ impl FromStr for AppSettings {
|
|||
"globalversion" => Ok(AppSettings::GlobalVersion),
|
||||
"hidden" => Ok(AppSettings::Hidden),
|
||||
"hidepossiblevaluesinhelp" => Ok(AppSettings::HidePossibleValuesInHelp),
|
||||
"lowindexmultiplepositional" => Ok(AppSettings::LowIndexMultiplePositional),
|
||||
"nobinaryname" => Ok(AppSettings::NoBinaryName),
|
||||
"nextlinehelp" => Ok(AppSettings::NextLineHelp),
|
||||
"strictutf8" => Ok(AppSettings::StrictUtf8),
|
||||
|
@ -735,6 +741,8 @@ mod test {
|
|||
AppSettings::Hidden);
|
||||
assert_eq!("hidepossiblevaluesinhelp".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::HidePossibleValuesInHelp);
|
||||
assert_eq!("lowindexmultiplePositional".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::LowIndexMultiplePositional);
|
||||
assert_eq!("nobinaryname".parse::<AppSettings>().unwrap(),
|
||||
AppSettings::NoBinaryName);
|
||||
assert_eq!("nextlinehelp".parse::<AppSettings>().unwrap(),
|
||||
|
|
|
@ -3,7 +3,7 @@ extern crate clap;
|
|||
use clap::{App, Arg, ErrorKind, SubCommand};
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_long() {
|
||||
fn option_long() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -26,7 +26,7 @@ fn multiple_values_of_option_long() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_with_subcmd() {
|
||||
fn with_subcmd() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -50,7 +50,7 @@ fn multiple_values_with_subcmd() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_short() {
|
||||
fn option_short() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -73,7 +73,7 @@ fn multiple_values_of_option_short() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_mixed() {
|
||||
fn option_mixed() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -98,7 +98,7 @@ fn multiple_values_of_option_mixed() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_exact_exact() {
|
||||
fn option_exact_exact() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -122,7 +122,7 @@ fn multiple_values_of_option_exact_exact() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_exact_exact_not_mult() {
|
||||
fn option_exact_exact_not_mult() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -143,7 +143,7 @@ fn multiple_values_of_option_exact_exact_not_mult() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_exact_exact_mult() {
|
||||
fn option_exact_exact_mult() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -166,7 +166,7 @@ fn multiple_values_of_option_exact_exact_mult() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_exact_less() {
|
||||
fn option_exact_less() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -185,7 +185,7 @@ fn multiple_values_of_option_exact_less() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_exact_more() {
|
||||
fn option_exact_more() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -206,7 +206,7 @@ fn multiple_values_of_option_exact_more() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_min_exact() {
|
||||
fn option_min_exact() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -230,7 +230,7 @@ fn multiple_values_of_option_min_exact() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_min_less() {
|
||||
fn option_min_less() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -307,7 +307,7 @@ fn option_short_min_more_single_occur() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_max_exact() {
|
||||
fn option_max_exact() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -331,7 +331,7 @@ fn multiple_values_of_option_max_exact() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_max_less() {
|
||||
fn option_max_less() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -354,7 +354,7 @@ fn multiple_values_of_option_max_less() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_option_max_more() {
|
||||
fn option_max_more() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -375,7 +375,7 @@ fn multiple_values_of_option_max_more() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional() {
|
||||
fn positional() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -391,7 +391,7 @@ fn multiple_values_of_positional() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_exact_exact() {
|
||||
fn positional_exact_exact() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -407,7 +407,7 @@ fn multiple_values_of_positional_exact_exact() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_exact_less() {
|
||||
fn positional_exact_less() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -419,7 +419,7 @@ fn multiple_values_of_positional_exact_less() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_exact_more() {
|
||||
fn positional_exact_more() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -431,7 +431,7 @@ fn multiple_values_of_positional_exact_more() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_min_exact() {
|
||||
fn positional_min_exact() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -447,7 +447,7 @@ fn multiple_values_of_positional_min_exact() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_min_less() {
|
||||
fn positional_min_less() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -459,7 +459,7 @@ fn multiple_values_of_positional_min_less() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_min_more() {
|
||||
fn positional_min_more() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -475,7 +475,7 @@ fn multiple_values_of_positional_min_more() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_max_exact() {
|
||||
fn positional_max_exact() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -491,7 +491,7 @@ fn multiple_values_of_positional_max_exact() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_max_less() {
|
||||
fn positional_max_less() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -507,7 +507,7 @@ fn multiple_values_of_positional_max_less() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_of_positional_max_more() {
|
||||
fn positional_max_more() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("pos")
|
||||
.help("multiple positionals")
|
||||
|
@ -519,7 +519,7 @@ fn multiple_values_of_positional_max_more() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_sep_long_equals() {
|
||||
fn sep_long_equals() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -541,7 +541,7 @@ fn multiple_values_sep_long_equals() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_sep_long_space() {
|
||||
fn sep_long_space() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -564,7 +564,7 @@ fn multiple_values_sep_long_space() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_sep_short_equals() {
|
||||
fn sep_short_equals() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -586,7 +586,7 @@ fn multiple_values_sep_short_equals() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_sep_short_space() {
|
||||
fn sep_short_space() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -609,7 +609,7 @@ fn multiple_values_sep_short_space() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_sep_short_no_space() {
|
||||
fn sep_short_no_space() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -631,7 +631,7 @@ fn multiple_values_sep_short_no_space() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_sep_positional() {
|
||||
fn sep_positional() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.help("multiple options")
|
||||
|
@ -651,7 +651,7 @@ fn multiple_values_sep_positional() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_different_sep() {
|
||||
fn different_sep() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -672,7 +672,7 @@ fn multiple_values_different_sep() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_different_sep_positional() {
|
||||
fn different_sep_positional() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.help("multiple options")
|
||||
|
@ -691,7 +691,7 @@ fn multiple_values_different_sep_positional() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_no_sep() {
|
||||
fn no_sep() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -712,7 +712,7 @@ fn multiple_values_no_sep() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_no_sep_positional() {
|
||||
fn no_sep_positional() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.help("multiple options")
|
||||
|
@ -731,7 +731,7 @@ fn multiple_values_no_sep_positional() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_req_delimiter_long() {
|
||||
fn req_delimiter_long() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -757,7 +757,7 @@ fn multiple_values_req_delimiter_long() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_req_delimiter_long_with_equal() {
|
||||
fn req_delimiter_long_with_equal() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -783,7 +783,7 @@ fn multiple_values_req_delimiter_long_with_equal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_req_delimiter_short_with_space() {
|
||||
fn req_delimiter_short_with_space() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -809,7 +809,7 @@ fn multiple_values_req_delimiter_short_with_space() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_req_delimiter_short_with_no_space() {
|
||||
fn req_delimiter_short_with_no_space() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("o")
|
||||
|
@ -835,7 +835,7 @@ fn multiple_values_req_delimiter_short_with_no_space() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_req_delimiter_short_with_equal() {
|
||||
fn req_delimiter_short_with_equal() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.short("option")
|
||||
|
@ -861,7 +861,7 @@ fn multiple_values_req_delimiter_short_with_equal() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_values_req_delimiter_complex() {
|
||||
fn req_delimiter_complex() {
|
||||
let m = App::new("multiple_values")
|
||||
.arg(Arg::with_name("option")
|
||||
.long("option")
|
||||
|
@ -900,3 +900,179 @@ fn multiple_values_req_delimiter_complex() {
|
|||
&["val1", "val3", "val5", "val7", "val9", "val11", "val14", "val17",
|
||||
"val20", "val23", "val26"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn low_index_positional_not_required() {
|
||||
let _ = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.index(1)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.index(2))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn low_index_positional_last_multiple_too() {
|
||||
let _ = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.index(1)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.index(2)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn low_index_positional_too_far_back() {
|
||||
let _ = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.index(1)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.required(true)
|
||||
.index(2))
|
||||
.arg(Arg::with_name("target2")
|
||||
.required(true)
|
||||
.index(3))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn low_index_positional() {
|
||||
let m = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.index(1)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.index(2)
|
||||
.required(true))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
]);
|
||||
|
||||
assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
|
||||
let m = m.unwrap();
|
||||
|
||||
assert!(m.is_present("files"));
|
||||
assert_eq!(m.occurrences_of("files"), 3);
|
||||
assert!(m.is_present("target"));
|
||||
assert_eq!(m.occurrences_of("target"), 1);
|
||||
assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
|
||||
assert_eq!(m.value_of("target").unwrap(), "target");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn low_index_positional_with_subcmd() {
|
||||
let m = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.index(1)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.index(2)
|
||||
.required(true))
|
||||
.subcommand(SubCommand::with_name("test").arg(Arg::with_name("other")))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
"test"
|
||||
]);
|
||||
|
||||
assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
|
||||
let m = m.unwrap();
|
||||
|
||||
assert!(m.is_present("files"));
|
||||
assert_eq!(m.occurrences_of("files"), 3);
|
||||
assert!(m.is_present("target"));
|
||||
assert_eq!(m.occurrences_of("target"), 1);
|
||||
assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
|
||||
assert_eq!(m.value_of("target").unwrap(), "target");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn low_index_positional_with_option() {
|
||||
let m = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.required(true)
|
||||
.index(1)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.index(2)
|
||||
.required(true))
|
||||
.arg(Arg::with_name("opt")
|
||||
.long("option")
|
||||
.takes_value(true))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
"--option", "test"
|
||||
]);
|
||||
|
||||
assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
|
||||
let m = m.unwrap();
|
||||
|
||||
assert!(m.is_present("files"));
|
||||
assert_eq!(m.occurrences_of("files"), 3);
|
||||
assert!(m.is_present("target"));
|
||||
assert_eq!(m.occurrences_of("target"), 1);
|
||||
assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
|
||||
assert_eq!(m.value_of("target").unwrap(), "target");
|
||||
assert_eq!(m.value_of("opt").unwrap(), "test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn low_index_positional_with_flag() {
|
||||
let m = App::new("lip")
|
||||
.arg(Arg::with_name("files")
|
||||
.index(1)
|
||||
.required(true)
|
||||
.multiple(true))
|
||||
.arg(Arg::with_name("target")
|
||||
.index(2)
|
||||
.required(true))
|
||||
.arg(Arg::with_name("flg")
|
||||
.long("flag"))
|
||||
.get_matches_from_safe(vec![
|
||||
"lip",
|
||||
"file1", "file2",
|
||||
"file3", "target",
|
||||
"--flag"
|
||||
]);
|
||||
|
||||
assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
|
||||
let m = m.unwrap();
|
||||
|
||||
assert!(m.is_present("files"));
|
||||
assert_eq!(m.occurrences_of("files"), 3);
|
||||
assert!(m.is_present("target"));
|
||||
assert_eq!(m.occurrences_of("target"), 1);
|
||||
assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
|
||||
assert_eq!(m.value_of("target").unwrap(), "target");
|
||||
assert!(m.is_present("flg"));
|
||||
}
|
Loading…
Reference in a new issue