diff --git a/CHANGELOG.md b/CHANGELOG.md
index c9fd51763f2..8ab45d94e81 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,10 +4,9 @@
#### Bug Fixes
-* adds support for building ArgGroups from standalone YAML ([bbed7388](https://github.com/kbknapp/clap-rs/commit/bbed73889d8f241d493c9ef18ac5926856df1c24))
+* adds support for building ArgGroups from standalone YAML ([fcbc7e12](https://github.com/kbknapp/clap-rs/commit/fcbc7e12f5d7b023b8f30cba8cad28a01cf6cd26))
* Stop lonely hyphens from causing panic ([85b11468](https://github.com/kbknapp/clap-rs/commit/85b11468b0189d5cc15f1cfac5db40d17a0077dc), closes [#410](https://github.com/kbknapp/clap-rs/issues/410))
-* fixes cargo features to NOT require nightly with unstable features ([8c72e779](https://github.com/kbknapp/clap-rs/commit/8c72e77975e31fb8268cc2f34565f2e693eba935))
-
+* **AppSettings:** fixes bug where subcmds didn't receive parent ver ([a62e4527](https://github.com/kbknapp/clap-rs/commit/a62e452754b3b0e3ac9a15aa8b5330636229ead1))
### v2.0.3 (2016-02-02)
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 9026434661d..46497ef0bad 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -50,7 +50,11 @@ use errors::Result as ClapResult;
/// // Your program logic starts here...
/// ```
#[allow(missing_debug_implementations)]
-pub struct App<'a, 'b>(Parser<'a, 'b>) where 'a: 'b;
+pub struct App<'a, 'b> where 'a: 'b {
+ #[doc(hidden)]
+ pub p: Parser<'a, 'b>
+}
+
impl<'a, 'b> App<'a, 'b> {
/// Creates a new instance of an application requiring a name. The name may be, but doesn't
@@ -64,7 +68,7 @@ impl<'a, 'b> App<'a, 'b> {
/// let prog = App::new("My Program")
/// # ;
/// ```
- pub fn new>(n: S) -> Self { App(Parser::with_name(n.into())) }
+ pub fn new>(n: S) -> Self { App { p: Parser::with_name(n.into()) } }
/// Creates a new instace of `App` from a .yml (YAML) file. A full example of supported YAML
/// objects can be found in `examples/17_yaml.rs` and `examples/17_yaml.yml`. One great use for
@@ -114,7 +118,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn author>(mut self, author: S) -> Self {
- self.0.meta.author = Some(author.into());
+ self.p.meta.author = Some(author.into());
self
}
@@ -136,7 +140,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn bin_name>(mut self, name: S) -> Self {
- self.0.meta.bin_name = Some(name.into());
+ self.p.meta.bin_name = Some(name.into());
self
}
@@ -152,7 +156,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn about>(mut self, about: S) -> Self {
- self.0.meta.about = Some(about.into());
+ self.p.meta.about = Some(about.into());
self
}
@@ -169,7 +173,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn after_help>(mut self, help: S) -> Self {
- self.0.meta.more_help = Some(help.into());
+ self.p.meta.more_help = Some(help.into());
self
}
@@ -189,7 +193,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn version>(mut self, ver: S) -> Self {
- self.0.meta.version = Some(ver.into());
+ self.p.meta.version = Some(ver.into());
self
}
@@ -217,7 +221,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn usage>(mut self, usage: S) -> Self {
- self.0.meta.usage_str = Some(usage.into());
+ self.p.meta.usage_str = Some(usage.into());
self
}
@@ -255,7 +259,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn help>(mut self, help: S) -> Self {
- self.0.meta.help_str = Some(help.into());
+ self.p.meta.help_str = Some(help.into());
self
}
@@ -277,7 +281,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn help_short + 'b>(mut self, s: S) -> Self {
- self.0.help_short(s.as_ref());
+ self.p.help_short(s.as_ref());
self
}
@@ -299,7 +303,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn version_short>(mut self, s: S) -> Self {
- self.0.version_short(s.as_ref());
+ self.p.version_short(s.as_ref());
self
}
@@ -317,7 +321,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn setting(mut self, setting: AppSettings) -> Self {
- self.0.set(setting);
+ self.p.set(setting);
self
}
@@ -336,7 +340,7 @@ impl<'a, 'b> App<'a, 'b> {
/// ```
pub fn settings(mut self, settings: &[AppSettings]) -> Self {
for s in settings {
- self.0.set(*s);
+ self.p.set(*s);
}
self
}
@@ -362,7 +366,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn arg> + 'a>(mut self, a: A) -> Self {
- self.0.add_arg(a.borrow());
+ self.p.add_arg(a.borrow());
self
}
@@ -381,7 +385,7 @@ impl<'a, 'b> App<'a, 'b> {
/// ```
pub fn args(mut self, args: &[Arg<'a, 'b>]) -> Self {
for arg in args {
- self.0.add_arg(arg);
+ self.p.add_arg(arg);
}
self
}
@@ -401,7 +405,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn arg_from_usage(mut self, usage: &'a str) -> Self {
- self.0.add_arg(&Arg::from_usage(usage));
+ self.p.add_arg(&Arg::from_usage(usage));
self
}
@@ -426,7 +430,7 @@ impl<'a, 'b> App<'a, 'b> {
pub fn args_from_usage(mut self, usage: &'a str) -> Self {
for l in usage.lines() {
if l.len() == 0 { continue; }
- self.0.add_arg(&Arg::from_usage(l.trim()));
+ self.p.add_arg(&Arg::from_usage(l.trim()));
}
self
}
@@ -464,7 +468,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn group(mut self, group: ArgGroup<'a>) -> Self {
- self.0.add_group(group);
+ self.p.add_group(group);
self
}
@@ -514,7 +518,7 @@ impl<'a, 'b> App<'a, 'b> {
/// # ;
/// ```
pub fn subcommand(mut self, subcmd: App<'a, 'b>) -> Self {
- self.0.add_subcommand(subcmd);
+ self.p.add_subcommand(subcmd);
self
}
@@ -536,7 +540,7 @@ impl<'a, 'b> App<'a, 'b> {
where I: IntoIterator- >
{
for subcmd in subcmds.into_iter() {
- self.0.add_subcommand(subcmd);
+ self.p.add_subcommand(subcmd);
}
self
}
@@ -569,7 +573,7 @@ impl<'a, 'b> App<'a, 'b> {
/// app.write_help(&mut out).ok().expect("failed to write to stdout");
/// ```
pub fn write_help(&self, w: &mut W) -> ClapResult<()> {
- self.0.write_help(w)
+ self.p.write_help(w)
}
/// Starts the parsing process, upon a failed parse an error will be displayed to the user and
@@ -690,10 +694,10 @@ impl<'a, 'b> App<'a, 'b> {
T: Into
{
// Verify all positional assertions pass
- self.0.verify_positionals();
+ self.p.verify_positionals();
// If there are global arguments, we need to propgate them down to subcommands
// before parsing incase we run into a subcommand
- self.0.propogate_globals();
+ self.p.propogate_globals();
let mut matcher = ArgMatcher::new();
@@ -705,14 +709,14 @@ impl<'a, 'b> App<'a, 'b> {
// will have two arguments, './target/release/my_prog', '-a' but we don't want
// to display
// the full path when displaying help messages and such
- if !self.0.is_set(AppSettings::NoBinaryName) {
+ if !self.p.is_set(AppSettings::NoBinaryName) {
if let Some(name) = it.next() {
let bn_os = name.into();
let p = Path::new(&*bn_os);
if let Some(f) = p.file_name() {
if let Some(s) = f.to_os_string().to_str() {
- if let None = self.0.meta.bin_name {
- self.0.meta.bin_name = Some(s.to_owned());
+ if let None = self.p.meta.bin_name {
+ self.p.meta.bin_name = Some(s.to_owned());
}
}
}
@@ -720,7 +724,7 @@ impl<'a, 'b> App<'a, 'b> {
}
// do the real parsing
- if let Err(e) = self.0.get_matches_with(&mut matcher, &mut it) {
+ if let Err(e) = self.p.get_matches_with(&mut matcher, &mut it) {
return Err(e);
}
@@ -732,7 +736,7 @@ impl<'a, 'b> App<'a, 'b> {
fn maybe_wait_for_exit(&self, e: Error) -> ! {
if e.use_stderr() {
wlnerr!("{}", e.message);
- if self.0.is_set(AppSettings::WaitOnError) {
+ if self.p.is_set(AppSettings::WaitOnError) {
wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
let mut s = String::new();
let i = io::stdin();
diff --git a/src/app/parser.rs b/src/app/parser.rs
index ec408d86dd9..a1f3e39621f 100644
--- a/src/app/parser.rs
+++ b/src/app/parser.rs
@@ -37,14 +37,14 @@ pub struct Parser<'a, 'b> where 'a: 'b {
// A list of positional arguments
positionals: VecMap>,
// A list of subcommands
- subcommands: Vec>,
+ #[doc(hidden)]
+ pub subcommands: Vec>,
groups: HashMap<&'a str, ArgGroup<'a>>,
global_args: Vec>,
overrides: Vec<&'b str>,
help_short: Option,
version_short: Option,
settings: AppFlags,
- version: Option<&'b str>,
pub meta: AppMeta<'b>,
}
@@ -65,7 +65,6 @@ impl<'a, 'b> Default for Parser<'a, 'b> {
global_args: vec![],
overrides: vec![],
settings: AppFlags::new(),
- version: None,
meta: AppMeta::new(),
}
}
@@ -192,16 +191,24 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
}
pub fn add_subcommand(&mut self, mut subcmd: App<'a, 'b>) {
- if subcmd.0.meta.name == "help" {
+ debugln!("fn=Parser::add_subcommand;");
+ debug!("Is help...");
+ if subcmd.p.meta.name == "help" {
+ sdebugln!("Yes");
self.settings.set(AppSettings::NeedsSubcommandHelp);
- }
+ } else { sdebugln!("No"); }
+ debug!("Using Setting VersionlessSubcommands...");
if self.settings.is_set(AppSettings::VersionlessSubcommands) {
- subcmd.0.settings.set(AppSettings::DisableVersion);
- }
- if self.settings.is_set(AppSettings::GlobalVersion) && subcmd.0.meta.version.is_none() &&
- self.version.is_some() {
- subcmd.0.meta.version = Some(self.version.unwrap());
- }
+ sdebugln!("Yes");
+ subcmd.p.settings.set(AppSettings::DisableVersion);
+ } else { sdebugln!("No"); }
+ debug!("Using Setting GlobalVersion...");
+ if self.settings.is_set(AppSettings::GlobalVersion) && subcmd.p.meta.version.is_none() &&
+ self.meta.version.is_some() {
+ sdebugln!("Yes");
+ subcmd = subcmd.setting(AppSettings::GlobalVersion)
+ .version(self.meta.version.unwrap());
+ } else { sdebugln!("No"); }
self.subcommands.push(subcmd);
}
@@ -386,10 +393,10 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
// done and to recursively call this method
{
for a in &self.global_args {
- sc.0.add_arg(a);
+ sc.p.add_arg(a);
}
}
- sc.0.propogate_globals();
+ sc.p.propogate_globals();
}
}
@@ -427,7 +434,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
// Has the user already passed '--'?
if !pos_only {
- let pos_sc = self.subcommands.iter().any(|s| &s.0.meta.name[..] == &*arg_os);
+ let pos_sc = self.subcommands.iter().any(|s| &s.p.meta.name[..] == &*arg_os);
if (!starts_new_arg || self.is_set(AppSettings::AllowLeadingHyphen)) && !pos_sc {
// Check to see if parsing a value from an option
if let Some(nvo) = needs_val_of {
@@ -465,7 +472,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
break;
} else if let Some(candidate) = suggestions::did_you_mean(
&*arg_os.to_string_lossy(),
- self.subcommands.iter().map(|s| &s.0.meta.name)) {
+ self.subcommands.iter().map(|s| &s.p.meta.name)) {
return Err(
Error::invalid_subcommand(arg_os.to_string_lossy().into_owned(),
candidate,
@@ -584,30 +591,30 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
mid_string.push_str(" ");
if let Some(ref mut sc) = self.subcommands
.iter_mut()
- .filter(|s| &s.0.meta.name == &sc_name)
+ .filter(|s| &s.p.meta.name == &sc_name)
.next() {
let mut sc_matcher = ArgMatcher::new();
// bin_name should be parent's bin_name + [] + the sc's name separated by
// a space
- sc.0.meta.usage = Some(format!("{}{}{}",
+ sc.p.meta.usage = Some(format!("{}{}{}",
self.meta.bin_name.as_ref().unwrap_or(&String::new()),
if self.meta.bin_name.is_some() {
&*mid_string
} else {
""
},
- &*sc.0.meta.name));
- sc.0.meta.bin_name = Some(format!("{}{}{}",
+ &*sc.p.meta.name));
+ sc.p.meta.bin_name = Some(format!("{}{}{}",
self.meta.bin_name.as_ref().unwrap_or(&String::new()),
if self.meta.bin_name.is_some() {
" "
} else {
""
},
- &*sc.0.meta.name));
- try!(sc.0.get_matches_with(&mut sc_matcher, it));
+ &*sc.p.meta.name));
+ try!(sc.p.get_matches_with(&mut sc_matcher, it));
matcher.subcommand(SubCommand {
- name: sc.0.meta.name.clone(),
+ name: sc.p.meta.name.clone(),
matches: sc_matcher.into(),
});
}
@@ -783,7 +790,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
if !self.subcommands.is_empty() &&
!self.subcommands
.iter()
- .any(|s| &s.0.meta.name[..] == "help") {
+ .any(|s| &s.p.meta.name[..] == "help") {
self.subcommands.push(App::new("help").about("Prints this message"));
}
}
@@ -1445,8 +1452,8 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
let mut longest_sc = 0;
for scl in self.subcommands
.iter()
- .filter(|s| !s.0.is_set(AppSettings::Hidden))
- .map(|s| s.0.meta.name.len()) {
+ .filter(|s| !s.p.is_set(AppSettings::Hidden))
+ .map(|s| s.p.meta.name.len()) {
if scl > longest_sc {
longest_sc = scl;
}
@@ -1509,12 +1516,12 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
if subcmds {
try!(write!(w, "\nSUBCOMMANDS:\n"));
for (name, sc) in self.subcommands.iter()
- .filter(|s| !s.0.is_set(AppSettings::Hidden))
- .map(|s| (&s.0.meta.name[..], s))
+ .filter(|s| !s.p.is_set(AppSettings::Hidden))
+ .map(|s| (&s.p.meta.name[..], s))
.collect::>() {
try!(write!(w, "{}{}", tab, name));
write_spaces!((longest_sc + 4) - (name.len()), w);
- if let Some(a) = sc.0.meta.about {
+ if let Some(a) = sc.p.meta.about {
if a.contains("{n}") {
let mut ab = a.split("{n}");
while let Some(part) = ab.next() {
diff --git a/tests/app_settings.rs b/tests/app_settings.rs
index da9228be9d3..6ffbb7559cf 100644
--- a/tests/app_settings.rs
+++ b/tests/app_settings.rs
@@ -13,6 +13,15 @@ fn sub_command_negate_required() {
.get_matches_from(vec!["myprog", "sub1"]);
}
+#[test]
+fn global_version() {
+ let app = App::new("global_version")
+ .setting(AppSettings::GlobalVersion)
+ .version("1.1")
+ .subcommand(SubCommand::with_name("sub1"));
+ assert_eq!(app.p.subcommands[0].p.meta.version, Some("1.1"));
+}
+
#[test]
fn sub_command_negate_required_2() {
let result = App::new("sub_command_negate")
@@ -145,8 +154,7 @@ fn app_settings_fromstr() {
assert_eq!("strictutf8".parse::().unwrap(), AppSettings::StrictUtf8);
assert_eq!("allowinvalidutf8".parse::().unwrap(), AppSettings::AllowInvalidUtf8);
assert_eq!("allowleadinghyphen".parse::().unwrap(), AppSettings::AllowLeadingHyphen);
- assert_eq!("hidepossiblevaluesinhelp".parse::().unwrap(), AppSettings::HidePossibleValuesInHelp);
+ assert_eq!("hidepossiblevaluesinhelp".parse::().unwrap(), AppSettings::HidePossibleValuesInHelp);
assert_eq!("hidden".parse::().unwrap(), AppSettings::Hidden);
assert!("hahahaha".parse::().is_err());
}
-