Auto merge of #524 - kbknapp:issues-511,523, r=kbknapp

Issues 511,523
This commit is contained in:
Homu 2016-06-08 19:58:33 +09:00
commit e1d33f8f22
10 changed files with 157 additions and 222 deletions

147
'
View file

@ -1,147 +0,0 @@
use std::fmt;
#[cfg(all(feature = "color", not(target_os = "windows")))]
use ansi_term::Colour::{Green, Red, Yellow};
#[cfg(all(feature = "color", not(target_os = "windows")))]
use ansi_term::ANSIString;
#[cfg(color)]
use libc;
#[cfg(color)]
const STDERR: i32 = libc::STDERR_FILENO;
#[cfg(color)]
const STDOUT: i32 = libc::STDOUT_FILENO;
#[cfg(not(color))]
const STDERR: i32 = 0;
#[cfg(not(color))]
const STDOUT: i32 = 0;
#[doc(hidden)]
#[derive(Debug, PartialEq)]
pub enum ColorWhen {
Auto, // Default
Always,
Never
}
#[cfg(color)]
pub fn is_a_tty(stderr: bool) -> bool {
let fd = if stderr { STDERR } else { STDOUT };
unsafe { libc::isatty(fd) != 0 }
}
#[cfg(not(color))]
pub fn is_a_tty(stderr: bool) -> bool {
false
}
#[doc(hidden)]
pub struct Colorizer {
use_stderr: bool,
when: ColorWhen
}
macro_rules! color {
($_self:ident, $c:ident, $m:expr) => {
match $_self.when {
ColorWhen::Auto => if is_a_tty($_self.use_stderr) {
Format::$c($m)
} else {
$m
},
ColorWhen::Always => Format::$c($m),
ColorWhen::Never => $m,
}
};
}
impl Colorizer {
pub fn good<T>(&self, msg: T) -> &fmt::Display where T: fmt::Display {
use Format::Good;
color!(self, Good, msg)
}
pub fn warning<T>(&self, msg: T) -> &fmt::Display where T: fmt::Display {
use Format::Warning;
color!(self, Warning, msg)
}
pub fn error<T>(&self, msg: T) -> &fmt::Display where T: fmt::Display {
use Format::Error;
color!(self, Error, msg)
}
}
impl Default for Colorizer {
fn default() -> Self {
Colorizer {
use_stderr: true,
when: ColorWhen::Auto
}
}
}
/// Defines styles for different types of error messages. Defaults to Error=Red, Warning=Yellow,
/// and Good=Green
#[derive(Debug)]
#[doc(hidden)]
pub enum Format<T> {
/// Defines the style used for errors, defaults to Red
Error(T),
/// Defines the style used for warnings, defaults to Yellow
Warning(T),
/// Defines the style used for good values, defaults to Green
Good(T),
}
#[cfg(all(feature = "color", not(target_os = "windows")))]
impl<T: AsRef<str>> Format<T> {
fn format(&self) -> ANSIString {
match *self {
Format::Error(ref e) => Red.bold().paint(e.as_ref()),
Format::Warning(ref e) => Yellow.paint(e.as_ref()),
Format::Good(ref e) => Green.paint(e.as_ref()),
}
}
}
#[cfg(all(feature = "color", not(target_os = "windows")))]
impl<T: AsRef<str>> fmt::Display for Format<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", &self.format())
}
}
#[cfg(any(not(feature = "color"), target_os = "windows"))]
impl<T: fmt::Display> Format<T> {
fn format(&self) -> &T {
match *self {
Format::Error(ref e) => e,
Format::Warning(ref e) => e,
Format::Good(ref e) => e,
}
}
}
#[cfg(any(not(feature = "color"), target_os = "windows"))]
impl<T: fmt::Display> fmt::Display for Format<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", &self.format())
}
}
#[cfg(all(test, feature = "color", not(target_os = "windows")))]
mod test {
use super::Format;
use ansi_term::Colour::{Green, Red, Yellow};
#[test]
fn colored_output() {
let err = Format::Error("error");
assert_eq!(&*format!("{}", err),
&*format!("{}", Red.bold().paint("error")));
let good = Format::Good("good");
assert_eq!(&*format!("{}", good), &*format!("{}", Green.paint("good")));
let warn = Format::Warning("warn");
assert_eq!(&*format!("{}", warn), &*format!("{}", Yellow.paint("warn")));
}
}

