mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
fix(Safe Matches): using 'safe' forms of the get_matches family no longer exit the process
Closes #256
This commit is contained in:
parent
c9a9548a8f
commit
c47025dca2
5 changed files with 108 additions and 10 deletions
|
@ -1670,7 +1670,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
// Callers still use &[""]
|
||||
assert_eq!(data.len(), 1);
|
||||
"Invalid unicode character in one or more arguments".to_owned()
|
||||
}
|
||||
},
|
||||
// HelpDisplayed, VersionDisplayed
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
ClapError {
|
||||
|
@ -1741,6 +1743,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
/// Starts the parsing process. Called on top level parent app **ONLY** then recursively calls
|
||||
/// the real parsing function for all subcommands
|
||||
///
|
||||
/// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are
|
||||
/// used. It will return an error, where the `error_type` is a `ClapErrorType::HelpDisplayed`
|
||||
/// or `ClapErrorType::VersionDisplayed` respectively. You must call `error.exit()` or
|
||||
/// perform a `std::process::exit` yourself.
|
||||
///
|
||||
/// **NOTE:** This method should only be used when is absolutely necessary to handle errors
|
||||
/// manually.
|
||||
///
|
||||
|
@ -1763,6 +1770,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
/// the real parsing function for all subcommands. Invalid unicode characters are replaced with
|
||||
/// `U+FFFD REPLACEMENT CHARACTER`
|
||||
///
|
||||
/// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are
|
||||
/// used. It will return an error, where the `error_type` is a `ClapErrorType::HelpDisplayed`
|
||||
/// or `ClapErrorType::VersionDisplayed` respectively. You must call `error.exit()` or
|
||||
/// perform a `std::process::exit` yourself.
|
||||
///
|
||||
/// **NOTE:** This method should only be used when is absolutely necessary to handle errors
|
||||
/// manually.
|
||||
///
|
||||
|
@ -1809,6 +1821,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
match self.get_matches_from_safe_borrow(itr) {
|
||||
Ok(m) => return m,
|
||||
Err(e) => {
|
||||
match e.error_type {
|
||||
ClapErrorType::HelpDisplayed | ClapErrorType::VersionDisplayed => e.exit(),
|
||||
_ => ()
|
||||
}
|
||||
wlnerr!("{}", e.error);
|
||||
if self.settings.is_set(&AppSettings::WaitOnError) {
|
||||
wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
|
||||
|
@ -1850,6 +1866,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
match self.get_matches_from_safe_borrow_lossy(itr) {
|
||||
Ok(m) => return m,
|
||||
Err(e) => {
|
||||
match e.error_type {
|
||||
ClapErrorType::HelpDisplayed | ClapErrorType::VersionDisplayed => e.exit(),
|
||||
_ => ()
|
||||
}
|
||||
wlnerr!("{}", e.error);
|
||||
if self.settings.is_set(&AppSettings::WaitOnError) {
|
||||
wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
|
||||
|
@ -1865,6 +1885,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
/// Starts the parsing process. Called on top level parent app **ONLY** then recursively calls
|
||||
/// the real parsing function for all subcommands
|
||||
///
|
||||
/// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are
|
||||
/// used. It will return an error, where the `error_type` is a `ClapErrorType::HelpDisplayed`
|
||||
/// or `ClapErrorType::VersionDisplayed` respectively. You must call `error.exit()` or
|
||||
/// perform a `std::process::exit` yourself.
|
||||
///
|
||||
/// **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
|
||||
|
@ -1901,6 +1926,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
/// the real parsing function for all subcommands. Invalid unicode characters are replaced with
|
||||
/// `U+FFFD REPLACEMENT CHARACTER`
|
||||
///
|
||||
/// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are
|
||||
/// used. It will return an error, where the `error_type` is a `ClapErrorType::HelpDisplayed`
|
||||
/// or `ClapErrorType::VersionDisplayed` respectively. You must call `error.exit()` or
|
||||
/// perform a `std::process::exit` yourself.
|
||||
///
|
||||
/// **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
|
||||
|
@ -2292,7 +2322,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
error_type: ClapErrorType::MissingSubcommand
|
||||
});
|
||||
}
|
||||
process::exit(0);
|
||||
// process::exit(0);
|
||||
return Err(ClapError{
|
||||
error: String::new(),
|
||||
error_type: ClapErrorType::HelpDisplayed
|
||||
})
|
||||
}
|
||||
subcmd_name = Some(arg_slice.to_owned());
|
||||
break;
|
||||
|
@ -2696,19 +2730,41 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
|
||||
fn check_for_help_and_version(&self,
|
||||
arg: char)
|
||||
-> io::Result<()> {
|
||||
-> Result<(), ClapError> {
|
||||
if let Some(h) = self.help_short {
|
||||
if h == arg {
|
||||
try!(self.print_help());
|
||||
process::exit(0);
|
||||
if let Err(e) = self.print_help() {
|
||||
return Err(ClapError{
|
||||
error: format!("{} {}\n\terror message: {}\n",
|
||||
Format::Error("error:"),
|
||||
INTERNAL_ERROR_MSG, e.description()),
|
||||
error_type: ClapErrorType::MissingSubcommand
|
||||
});
|
||||
}
|
||||
// process::exit(0);
|
||||
return Err(ClapError{
|
||||
error: String::new(),
|
||||
error_type: ClapErrorType::HelpDisplayed
|
||||
})
|
||||
}
|
||||
}
|
||||
if let Some(v) = self.version_short {
|
||||
if v == arg {
|
||||
let out = io::stdout();
|
||||
let mut buf_w = BufWriter::new(out.lock());
|
||||
try!(self.print_version(&mut buf_w));
|
||||
process::exit(0);
|
||||
if let Err(e) = self.print_version(&mut buf_w) {
|
||||
return Err(ClapError{
|
||||
error: format!("{} {}\n\terror message: {}\n",
|
||||
Format::Error("error:"),
|
||||
INTERNAL_ERROR_MSG, e.description()),
|
||||
error_type: ClapErrorType::MissingSubcommand
|
||||
});
|
||||
}
|
||||
// process::exit(0);
|
||||
return Err(ClapError{
|
||||
error: String::new(),
|
||||
error_type: ClapErrorType::VersionDisplayed
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2730,7 +2786,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
error_type: ClapErrorType::MissingSubcommand
|
||||
});
|
||||
}
|
||||
process::exit(0);
|
||||
return Err(ClapError{
|
||||
error: String::new(),
|
||||
error_type: ClapErrorType::HelpDisplayed
|
||||
})
|
||||
// process::exit(0);
|
||||
} else if arg == "version" && self.settings.is_set(&AppSettings::NeedsLongVersion) {
|
||||
let out = io::stdout();
|
||||
let mut buf_w = BufWriter::new(out.lock());
|
||||
|
@ -2742,7 +2802,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
error_type: ClapErrorType::MissingSubcommand
|
||||
});
|
||||
}
|
||||
process::exit(0);
|
||||
return Err(ClapError{
|
||||
error: String::new(),
|
||||
error_type: ClapErrorType::VersionDisplayed
|
||||
})
|
||||
// process::exit(0);
|
||||
}
|
||||
|
||||
let mut arg_val: Option<&'av str> = None;
|
||||
|
|
|
@ -219,7 +219,38 @@ pub enum ClapErrorType {
|
|||
/// OsString::from_vec(vec![0xE9])]);
|
||||
/// assert!(result.is_err());
|
||||
/// ```
|
||||
InvalidUnicode
|
||||
InvalidUnicode,
|
||||
/// Not a true 'error' as it means `--help` or similar was used. The help message will be sent
|
||||
/// to `stdout` unless the help is displayed due to an error (such as missing subcommands) at
|
||||
/// which point it will be sent to `stderr`
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::ClapErrorType;
|
||||
/// let result = App::new("myprog")
|
||||
/// .get_matches_from_safe(vec!["", "--help"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().error_type, ClapErrorType::HelpDisplayed);
|
||||
/// ```
|
||||
HelpDisplayed,
|
||||
/// Not a true 'error' as it means `--version` or similar was used. The message will be sent
|
||||
/// to `stdout`
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::ClapErrorType;
|
||||
/// let result = App::new("myprog")
|
||||
/// .get_matches_from_safe(vec!["", "--version"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().error_type, ClapErrorType::VersionDisplayed);
|
||||
/// ```
|
||||
VersionDisplayed
|
||||
}
|
||||
|
||||
/// Command line argument parser error
|
||||
|
|
|
@ -52,6 +52,7 @@ use args::MatchedArg;
|
|||
/// println!("Not printing testing lists...");
|
||||
/// }
|
||||
/// }
|
||||
#[derive(Debug)]
|
||||
pub struct ArgMatches<'n, 'a> {
|
||||
#[doc(hidden)]
|
||||
pub args: HashMap<&'a str, MatchedArg>,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
pub struct MatchedArg {
|
||||
// #[doc(hidden)]
|
||||
// pub name: String,
|
||||
|
|
|
@ -23,6 +23,7 @@ use ArgMatches;
|
|||
/// .help("The configuration file to use")
|
||||
/// .index(1))
|
||||
/// # ).get_matches();
|
||||
#[derive(Debug)]
|
||||
pub struct SubCommand<'n, 'a> {
|
||||
#[doc(hidden)]
|
||||
pub name: &'n str,
|
||||
|
|
Loading…
Reference in a new issue