diff --git a/CHANGELOG.md b/CHANGELOG.md
index e727bee9c8c..c2fe69bf269 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,21 @@
+
+### v2.20.3 (2017-02-03)
+
+
+#### Documentation
+
+* **Macros:** adds a warning about changing values in Cargo.toml not triggering a rebuild automatically ([112aea3e](https://github.com/kbknapp/clap-rs/commit/112aea3e42ae9e0c0a2d33ebad89496dbdd95e5d), closes [#838](https://github.com/kbknapp/clap-rs/issues/838))
+
+#### Bug Fixes
+
+* fixes a println->debugln typo ([279aa62e](https://github.com/kbknapp/clap-rs/commit/279aa62eaf08f56ce090ba16b937bc763cbb45be))
+* fixes bash completions for commands that have an underscore in the name ([7f5cfa72](https://github.com/kbknapp/clap-rs/commit/7f5cfa724f0ac4e098f5fe466c903febddb2d994), closes [#581](https://github.com/kbknapp/clap-rs/issues/581))
+* fixes a bug where ZSH completions would panic if the binary name had an underscore in it ([891a2a00](https://github.com/kbknapp/clap-rs/commit/891a2a006f775e92c556dda48bb32fac9807c4fb), closes [#581](https://github.com/kbknapp/clap-rs/issues/581))
+* allow final word to be wrapped in wrap_help ([564c5f0f](https://github.com/kbknapp/clap-rs/commit/564c5f0f1730f4a2c1cdd128664f1a981c31dcd4), closes [#828](https://github.com/kbknapp/clap-rs/issues/828))
+* fixes a bug where global args weren't included in the generated completion scripts ([9a1e006e](https://github.com/kbknapp/clap-rs/commit/9a1e006eb75ad5a6057ebd119aa90f7e06c0ace8), closes [#841](https://github.com/kbknapp/clap-rs/issues/841))
+
+
+
### v2.20.2 (2017-02-03)
diff --git a/Cargo.toml b/Cargo.toml
index be77e3450dc..2137eeb75ac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "clap"
-version = "2.20.2"
+version = "2.20.3"
authors = ["Kevin K. "]
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
repository = "https://github.com/kbknapp/clap-rs.git"
@@ -10,7 +10,7 @@ homepage = "https://clap.rs/"
readme = "README.md"
license = "MIT"
keywords = ["argument", "command", "arg", "parser", "parse"]
-categories = ["command-line-interface"]
+categories = ["command-line interface"]
description = """
A simple to use, efficient, and full featured Command Line Argument Parser
"""
diff --git a/README.md b/README.md
index 0d309daf9fe..531056bc4aa 100644
--- a/README.md
+++ b/README.md
@@ -47,12 +47,17 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
Here's the highlights for v2.20.2
-* fixes a critical bug where subcommand settings were being propogated too far
-* adds ArgGroup::multiple to the supported YAML fields for building ArgGroups from YAML
+* fixes a println->debugln typo
+* **Completions**: fixes bash completions for commands that have an underscore in the name
+* **Completions**: fixes a bug where ZSH completions would panic if the binary name had an underscore in it
+* allow final word to be wrapped in wrap_help
+* **Completions**: fixes a bug where global args weren't included in the generated completion scripts
+* **Macros Documentation:** adds a warning about changing values in Cargo.toml not triggering a rebuild automatically
+Here's the highlights from v2.0.0 to v2.20.2
-Here's the highlights from v2.0.0 to v2.20.1
-
+* Fixes a critical bug where subcommand settings were being propogated too far
+* Adds ArgGroup::multiple to the supported YAML fields for building ArgGroups from YAML
* Fixes a bug where the final word wasn't wrapped in help messages
* Fixes finding required arguments in group arguments
* **ArgsNegateSubcommands:** disables args being allowed between subcommands
diff --git a/src/app/macros.rs b/src/app/macros.rs
index 61d861f3c59..f589216f396 100644
--- a/src/app/macros.rs
+++ b/src/app/macros.rs
@@ -132,7 +132,7 @@ macro_rules! validate_multiples {
if $m.contains(&$a.b.name) && !$a.b.settings.is_set(ArgSettings::Multiple) {
// Not the first time, and we don't allow multiples
return Err(Error::unexpected_multiple_usage($a,
- &*$_self.create_current_usage($m),
+ &*$_self.create_current_usage($m, None),
$_self.color()))
}
};
diff --git a/src/app/parser.rs b/src/app/parser.rs
index 1304b19b149..f2fbbe49cb8 100644
--- a/src/app/parser.rs
+++ b/src/app/parser.rs
@@ -117,6 +117,8 @@ impl<'a, 'b> Parser<'a, 'b>
self.propogate_help_version();
self.build_bin_names();
+ self.propogate_globals();
+ self.propogate_settings();
ComplGen::new(self).generate(for_shell, buf)
}
@@ -304,23 +306,32 @@ impl<'a, 'b> Parser<'a, 'b>
pub fn get_required_from(&self,
reqs: &[&'a str],
- matcher: Option<&ArgMatcher<'a>>)
+ matcher: Option<&ArgMatcher<'a>>,
+ extra: Option<&str>)
-> VecDeque {
- debugln!("Parser::get_required_from; reqs={:?}", reqs);
+ debugln!("Parser::get_required_from: reqs={:?}, extra={:?}", reqs, extra);
let mut c_flags: Vec<&str> = vec![];
let mut c_pos: Vec<&str> = vec![];
let mut c_opt: Vec<&str> = vec![];
let mut grps: Vec<&str> = vec![];
- for name in reqs {
- if self.flags.iter().any(|f| &f.b.name == name) {
- c_flags.push(name);
- } else if self.opts.iter().any(|o| &o.b.name == name) {
- c_opt.push(name);
- } else if self.groups.contains_key(name) {
- grps.push(name);
- } else {
- c_pos.push(name);
+ macro_rules! categorize {
+ ($_self:ident, $name:ident, $c_flags:ident, $c_pos:ident, $c_opt:ident, $grps:ident) => {
+ if $_self.flags.iter().any(|f| &f.b.name == $name) {
+ $c_flags.push($name);
+ } else if self.opts.iter().any(|o| &o.b.name == $name) {
+ $c_opt.push($name);
+ } else if self.groups.contains_key($name) {
+ $grps.push($name);
+ } else {
+ $c_pos.push($name);
+ }
}
+ };
+ for name in reqs {
+ categorize!(self, name, c_flags, c_pos, c_opt, grps);
+ }
+ if let Some(ref name) = extra {
+ categorize!(self, name, c_flags, c_pos, c_opt, grps);
}
macro_rules! fill_vecs {
($_self:ident {
@@ -843,7 +854,7 @@ impl<'a, 'b> Parser<'a, 'b>
arg_os.to_string_lossy().parse::().is_ok()) {
return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
"",
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
} else if !self.is_set(AppSettings::AllowLeadingHyphen) {
@@ -867,7 +878,7 @@ impl<'a, 'b> Parser<'a, 'b>
.bin_name
.as_ref()
.unwrap_or(&self.meta.name),
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
@@ -916,7 +927,7 @@ impl<'a, 'b> Parser<'a, 'b>
Some(s) => s.to_string(),
None => {
if !self.settings.is_set(AppSettings::StrictUtf8) {
- return Err(Error::invalid_utf8(&*self.create_current_usage(matcher),
+ return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None),
self.color()));
}
arg_os.to_string_lossy().into_owned()
@@ -928,7 +939,7 @@ impl<'a, 'b> Parser<'a, 'b>
while let Some(v) = it.next() {
let a = v.into();
if a.to_str().is_none() && !self.settings.is_set(AppSettings::StrictUtf8) {
- return Err(Error::invalid_utf8(&*self.create_current_usage(matcher),
+ return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None),
self.color()));
}
sc_m.add_val_to("", &a);
@@ -942,7 +953,7 @@ impl<'a, 'b> Parser<'a, 'b>
self.is_set(AppSettings::AllowNegativeNumbers)) {
return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
"",
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
@@ -972,7 +983,7 @@ impl<'a, 'b> Parser<'a, 'b>
} else if self.is_set(AppSettings::SubcommandRequired) {
let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name);
return Err(Error::missing_subcommand(bn,
- &self.create_current_usage(matcher),
+ &self.create_current_usage(matcher, None),
self.color()));
} else if self.is_set(AppSettings::SubcommandRequiredElseHelp) {
debugln!("parser::get_matches_with: SubcommandRequiredElseHelp=true");
@@ -995,6 +1006,7 @@ impl<'a, 'b> Parser<'a, 'b>
-> ClapResult<()> {
debugln!("Parser::validate;");
let mut reqs_validated = false;
+ try!(self.add_defaults(matcher));
if let Some(a) = needs_val_of {
debugln!("Parser::validate: needs_val_of={:?}", a);
if let Some(o) = find_by_name!(self, &a, opts, iter) {
@@ -1007,7 +1019,7 @@ impl<'a, 'b> Parser<'a, 'b>
};
if should_err {
return Err(Error::empty_value(o,
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
@@ -1018,7 +1030,6 @@ impl<'a, 'b> Parser<'a, 'b>
!reqs_validated {
try!(self.validate_required(matcher));
}
- try!(self.add_defaults(matcher));
try!(self.validate_matched_args(matcher));
matcher.usage(self.create_usage(&[]));
@@ -1086,7 +1097,7 @@ impl<'a, 'b> Parser<'a, 'b>
for k in matcher.arg_names() {
hs.push(k);
}
- let reqs = self.get_required_from(&hs, Some(matcher));
+ let reqs = self.get_required_from(&hs, Some(matcher), None);
for s in &reqs {
write!(&mut mid_string, " {}", s).expect(INTERNAL_ERROR_MSG);
@@ -1118,8 +1129,8 @@ impl<'a, 'b> Parser<'a, 'b>
""
},
&*sc.p.meta.name));
- println!("Parser::parse_subcommand: About to parse sc={}", sc.p.meta.name);
- println!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings);
+ debugln!("Parser::parse_subcommand: About to parse sc={}", sc.p.meta.name);
+ debugln!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings);
try!(sc.p.get_matches_with(&mut sc_matcher, it));
matcher.subcommand(SubCommand {
name: sc.p.meta.name.clone(),
@@ -1264,8 +1275,8 @@ impl<'a, 'b> Parser<'a, 'b>
// Retrieves the names of all args the user has supplied thus far, except required ones
// because those will be listed in self.required
- pub fn create_current_usage(&self, matcher: &'b ArgMatcher<'a>) -> String {
- self.create_usage(&*matcher.arg_names()
+ pub fn create_current_usage(&self, matcher: &'b ArgMatcher<'a>, extra: Option<&str>) -> String {
+ let mut args: Vec<_> = matcher.arg_names()
.iter()
.filter(|n| {
if let Some(o) = find_by_name!(self, *n, opts, iter) {
@@ -1277,7 +1288,11 @@ impl<'a, 'b> Parser<'a, 'b>
}
})
.map(|&n| n)
- .collect::>())
+ .collect();
+ if let Some(r) = extra {
+ args.push(r);
+ }
+ self.create_usage(&*args)
}
fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> {
@@ -1462,7 +1477,7 @@ impl<'a, 'b> Parser<'a, 'b>
arg.push(c);
return Err(Error::unknown_argument(&*arg,
"",
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
@@ -1485,7 +1500,7 @@ impl<'a, 'b> Parser<'a, 'b>
if !opt.is_set(ArgSettings::EmptyValues) && v.len_() == 0 {
sdebugln!("Found Empty - Error");
return Err(Error::empty_value(opt,
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
sdebugln!("Found - {:?}, len: {}", v, v.len_());
@@ -1579,7 +1594,7 @@ impl<'a, 'b> Parser<'a, 'b>
{
debugln!("Parser::validate_value: val={:?}", val);
if self.is_set(AppSettings::StrictUtf8) && val.to_str().is_none() {
- return Err(Error::invalid_utf8(&*self.create_current_usage(matcher), self.color()));
+ return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None), self.color()));
}
if let Some(p_vals) = arg.possible_vals() {
let val_str = val.to_string_lossy();
@@ -1587,13 +1602,13 @@ impl<'a, 'b> Parser<'a, 'b>
return Err(Error::invalid_value(val_str,
p_vals,
arg,
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_() &&
matcher.contains(&*arg.name()) {
- return Err(Error::empty_value(arg, &*self.create_current_usage(matcher), self.color()));
+ return Err(Error::empty_value(arg, &*self.create_current_usage(matcher, None), self.color()));
}
if let Some(vtor) = arg.validator() {
if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
@@ -1641,7 +1656,7 @@ impl<'a, 'b> Parser<'a, 'b>
);
debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, $name);
$matcher.remove($name);
- let usg = $me.create_current_usage($matcher);
+ let usg = $me.create_current_usage($matcher, None);
if let Some(f) = find_by_name!($me, $name, flags, iter) {
debugln!("build_err!: It was a flag...");
Error::argument_conflict(f, c_with, &*usg, self.color())
@@ -1695,7 +1710,7 @@ impl<'a, 'b> Parser<'a, 'b>
} else if let Some(grp) = self.groups.get(name) {
if let Some(ref g_reqs) = grp.requires {
if g_reqs.iter().any(|&n| !matcher.contains(n)) {
- return self.missing_required_error(matcher);
+ return self.missing_required_error(matcher, None);
}
}
}
@@ -1735,7 +1750,7 @@ impl<'a, 'b> Parser<'a, 'b>
} else {
"ere"
},
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
@@ -1752,7 +1767,7 @@ impl<'a, 'b> Parser<'a, 'b>
.to_str()
.expect(INVALID_UTF8),
a,
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
@@ -1763,13 +1778,13 @@ impl<'a, 'b> Parser<'a, 'b>
return Err(Error::too_few_values(a,
num,
ma.vals.len(),
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()));
}
}
// Issue 665 (https://github.com/kbknapp/clap-rs/issues/665)
if a.takes_value() && !a.is_set(ArgSettings::EmptyValues) && ma.vals.is_empty() {
- return Err(Error::empty_value(a, &*self.create_current_usage(matcher), self.color()));
+ return Err(Error::empty_value(a, &*self.create_current_usage(matcher, None), self.color()));
}
Ok(())
}
@@ -1787,7 +1802,7 @@ impl<'a, 'b> Parser<'a, 'b>
if ma.vals
.values()
.any(|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name)) {
- return self.missing_required_error(matcher);
+ return self.missing_required_error(matcher, None);
}
}
}
@@ -1795,21 +1810,27 @@ impl<'a, 'b> Parser<'a, 'b>
}
#[inline]
- fn missing_required_error(&self, matcher: &ArgMatcher) -> ClapResult<()> {
+ fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> {
+ debugln!("Parser::missing_required_error: extra={:?}", extra);
let c = Colorizer {
use_stderr: true,
when: self.color(),
};
let mut reqs = self.required.iter().map(|&r| &*r).collect::>();
+ if let Some(r) = extra {
+ reqs.push(r);
+ }
reqs.retain(|n| !matcher.contains(n));
reqs.dedup();
- Err(Error::missing_required_argument(&*self.get_required_from(&self.required[..],
- Some(matcher))
+ debugln!("Parser::missing_required_error: reqs={:#?}", reqs);
+ Err(Error::missing_required_argument(&*self.get_required_from(&reqs[..],
+ Some(matcher),
+ extra)
.iter()
.fold(String::new(), |acc, s| {
acc + &format!("\n {}", c.error(s))[..]
}),
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, extra),
self.color()))
}
@@ -1843,7 +1864,7 @@ impl<'a, 'b> Parser<'a, 'b>
continue 'outer;
}
}
- return self.missing_required_error(matcher);
+ return self.missing_required_error(matcher, None);
}
// Validate the conditionally required args
@@ -1851,7 +1872,7 @@ impl<'a, 'b> Parser<'a, 'b>
if let Some(ma) = matcher.get(a) {
for val in ma.vals.values() {
if v == val && matcher.get(r).is_none() {
- return self.missing_required_error(matcher);
+ return self.missing_required_error(matcher, Some(r));
}
}
}
@@ -1923,7 +1944,7 @@ impl<'a, 'b> Parser<'a, 'b>
let used_arg = format!("--{}", arg);
Err(Error::unknown_argument(&*used_arg,
&*suffix.0,
- &*self.create_current_usage(matcher),
+ &*self.create_current_usage(matcher, None),
self.color()))
}
@@ -1957,7 +1978,7 @@ impl<'a, 'b> Parser<'a, 'b>
.unwrap_or(&self.meta.name)));
let mut reqs: Vec<&str> = self.required().map(|r| &**r).collect();
reqs.dedup();
- let req_string = self.get_required_from(&reqs, None)
+ let req_string = self.get_required_from(&reqs, None, None)
.iter()
.fold(String::new(), |a, s| a + &format!(" {}", s)[..]);
@@ -2012,7 +2033,7 @@ impl<'a, 'b> Parser<'a, 'b>
let mut hs: Vec<&str> = self.required().map(|s| &**s).collect();
hs.extend_from_slice(used);
- let r_string = self.get_required_from(&hs, None)
+ let r_string = self.get_required_from(&hs, None, None)
.iter()
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
diff --git a/src/completions/bash.rs b/src/completions/bash.rs
index 47a69e14b6d..ab94865b8e5 100644
--- a/src/completions/bash.rs
+++ b/src/completions/bash.rs
@@ -77,10 +77,10 @@ complete -F _{name} -o bashdefault -o default {name}
for sc in &scs {
subcmds = format!("{}
{name})
- cmd+=\"_{name}\"
+ cmd+=\"__{name}\"
;;",
subcmds,
- name = sc.replace("-", "_"));
+ name = sc.replace("-", "__"));
}
subcmds
@@ -111,9 +111,9 @@ complete -F _{name} -o bashdefault -o default {name}
return 0
;;",
subcmd_dets,
- subcmd = sc.replace("-", "_"),
+ subcmd = sc.replace("-", "__"),
sc_opts = self.all_options_for_path(&*sc),
- level = sc.split("_").map(|_| 1).fold(0, |acc, n| acc + n),
+ level = sc.split("__").map(|_| 1).fold(0, |acc, n| acc + n),
opts_details = self.option_details_for_path(&*sc));
}
@@ -123,7 +123,7 @@ complete -F _{name} -o bashdefault -o default {name}
fn option_details_for_path(&self, path: &str) -> String {
debugln!("BashGen::option_details_for_path: path={}", path);
let mut p = self.p;
- for sc in path.split('_').skip(1) {
+ for sc in path.split("__").skip(1) {
debugln!("BashGen::option_details_for_path:iter: sc={}", sc);
p = &p.subcommands
.iter()
@@ -212,7 +212,7 @@ complete -F _{name} -o bashdefault -o default {name}
fn all_options_for_path(&self, path: &str) -> String {
debugln!("BashGen::all_options_for_path: path={}", path);
let mut p = self.p;
- for sc in path.split('_').skip(1) {
+ for sc in path.split("__").skip(1) {
debugln!("BashGen::all_options_for_path:iter: sc={}", sc);
p = &p.subcommands
.iter()
diff --git a/src/completions/mod.rs b/src/completions/mod.rs
index 8a7c21f1b2f..6d067882bf0 100644
--- a/src/completions/mod.rs
+++ b/src/completions/mod.rs
@@ -125,7 +125,7 @@ pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec {
if !p.has_subcommands() {
if !first {
let name = &*p.meta.name;
- let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "_");
+ let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__");
let mut ret = vec![path.clone()];
if let Some(ref aliases) = p.meta.aliases {
for &(n, _) in aliases {
@@ -138,7 +138,7 @@ pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec {
}
for sc in &p.subcommands {
let name = &*sc.p.meta.name;
- let path = sc.p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "_");
+ let path = sc.p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__");
subcmds.push(path.clone());
if let Some(ref aliases) = sc.p.meta.aliases {
for &(n, _) in aliases {
diff --git a/src/completions/zsh.rs b/src/completions/zsh.rs
index a3bb2fb3bd5..fa84342f8c2 100644
--- a/src/completions/zsh.rs
+++ b/src/completions/zsh.rs
@@ -29,10 +29,10 @@ impl<'a, 'b> ZshGen<'a, 'b> {
#compdef {name}
_{name}() {{
- typeset -A opt_args
- local ret=1
+ typeset -A opt_args
+ local ret=1
- local context curcontext=\"$curcontext\" state line
+ local context curcontext=\"$curcontext\" state line
{initial_args}
{subcommands}
}}
@@ -86,7 +86,7 @@ _{bin_name_underscore}_commands() {{
)
_describe -t commands '{bin_name} commands' commands \"$@\"
}}",
- bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "_"),
+ bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"),
bin_name = p.meta.bin_name.as_ref().unwrap(),
subcommands_and_args = subcommands_and_args_of(p))];
@@ -104,7 +104,7 @@ _{bin_name_underscore}_commands() {{
)
_describe -t commands '{bin_name} commands' commands \"$@\"
}}",
- bin_name_underscore = bin_name.replace(" ", "_"),
+ bin_name_underscore = bin_name.replace(" ", "__"),
bin_name = bin_name,
subcommands_and_args = subcommands_and_args_of(parser_of(p, bin_name))));
}
@@ -265,7 +265,7 @@ fn get_args_of(p: &Parser) -> String {
let flags = write_flags_of(p);
let sc_or_a = if p.has_subcommands() || p.has_positionals() {
format!("\"1:: :_{name}_commands\" \\",
- name = p.meta.bin_name.as_ref().unwrap().replace(" ", "_"))
+ name = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"))
} else {
String::new()
};
diff --git a/src/macros.rs b/src/macros.rs
index 86a2c8eb063..ee43113f737 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -498,6 +498,13 @@ macro_rules! crate_name {
/// Provided separator is for the [`crate_authors!`](macro.crate_authors.html) macro,
/// refer to the documentation therefor.
///
+/// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically,
+/// and therefore won't change the generated output until you recompile.
+///
+/// **Pro Tip:** In some cases you can "trick" the compiler into triggering a rebuild when your
+/// `Cargo.toml` is changed by including this in your `src/main.rs` file
+/// `include_str!("../Cargo.toml");`
+///
/// # Examples
///
/// ```no_run
diff --git a/tests/completions.rs b/tests/completions.rs
index 6aa99f5d7ab..8b4f843ffd0 100644
--- a/tests/completions.rs
+++ b/tests/completions.rs
@@ -1,25 +1,719 @@
-extern crate clap;
-
-use clap::{App, Arg, SubCommand, Shell};
-
-#[test]
-fn test_generation() {
- let mut app = App::new("myapp")
- .about("Tests completions")
- .arg(Arg::with_name("file")
- .help("some input file"))
- .subcommand(SubCommand::with_name("test")
- .about("tests things")
- .arg(Arg::with_name("case")
- .long("case")
- .takes_value(true)
- .help("the case to test")));
- let mut buf = vec![];
- app.gen_completions_to("myapp", Shell::Bash, &mut buf);
- let string = String::from_utf8(buf).unwrap();
- let first_line = string.lines().nth(0).unwrap();
- let last_line = string.lines().rev().nth(0).unwrap();
-
- assert_eq!(first_line, "_myapp() {");
- assert_eq!(last_line, "complete -F _myapp -o bashdefault -o default myapp");
-}
+extern crate regex;
+extern crate clap;
+
+use clap::{App, Arg, SubCommand, Shell};
+use regex::Regex;
+
+static BASH: &'static str = r#"_myapp() {
+ local i cur prev opts cmds
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cmd=""
+ opts=""
+
+ for i in ${COMP_WORDS[@]}
+ do
+ case "${i}" in
+ myapp)
+ cmd="myapp"
+ ;;
+
+ help)
+ cmd+="__help"
+ ;;
+ test)
+ cmd+="__test"
+ ;;
+ *)
+ ;;
+ esac
+ done
+
+ case "${cmd}" in
+ myapp)
+ opts=" -h -V --help --version test help"
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ myapp__help)
+ opts=" -h -V --help --version "
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ myapp__test)
+ opts=" -h -V --case --help --version "
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ --case)
+ COMPREPLY=("")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+}
+
+complete -F _myapp -o bashdefault -o default myapp
+"#;
+
+static ZSH: &'static str = r#"#compdef myapp
+
+_myapp() {
+ typeset -A opt_args
+ local ret=1
+
+ local context curcontext="$curcontext" state line
+ _arguments -s -S -C \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+"1:: :_myapp_commands" \
+"*:: :->myapp" \
+&& ret=0
+ case $state in
+ (myapp)
+ curcontext="${curcontext%:*:*}:myapp-command-$words[1]:"
+ case $line[1] in
+ (test)
+_arguments -s -S -C \
+"--case+[the case to test]" \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+&& ret=0
+;;
+(help)
+_arguments -s -S -C \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+&& ret=0
+;;
+ esac
+ ;;
+esac
+}
+
+(( $+functions[_myapp_commands] )) ||
+_myapp_commands() {
+ local commands; commands=(
+ "test:tests things" \
+"help:Prints this message or the help of the given subcommand(s)" \
+"FILE:some input file" \
+ )
+ _describe -t commands 'myapp commands' commands "$@"
+}
+(( $+functions[_myapp__help_commands] )) ||
+_myapp__help_commands() {
+ local commands; commands=(
+
+ )
+ _describe -t commands 'myapp help commands' commands "$@"
+}
+(( $+functions[_myapp__test_commands] )) ||
+_myapp__test_commands() {
+ local commands; commands=(
+
+ )
+ _describe -t commands 'myapp test commands' commands "$@"
+}
+
+_myapp "$@""#;
+
+static FISH: &'static str = r#"function __fish_using_command
+ set cmd (commandline -opc)
+ if [ (count $cmd) -eq (count $argv) ]
+ for i in (seq (count $argv))
+ if [ $cmd[$i] != $argv[$i] ]
+ return 1
+ end
+ end
+ return 0
+ end
+ return 1
+end
+
+complete -c myapp -n "__fish_using_command myapp" -s h -l help -d "Prints help information"
+complete -c myapp -n "__fish_using_command myapp" -s V -l version -d "Prints version information"
+complete -c myapp -n "__fish_using_command myapp" -f -a "test"
+complete -c myapp -n "__fish_using_command myapp" -f -a "help"
+complete -c myapp -n "__fish_using_command myapp test" -l case -d "the case to test"
+complete -c myapp -n "__fish_using_command myapp test" -s h -l help -d "Prints help information"
+complete -c myapp -n "__fish_using_command myapp test" -s V -l version -d "Prints version information"
+complete -c myapp -n "__fish_using_command myapp help" -s h -l help -d "Prints help information"
+complete -c myapp -n "__fish_using_command myapp help" -s V -l version -d "Prints version information"
+"#;
+
+#[cfg(not(target_os="windows"))]
+static POWERSHELL: &'static str = r#"
+@('myapp', './myapp') | %{
+ Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
+ param($wordToComplete, $commandAst, $cursorPosition)
+
+ $command = '_myapp'
+ $commandAst.CommandElements |
+ Select-Object -Skip 1 |
+ %{
+ switch ($_.ToString()) {
+
+ 'test' {
+ $command += '_test'
+ break
+ }
+
+ 'help' {
+ $command += '_help'
+ break
+ }
+
+ }
+ }
+
+ $completions = @()
+
+ switch ($command) {
+
+ '_myapp' {
+ $completions = @('test', 'help', '-h', '-V', '--help', '--version')
+ }
+
+ '_myapp_test' {
+ $completions = @('-h', '-V', '--case', '--help', '--version')
+ }
+
+ '_myapp_help' {
+ $completions = @('-h', '-V', '--help', '--version')
+ }
+
+ }
+
+ $completions |
+ ?{ $_ -like "$wordToComplete*" } |
+ Sort-Object |
+ %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
+ }
+}
+"#;
+
+#[cfg(target_os="windows")]
+static POWERSHELL: &'static str = r#"
+@('myapp', './myapp', 'myapp.exe', '.\myapp', '.\myapp.exe', './myapp.exe') | %{
+ Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
+ param($wordToComplete, $commandAst, $cursorPosition)
+ $command = '_myapp'
+ $commandAst.CommandElements |
+ Select-Object -Skip 1 |
+ %{
+ switch ($_.ToString()) {
+ 'test' {
+ $command += '_test'
+ break
+ }
+ 'help' {
+ $command += '_help'
+ break
+ }
+ }
+ }
+ $completions = @()
+ switch ($command) {
+ '_myapp' {
+ $completions = @('test', 'help', '-h', '-V', '--help', '--version')
+ }
+ '_myapp_test' {
+ $completions = @('-h', '-V', '--case', '--help', '--version')
+ }
+ '_myapp_help' {
+ $completions = @('-h', '-V', '--help', '--version')
+ }
+ }
+ $completions |
+ ?{ $_ -like "$wordToComplete*" } |
+ Sort-Object |
+ %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
+ }
+}
+"#;
+
+#[cfg(not(target_os="windows"))]
+static POWERSHELL_WUS: &'static str = r#"
+@('my_app', './my_app') | %{
+ Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
+ param($wordToComplete, $commandAst, $cursorPosition)
+
+ $command = '_my_app'
+ $commandAst.CommandElements |
+ Select-Object -Skip 1 |
+ %{
+ switch ($_.ToString()) {
+
+ 'test' {
+ $command += '_test'
+ break
+ }
+
+ 'some_cmd' {
+ $command += '_some_cmd'
+ break
+ }
+
+ 'help' {
+ $command += '_help'
+ break
+ }
+
+ }
+ }
+
+ $completions = @()
+
+ switch ($command) {
+
+ '_my_app' {
+ $completions = @('test', 'some_cmd', 'help', '-h', '-V', '--help', '--version')
+ }
+
+ '_my_app_test' {
+ $completions = @('-h', '-V', '--case', '--help', '--version')
+ }
+
+ '_my_app_some_cmd' {
+ $completions = @('-h', '-V', '--config', '--help', '--version')
+ }
+
+ '_my_app_help' {
+ $completions = @('-h', '-V', '--help', '--version')
+ }
+
+ }
+
+ $completions |
+ ?{ $_ -like "$wordToComplete*" } |
+ Sort-Object |
+ %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
+ }
+}
+"#;
+
+#[cfg(target_os="windows")]
+static POWERSHELL_WUS: &'static str = r#"
+@('my_app', './my_app', 'my_app.exe', '.\my_app', '.\my_app.exe', './my_app.exe') | %{
+ Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
+ param($wordToComplete, $commandAst, $cursorPosition)
+ $command = '_my_app'
+ $commandAst.CommandElements |
+ Select-Object -Skip 1 |
+ %{
+ switch ($_.ToString()) {
+ 'test' {
+ $command += '_test'
+ break
+ }
+ 'some_cmd' {
+ $command += '_some_cmd'
+ break
+ }
+ 'help' {
+ $command += '_help'
+ break
+ }
+ }
+ }
+ $completions = @()
+ switch ($command) {
+ '_my_app' {
+ $completions = @('test', 'some_cmd', 'help', '-h', '-V', '--help', '--version')
+ }
+ '_my_app_test' {
+ $completions = @('-h', '-V', '--case', '--help', '--version')
+ }
+ '_my_app_some_cmd' {
+ $completions = @('-h', '-V', '--config', '--help', '--version')
+ }
+ '_my_app_help' {
+ $completions = @('-h', '-V', '--help', '--version')
+ }
+ }
+ $completions |
+ ?{ $_ -like "$wordToComplete*" } |
+ Sort-Object |
+ %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
+ }
+}
+"#;
+
+static ZSH_WUS: &'static str = r#"#compdef my_app
+
+_my_app() {
+ typeset -A opt_args
+ local ret=1
+
+ local context curcontext="$curcontext" state line
+ _arguments -s -S -C \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+"1:: :_my_app_commands" \
+"*:: :->my_app" \
+&& ret=0
+ case $state in
+ (my_app)
+ curcontext="${curcontext%:*:*}:my_app-command-$words[1]:"
+ case $line[1] in
+ (test)
+_arguments -s -S -C \
+"--case+[the case to test]" \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+&& ret=0
+;;
+(some_cmd)
+_arguments -s -S -C \
+"--config+[the other case to test]" \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+&& ret=0
+;;
+(help)
+_arguments -s -S -C \
+"-h[Prints help information]" \
+"--help[Prints help information]" \
+"-V[Prints version information]" \
+"--version[Prints version information]" \
+&& ret=0
+;;
+ esac
+ ;;
+esac
+}
+
+(( $+functions[_my_app_commands] )) ||
+_my_app_commands() {
+ local commands; commands=(
+ "test:tests things" \
+"some_cmd:tests other things" \
+"help:Prints this message or the help of the given subcommand(s)" \
+"FILE:some input file" \
+ )
+ _describe -t commands 'my_app commands' commands "$@"
+}
+(( $+functions[_my_app__help_commands] )) ||
+_my_app__help_commands() {
+ local commands; commands=(
+
+ )
+ _describe -t commands 'my_app help commands' commands "$@"
+}
+(( $+functions[_my_app__some_cmd_commands] )) ||
+_my_app__some_cmd_commands() {
+ local commands; commands=(
+
+ )
+ _describe -t commands 'my_app some_cmd commands' commands "$@"
+}
+(( $+functions[_my_app__test_commands] )) ||
+_my_app__test_commands() {
+ local commands; commands=(
+
+ )
+ _describe -t commands 'my_app test commands' commands "$@"
+}
+
+_my_app "$@""#;
+
+static FISH_WUS: &'static str = r#"function __fish_using_command
+ set cmd (commandline -opc)
+ if [ (count $cmd) -eq (count $argv) ]
+ for i in (seq (count $argv))
+ if [ $cmd[$i] != $argv[$i] ]
+ return 1
+ end
+ end
+ return 0
+ end
+ return 1
+end
+
+complete -c my_app -n "__fish_using_command my_app" -s h -l help -d "Prints help information"
+complete -c my_app -n "__fish_using_command my_app" -s V -l version -d "Prints version information"
+complete -c my_app -n "__fish_using_command my_app" -f -a "test"
+complete -c my_app -n "__fish_using_command my_app" -f -a "some_cmd"
+complete -c my_app -n "__fish_using_command my_app" -f -a "help"
+complete -c my_app -n "__fish_using_command my_app test" -l case -d "the case to test"
+complete -c my_app -n "__fish_using_command my_app test" -s h -l help -d "Prints help information"
+complete -c my_app -n "__fish_using_command my_app test" -s V -l version -d "Prints version information"
+complete -c my_app -n "__fish_using_command my_app some_cmd" -l config -d "the other case to test"
+complete -c my_app -n "__fish_using_command my_app some_cmd" -s h -l help -d "Prints help information"
+complete -c my_app -n "__fish_using_command my_app some_cmd" -s V -l version -d "Prints version information"
+complete -c my_app -n "__fish_using_command my_app help" -s h -l help -d "Prints help information"
+complete -c my_app -n "__fish_using_command my_app help" -s V -l version -d "Prints version information"
+"#;
+
+static BASH_WUS: &'static str = r#"_my_app() {
+ local i cur prev opts cmds
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cmd=""
+ opts=""
+
+ for i in ${COMP_WORDS[@]}
+ do
+ case "${i}" in
+ my_app)
+ cmd="my_app"
+ ;;
+
+ help)
+ cmd+="__help"
+ ;;
+ some_cmd)
+ cmd+="__some_cmd"
+ ;;
+ test)
+ cmd+="__test"
+ ;;
+ *)
+ ;;
+ esac
+ done
+
+ case "${cmd}" in
+ my_app)
+ opts=" -h -V --help --version test some_cmd help"
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+
+ my_app__help)
+ opts=" -h -V --help --version "
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ my_app__some_cmd)
+ opts=" -h -V --config --help --version "
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ --config)
+ COMPREPLY=("")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ my_app__test)
+ opts=" -h -V --case --help --version "
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ fi
+ case "${prev}" in
+
+ --case)
+ COMPREPLY=("")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+}
+
+complete -F _my_app -o bashdefault -o default my_app
+"#;
+
+fn compare(left: &str, right: &str) -> bool {
+ let b = left == right;
+ if !b {
+ let re = Regex::new(" ").unwrap();
+ println!("");
+ println!("--> left");
+ // println!("{}", left);
+ println!("{}", re.replace_all(left, "\u{2022}"));
+ println!("--> right");
+ println!("{}", re.replace_all(right, "\u{2022}"));
+ // println!("{}", right);
+ println!("--")
+ }
+ b
+}
+
+fn build_app() -> App<'static, 'static> {
+ build_app_with_name("myapp")
+}
+
+fn build_app_with_name(s: &'static str) -> App<'static, 'static> {
+ App::new(s)
+ .about("Tests completions")
+ .arg(Arg::with_name("file")
+ .help("some input file"))
+ .subcommand(SubCommand::with_name("test")
+ .about("tests things")
+ .arg(Arg::with_name("case")
+ .long("case")
+ .takes_value(true)
+ .help("the case to test")))
+}
+
+fn build_app_with_underscore() -> App<'static, 'static> {
+ build_app_with_name("my_app")
+ .subcommand(SubCommand::with_name("some_cmd")
+ .about("tests other things")
+ .arg(Arg::with_name("config")
+ .long("--config")
+ .takes_value(true)
+ .help("the other case to test")))
+}
+
+#[test]
+fn bash() {
+ let mut app = build_app();
+ let mut buf = vec![];
+ app.gen_completions_to("myapp", Shell::Bash, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, BASH));
+}
+
+#[test]
+fn zsh() {
+ let mut app = build_app();
+ let mut buf = vec![];
+ app.gen_completions_to("myapp", Shell::Zsh, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, ZSH));
+}
+
+#[test]
+fn fish() {
+ let mut app = build_app();
+ let mut buf = vec![];
+ app.gen_completions_to("myapp", Shell::Fish, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, FISH));
+}
+
+// Disabled until I figure out this windows line ending and AppVeyor issues
+//#[test]
+fn powershell() {
+ let mut app = build_app();
+ let mut buf = vec![];
+ app.gen_completions_to("myapp", Shell::PowerShell, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, POWERSHELL));
+}
+
+// Disabled until I figure out this windows line ending and AppVeyor issues
+//#[test]
+fn powershell_with_underscore() {
+ let mut app = build_app_with_underscore();
+ let mut buf = vec![];
+ app.gen_completions_to("my_app", Shell::PowerShell, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, POWERSHELL_WUS));
+}
+
+#[test]
+fn bash_with_underscore() {
+ let mut app = build_app_with_underscore();
+ let mut buf = vec![];
+ app.gen_completions_to("my_app", Shell::Bash, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, BASH_WUS));
+}
+
+#[test]
+fn fish_with_underscore() {
+ let mut app = build_app_with_underscore();
+ let mut buf = vec![];
+ app.gen_completions_to("my_app", Shell::Fish, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, FISH_WUS));
+}
+
+#[test]
+fn zsh_with_underscore() {
+ let mut app = build_app_with_underscore();
+ let mut buf = vec![];
+ app.gen_completions_to("my_app", Shell::Zsh, &mut buf);
+ let string = String::from_utf8(buf).unwrap();
+
+ assert!(compare(&*string, ZSH_WUS));
+}
\ No newline at end of file
diff --git a/tests/default_vals.rs b/tests/default_vals.rs
index ce6769ffbd6..17cbf443d5d 100644
--- a/tests/default_vals.rs
+++ b/tests/default_vals.rs
@@ -3,7 +3,7 @@ extern crate regex;
include!("../clap-test.rs");
-use clap::{App, Arg};
+use clap::{App, Arg, ErrorKind};
#[test]
fn opts() {
@@ -316,4 +316,56 @@ fn default_ifs_arg_present_order() {
let m = r.unwrap();
assert!(m.is_present("arg"));
assert_eq!(m.value_of("arg").unwrap(), "default");
+}
+
+#[test]
+fn conditional_reqs_fail() {
+ let m = App::new("Test app")
+ .version("1.0")
+ .author("F0x06")
+ .about("Arg test")
+ .arg(Arg::with_name("target")
+ .takes_value(true)
+ .default_value("file")
+ .possible_values(&["file", "stdout"])
+ .long("target"))
+ .arg(Arg::with_name("input")
+ .takes_value(true)
+ .required(true)
+ .long("input"))
+ .arg(Arg::with_name("output")
+ .takes_value(true)
+ .required_if("target", "file")
+ .long("output"))
+ .get_matches_from_safe(vec!["test", "--input", "some"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn conditional_reqs_pass() {
+ let m = App::new("Test app")
+ .version("1.0")
+ .author("F0x06")
+ .about("Arg test")
+ .arg(Arg::with_name("target")
+ .takes_value(true)
+ .default_value("file")
+ .possible_values(&["file", "stdout"])
+ .long("target"))
+ .arg(Arg::with_name("input")
+ .takes_value(true)
+ .required(true)
+ .long("input"))
+ .arg(Arg::with_name("output")
+ .takes_value(true)
+ .required_if("target", "file")
+ .long("output"))
+ .get_matches_from_safe(vec!["test", "--input", "some", "--output", "other"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+ assert_eq!(m.value_of("output"), Some("other"));
+ assert_eq!(m.value_of("input"), Some("some"));
}
\ No newline at end of file
diff --git a/tests/require.rs b/tests/require.rs
index 987c45a032a..f8eb4105823 100644
--- a/tests/require.rs
+++ b/tests/require.rs
@@ -14,11 +14,18 @@ USAGE:
For more information try --help";
+static COND_REQ_IN_USAGE: &'static str = "error: The following required arguments were not provided:
+ --output