View file

@ -2,7 +2,7 @@ sudo: false
language: rust
rust:
- nightly
- nightly-2016-04-28
- nightly-2016-06-05
- beta
- stable
# Only while clippy is failing

View file

@ -18,7 +18,7 @@ libc = { version = "~0.2.9", optional = true }
ansi_term = { version = "~0.7.2", optional = true }
strsim = { version = "~0.4.0", optional = true }
yaml-rust = { version = "~0.3.2", optional = true }
clippy = { version = "=0.0.64", optional = true }
clippy = { version = "~0.0.74", optional = true }
unicode-width = { version = "~0.1.3", optional = true }
[dev-dependencies]

View file

@ -132,7 +132,7 @@ impl<'a> Help<'a> {
use_stderr: stderr,
when: parser.color(),
};
Self::new(w, nlh, hide_v, color, cizer).write_help(&parser)
Self::new(w, nlh, hide_v, color, cizer).write_help(parser)
}
/// Writes the parser help to the wrapped stream.
@ -485,6 +485,7 @@ impl<'a> Help<'a> {
impl<'a> Help<'a> {
/// Writes help for all arguments (options, flags, args, subcommands)
/// including titles of a Parser Object to the wrapped stream.
#[cfg_attr(feature = "lints", allow(useless_let_if_seq))]
pub fn write_all_args(&mut self, parser: &Parser) -> ClapResult<()> {
let flags = parser.has_flags();
@ -542,7 +543,7 @@ impl<'a> Help<'a> {
/// Writes help for subcommands of a Parser Object to the wrapped stream.
fn write_subcommands(&mut self, parser: &Parser) -> io::Result<()> {
debugln!("exec=write_subcommands;");
debugln!("exec=write_subcommands;");
let mut longest = 0;
let mut ord_m = VecMap::new();
@ -556,12 +557,10 @@ impl<'a> Help<'a> {
for (_, btm) in ord_m.into_iter() {
for (_, sc) in btm.into_iter() {
if !first {
debugln!("Writing newline...");
try!(self.writer.write(b"\n"));
} else {
first = false;
}
debugln!("Writing sc...{}", sc);
try!(self.write_arg(sc, longest));
}
}

View file

@ -76,8 +76,7 @@ macro_rules! _handle_group_reqs{
use args::AnyArg;
debugln!("macro=_handle_group_reqs!;");
for grp in $me.groups.values() {
let mut found = false;
if grp.args.contains(&$arg.name()) {
let found = if grp.args.contains(&$arg.name()) {
vec_remove!($me.required, &$arg.name());
if let Some(ref reqs) = grp.requires {
$me.required.extend(reqs);
@ -85,8 +84,10 @@ macro_rules! _handle_group_reqs{
if let Some(ref bl) = grp.conflicts {
$me.blacklist.extend(bl);
}
found = true; // What if arg is in more than one group with different reqs?
}
true // What if arg is in more than one group with different reqs?
} else {
false
};
if found {
vec_remove_all!($me.required, &grp.args);
debugln!("Adding args from group to blacklist...{:?}", grp.args);
@ -112,27 +113,26 @@ macro_rules! parse_positional {
$_self:ident,
$p:ident,
$arg_os:ident,
$pos_only:ident,
$pos_counter:ident,
$matcher:ident
) => {
debugln!("macro=parse_positional!;");
validate_multiples!($_self, $p, $matcher);
if let Err(e) = $_self.add_val_to_arg($p, &$arg_os, $matcher) {
return Err(e);
}
if !$pos_only &&
if !$_self.trailing_vals &&
($_self.settings.is_set(AppSettings::TrailingVarArg) &&
$pos_counter == $_self.positionals.len()) {
$pos_only = true;
$_self.trailing_vals = true;
}
if let Err(e) = $_self.add_val_to_arg($p, &$arg_os, $matcher) {
return Err(e);
}
$matcher.inc_occurrence_of($p.name);
let _ = $_self.groups_for_arg($p.name)
.and_then(|vec| Some($matcher.inc_occurrences_of(&*vec)));
arg_post_processing!($_self, $p, $matcher);
// Only increment the positional counter if it doesn't allow multiples
// Only increment the positional counter if it doesn't allow multiples
if !$p.settings.is_set(ArgSettings::Multiple) {
$pos_counter += 1;
}

View file

@ -840,7 +840,7 @@ impl<'a, 'b> App<'a, 'b> {
/// ```
/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
pub fn write_help<W: Write>(&self, w: &mut W) -> ClapResult<()> {
Help::write_app_help(w, &self)
Help::write_app_help(w, self)
}
/// Writes the version message to the user to a [`io::Write`] object

View file

@ -51,6 +51,7 @@ pub struct Parser<'a, 'b>
settings: AppFlags,
pub g_settings: Vec<AppSettings>,
pub meta: AppMeta<'b>,
trailing_vals: bool,
}
impl<'a, 'b> Default for Parser<'a, 'b> {
@ -72,6 +73,7 @@ impl<'a, 'b> Default for Parser<'a, 'b> {
g_settings: vec![],
settings: AppFlags::new(),
meta: AppMeta::new(),
trailing_vals: false,
}
}
}
@ -136,10 +138,10 @@ impl<'a, 'b> Parser<'a, 'b>
argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \
to take multiple values",
a.name));
let pb = PosBuilder::from_arg(&a, i as u64, &mut self.required);
let pb = PosBuilder::from_arg(a, i as u64, &mut self.required);
self.positionals.insert(i, pb);
} else if a.is_set(ArgSettings::TakesValue) {
let mut ob = OptBuilder::from_arg(&a, &mut self.required);
let mut ob = OptBuilder::from_arg(a, &mut self.required);
if self.settings.is_set(AppSettings::DeriveDisplayOrder) && a.disp_ord == 999 {
ob.disp_ord = if self.settings.is_set(AppSettings::UnifiedHelpMessage) {
self.flags.len() + self.opts.len()
@ -307,7 +309,7 @@ impl<'a, 'b> Parser<'a, 'b>
c_opt.dedup();
grps.dedup();
let mut args_in_groups = vec![];
for g in grps.iter() {
for g in &grps {
for a in self.arg_names_in_group(g).into_iter() {
args_in_groups.push(a);
}
@ -327,11 +329,10 @@ impl<'a, 'b> Parser<'a, 'b>
}
debugln!("args_in_groups={:?}", args_in_groups);
for (_, s) in pmap {
if !args_in_groups.is_empty() {
if args_in_groups.contains(&&*s) {
continue;
}
if (!args_in_groups.is_empty()) && (args_in_groups.contains(&&*s)) {
continue;
}
ret_val.push_back(s);
}
macro_rules! write_arg {
@ -456,7 +457,6 @@ impl<'a, 'b> Parser<'a, 'b>
// necessary
self.create_help_and_version();
let mut pos_only = false;
let mut subcmd_name: Option<String> = None;
let mut needs_val_of: Option<&str> = None;
let mut pos_counter = 1;
@ -475,7 +475,7 @@ impl<'a, 'b> Parser<'a, 'b>
};
// Has the user already passed '--'?
if !pos_only {
if !self.trailing_vals {
// Does the arg match a subcommand name, or any of it's aliases (if defined)
let pos_sc = self.subcommands
.iter()
@ -501,7 +501,7 @@ impl<'a, 'b> Parser<'a, 'b>
if arg_os.len_() == 2 {
// The user has passed '--' which means only positional args follow no
// matter what they start with
pos_only = true;
self.trailing_vals = true;
continue;
}
@ -564,7 +564,7 @@ impl<'a, 'b> Parser<'a, 'b>
}
if let Some(p) = self.positionals.get(pos_counter) {
parse_positional!(self, p, arg_os, pos_only, pos_counter, matcher);
parse_positional!(self, p, arg_os, pos_counter, matcher);
} else {
if self.settings.is_set(AppSettings::AllowExternalSubcommands) {
let mut sc_m = ArgMatcher::new();
@ -1131,13 +1131,17 @@ impl<'a, 'b> Parser<'a, 'b>
{
debugln!("fn=add_val_to_arg;");
let mut ret = None;
if let Some(delim) = arg.val_delim() {
if val.is_empty_() {
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
} else {
for v in val.split(delim as u32 as u8) {
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
if !(self.trailing_vals && self.is_set(AppSettings::DontDelimitTrailingValues)) {
if let Some(delim) = arg.val_delim() {
if val.is_empty_() {
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
} else {
for v in val.split(delim as u32 as u8) {
ret = try!(self.add_single_val_to_arg(arg, v, matcher));
}
}
} else {
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
}
} else {
ret = try!(self.add_single_val_to_arg(arg, val, matcher));
@ -1253,7 +1257,7 @@ impl<'a, 'b> Parser<'a, 'b>
debugln!("groups contains it...");
for n in self.arg_names_in_group(name) {
debugln!("Checking arg '{}' in group...", n);
if matcher.contains(&n) {
if matcher.contains(n) {
debugln!("matcher contains it...");
return Err(build_err!(self, n, matcher));
}
@ -1465,7 +1469,7 @@ impl<'a, 'b> Parser<'a, 'b>
debugln!("fn=create_usage;");
let mut usage = String::with_capacity(75);
usage.push_str("USAGE:\n ");
usage.push_str(&self.create_usage_no_title(&used));
usage.push_str(&self.create_usage_no_title(used));
usage
}
@ -1601,11 +1605,11 @@ impl<'a, 'b> Parser<'a, 'b>
}
pub fn write_help<W: Write>(&self, w: &mut W) -> ClapResult<()> {
Help::write_parser_help(w, &self)
Help::write_parser_help(w, self)
}
pub fn write_help_err<W: Write>(&self, w: &mut W) -> ClapResult<()> {
Help::write_parser_help_to_stderr(w, &self)
Help::write_parser_help_to_stderr(w, self)
}
fn add_defaults(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
@ -1679,6 +1683,7 @@ impl<'a, 'b> Clone for Parser<'a, 'b>
settings: self.settings.clone(),
g_settings: self.g_settings.clone(),
meta: self.meta.clone(),
trailing_vals: self.trailing_vals,
}
}
}

View file

@ -3,32 +3,33 @@ use std::ascii::AsciiExt;
bitflags! {
flags Flags: u32 {
const SC_NEGATE_REQS = 0b00000000000000000000000001,
const SC_REQUIRED = 0b00000000000000000000000010,
const A_REQUIRED_ELSE_HELP = 0b00000000000000000000000100,
const GLOBAL_VERSION = 0b00000000000000000000001000,
const VERSIONLESS_SC = 0b00000000000000000000010000,
const UNIFIED_HELP = 0b00000000000000000000100000,
const WAIT_ON_ERROR = 0b00000000000000000001000000,
const SC_REQUIRED_ELSE_HELP= 0b00000000000000000010000000,
const NEEDS_LONG_HELP = 0b00000000000000000100000000,
const NEEDS_LONG_VERSION = 0b00000000000000001000000000,
const NEEDS_SC_HELP = 0b00000000000000010000000000,
const DISABLE_VERSION = 0b00000000000000100000000000,
const HIDDEN = 0b00000000000001000000000000,
const TRAILING_VARARG = 0b00000000000010000000000000,
const NO_BIN_NAME = 0b00000000000100000000000000,
const ALLOW_UNK_SC = 0b00000000001000000000000000,
const UTF8_STRICT = 0b00000000010000000000000000,
const UTF8_NONE = 0b00000000100000000000000000,
const LEADING_HYPHEN = 0b00000001000000000000000000,
const NO_POS_VALUES = 0b00000010000000000000000000,
const NEXT_LINE_HELP = 0b00000100000000000000000000,
const DERIVE_DISP_ORDER = 0b00001000000000000000000000,
const COLORED_HELP = 0b00010000000000000000000000,
const COLOR_ALWAYS = 0b00100000000000000000000000,
const COLOR_AUTO = 0b01000000000000000000000000,
const COLOR_NEVER = 0b10000000000000000000000000,
const SC_NEGATE_REQS = 0b000000000000000000000000001,
const SC_REQUIRED = 0b000000000000000000000000010,
const A_REQUIRED_ELSE_HELP = 0b000000000000000000000000100,
const GLOBAL_VERSION = 0b000000000000000000000001000,
const VERSIONLESS_SC = 0b000000000000000000000010000,
const UNIFIED_HELP = 0b000000000000000000000100000,
const WAIT_ON_ERROR = 0b000000000000000000001000000,
const SC_REQUIRED_ELSE_HELP= 0b000000000000000000010000000,
const NEEDS_LONG_HELP = 0b000000000000000000100000000,
const NEEDS_LONG_VERSION = 0b000000000000000001000000000,
const NEEDS_SC_HELP = 0b000000000000000010000000000,
const DISABLE_VERSION = 0b000000000000000100000000000,
const HIDDEN = 0b000000000000001000000000000,
const TRAILING_VARARG = 0b000000000000010000000000000,
const NO_BIN_NAME = 0b000000000000100000000000000,
const ALLOW_UNK_SC = 0b000000000001000000000000000,
const UTF8_STRICT = 0b000000000010000000000000000,
const UTF8_NONE = 0b000000000100000000000000000,
const LEADING_HYPHEN = 0b000000001000000000000000000,
const NO_POS_VALUES = 0b000000010000000000000000000,
const NEXT_LINE_HELP = 0b000000100000000000000000000,
const DERIVE_DISP_ORDER = 0b000001000000000000000000000,
const COLORED_HELP = 0b000010000000000000000000000,
const COLOR_ALWAYS = 0b000100000000000000000000000,
const COLOR_AUTO = 0b001000000000000000000000000,
const COLOR_NEVER = 0b010000000000000000000000000,
const DONT_DELIM_TRAIL = 0b100000000000000000000000000,
}
}
@ -79,7 +80,8 @@ impl AppFlags {
DeriveDisplayOrder => DERIVE_DISP_ORDER,
ColorAlways => COLOR_ALWAYS,
ColorAuto => COLOR_AUTO,
ColorNever => COLOR_NEVER
ColorNever => COLOR_NEVER,
DontDelimitTrailingValues => DONT_DELIM_TRAIL
}
}
@ -551,6 +553,24 @@ pub enum AppSettings {
/// .get_matches();
/// ```
ColorNever,
/// Disables the automatic delimiting of values when `--` or [`AppSettings::TrailingVarArg`]
/// was used.
///
/// **NOTE:** The same thing can be done manually by setting the final positional argument to
/// [`Arg::use_delimiter(false)`]. Using this setting is safer, because it's easier to locate
/// when making changes.
///
/// # Examples
///
/// ```no_run
/// # use clap::{App, Arg, SubCommand, AppSettings};
/// App::new("myprog")
/// .setting(AppSettings::DontDelimitTrailingValues)
/// .get_matches();
/// ```
/// [`AppSettings::TrailingVarArg`]: ./enum.AppSettings.html#variant.TrailingVarArg
/// [`Arg::use_delimiter(false)`]: ./struct.Arg.html#method.use_delimiter
DontDelimitTrailingValues,
#[doc(hidden)]
NeedsLongVersion,
#[doc(hidden)]
@ -584,6 +604,10 @@ impl FromStr for AppSettings {
"nextlinehelp" => Ok(AppSettings::NextLineHelp),
"derivedisplayorder" => Ok(AppSettings::DeriveDisplayOrder),
"coloredhelp" => Ok(AppSettings::ColoredHelp),
"dontdelimittrailingvalues" => Ok(AppSettings::DontDelimitTrailingValues),
"colorauto" => Ok(AppSettings::ColorAuto),
"coloralways" => Ok(AppSettings::ColorAlways),
"colornever" => Ok(AppSettings::ColorNever),
_ => Err("unknown AppSetting, cannot convert from str".to_owned()),
}
}
@ -629,6 +653,8 @@ mod test {
AppSettings::ColoredHelp);
assert_eq!("hidden".parse::<AppSettings>().unwrap(),
AppSettings::Hidden);
assert_eq!("dontdelimittrailingvalues".parse::<AppSettings>().unwrap(),
AppSettings::DontDelimitTrailingValues);
assert!("hahahaha".parse::<AppSettings>().is_err());
}
}

View file

@ -55,24 +55,24 @@ impl OsStrExt2 for OsStr {
fn split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr) {
for (i, b) in self.as_bytes().iter().enumerate() {
if b == &byte {
return (&OsStr::from_bytes(&self.as_bytes()[..i]),
&OsStr::from_bytes(&self.as_bytes()[i + 1..]));
return (OsStr::from_bytes(&self.as_bytes()[..i]),
OsStr::from_bytes(&self.as_bytes()[i + 1..]));
}
}
(&*self, &OsStr::from_bytes(&self.as_bytes()[self.len_()..self.len_()]))
(&*self, OsStr::from_bytes(&self.as_bytes()[self.len_()..self.len_()]))
}
fn trim_left_matches(&self, byte: u8) -> &OsStr {
for (i, b) in self.as_bytes().iter().enumerate() {
if b != &byte {
return &OsStr::from_bytes(&self.as_bytes()[i..]);
return OsStr::from_bytes(&self.as_bytes()[i..]);
}
}
&*self
}
fn split_at(&self, i: usize) -> (&OsStr, &OsStr) {
(&OsStr::from_bytes(&self.as_bytes()[..i]), &OsStr::from_bytes(&self.as_bytes()[i..]))
(OsStr::from_bytes(&self.as_bytes()[..i]), OsStr::from_bytes(&self.as_bytes()[i..]))
}
fn len_(&self) -> usize {
@ -109,10 +109,10 @@ impl<'a> Iterator for OsSplit<'a> {
for b in &self.val[start..] {
self.pos += 1;
if *b == self.sep {
return Some(&OsStr::from_bytes(&self.val[start..self.pos - 1]));
return Some(OsStr::from_bytes(&self.val[start..self.pos - 1]));
}
}
Some(&OsStr::from_bytes(&self.val[start..]))
Some(OsStr::from_bytes(&self.val[start..]))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let mut count = 0;
@ -137,9 +137,9 @@ impl<'a> DoubleEndedIterator for OsSplit<'a> {
for b in self.val[..self.pos].iter().rev() {
self.pos -= 1;
if *b == self.sep {
return Some(&OsStr::from_bytes(&self.val[self.pos + 1..start]));
return Some(OsStr::from_bytes(&self.val[self.pos + 1..start]));
}
}
Some(&OsStr::from_bytes(&self.val[..start]))
Some(OsStr::from_bytes(&self.val[..start]))
}
}

View file

@ -182,3 +182,55 @@ fn global_settings() {
.is_set(AppSettings::TrailingVarArg));
}
#[test]
fn stop_delim_values_only_pos_follows() {
let r = App::new("onlypos")
.setting(AppSettings::DontDelimitTrailingValues)
.args(&[Arg::from_usage("-f [flag] 'some opt'"),
Arg::from_usage("[arg]... 'some arg'")])
.get_matches_from_safe(vec!["", "--", "-f", "-g,x"]);
assert!(r.is_ok());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert!(!m.is_present("f"));
assert_eq!(m.values_of("arg").unwrap().collect::<Vec<_>>(), &["-f", "-g,x"]);
}
#[test]
fn dont_delim_values_trailingvararg() {
let m = App::new("positional")
.setting(AppSettings::TrailingVarArg)
.setting(AppSettings::DontDelimitTrailingValues)
.arg(
Arg::from_usage("[opt]... 'some pos'"),
)
.get_matches_from(vec!["", "test", "--foo", "-Wl,-bar"]);
assert!(m.is_present("opt"));
assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>(), &["test", "--foo", "-Wl,-bar"]);
}
#[test]
fn delim_values_only_pos_follows() {
let r = App::new("onlypos")
.args(&[Arg::from_usage("-f [flag] 'some opt'"),
Arg::from_usage("[arg]... 'some arg'")])
.get_matches_from_safe(vec!["", "--", "-f", "-g,x"]);
assert!(r.is_ok());
let m = r.unwrap();
assert!(m.is_present("arg"));
assert!(!m.is_present("f"));
assert_eq!(m.values_of("arg").unwrap().collect::<Vec<_>>(), &["-f", "-g", "x"]);
}
#[test]
fn delim_values_trailingvararg() {
let m = App::new("positional")
.setting(AppSettings::TrailingVarArg)
.arg(
Arg::from_usage("[opt]... 'some pos'"),
)
.get_matches_from(vec!["", "test", "--foo", "-Wl,-bar"]);
assert!(m.is_present("opt"));
assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>(), &["test", "--foo", "-Wl", "-bar"]);
}