From 94003db4b5eebe552ca337521c1c001295822745 Mon Sep 17 00:00:00 2001 From: Kevin K Date: Mon, 7 Sep 2015 17:35:37 -0400 Subject: [PATCH] feat: adds abiltiy not consume self when parsing matches and/or exit on help --- src/app/app.rs | 53 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/app/app.rs b/src/app/app.rs index 5b9dd1d8e98..2a29f0919c9 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -1924,8 +1924,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ matches } - /// Starts the parsing process. Called on top level parent app **ONLY** then recursively calls - /// the real parsing function for all subcommands + /// Starts the parsing process without consuming the `App` struct `self`. This is normally not + /// the desired functionality, instead prefer `App::get_matches_from_safe` which *does* + /// consume `self`. /// /// **NOTE:** The first argument will be parsed as the binary name. /// @@ -1936,21 +1937,20 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ /// **NOTE:** This method should only be used when is absolutely necessary to handle errors /// manually. /// - /// /// # Example /// /// ```no_run /// # use clap::{App, Arg}; /// let arg_vec = vec!["my_prog", "some", "args", "to", "parse"]; /// - /// let matches = App::new("myprog") + /// let mut app = App::new("myprog"); /// // Args and options go here... - /// .get_matches_from_safe(arg_vec) + /// let matches = app.get_matches_from_safe_borrow(arg_vec) /// .unwrap_or_else( |e| { panic!("An error occurs: {}", e) }); /// ``` - pub fn get_matches_from_safe(mut self, - itr: I) - -> Result, ClapError> + pub fn get_matches_from_safe_borrow(&mut self, + itr: I) + -> Result, ClapError> where I: IntoIterator, T: AsRef { @@ -1987,6 +1987,39 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ Ok(matches) } + /// Starts the parsing process. Called on top level parent app **ONLY** then recursively calls + /// the real parsing function for all subcommands + /// + /// **NOTE:** The first argument will be parsed as the binary name. + /// + /// **NOTE:** This method should only be used when absolutely necessary, such as needing to + /// parse arguments from something other than `std::env::args()`. If you are unsure, use + /// `App::get_matches_safe()` + /// + /// **NOTE:** This method should only be used when is absolutely necessary to handle errors + /// manually. + /// + /// + /// # Example + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// let arg_vec = vec!["my_prog", "some", "args", "to", "parse"]; + /// + /// let matches = App::new("myprog") + /// // Args and options go here... + /// .get_matches_from_safe(arg_vec) + /// .unwrap_or_else( |e| { panic!("An error occurs: {}", e) }); + /// ``` + pub fn get_matches_from_safe(mut self, + itr: I) + -> Result, ClapError> + where I: IntoIterator, + T: AsRef + { + self.get_matches_from_safe_borrow(itr) + } + fn verify_positionals(&mut self) { // Because you must wait until all arguments have been supplied, this is the first chance // to make assertions on positional argument indexes @@ -2251,7 +2284,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ // may be trying to pass might match a subcommand name if !pos_only { if self.subcommands.contains_key(arg_slice) { - if arg_slice == "help" { + if arg_slice == "help" && self.needs_subcmd_help { self.print_help(); } subcmd_name = Some(arg_slice.to_owned()); @@ -2343,7 +2376,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ vals.insert(len, arg_slice.to_owned()); } } - } else { // Only increment the positional counter if it doesn't allow multiples pos_counter += 1; @@ -2407,7 +2439,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ parse_group_reqs!(self, p); } - } else { return Err(self.report_error(format!("The argument '{}' was found, but '{}' \ wasn't expecting any", Format::Warning(arg.as_ref()),