From 2d013315400d659d4ed33343fcb5860103113219 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 2 Feb 2022 16:06:23 -0600 Subject: [PATCH 1/2] refactor(error): Prepare for splitting mod --- src/{parse/error.rs => error/mod.rs} | 0 src/lib.rs | 18 +++++++++--------- src/parse/mod.rs | 1 - src/parse/parser.rs | 26 ++++++++++++-------------- src/parse/validator.rs | 16 ++++++---------- 5 files changed, 27 insertions(+), 34 deletions(-) rename src/{parse/error.rs => error/mod.rs} (100%) diff --git a/src/parse/error.rs b/src/error/mod.rs similarity index 100% rename from src/parse/error.rs rename to src/error/mod.rs diff --git a/src/lib.rs b/src/lib.rs index 7352c2dd..e8e70bc9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,20 +26,18 @@ #[cfg(not(feature = "std"))] compile_error!("`std` feature is currently required to build `clap`"); -pub use crate::parse::error; -pub use crate::parse::error::{ErrorKind, Result}; +pub use crate::build::{ + App, AppFlags, AppSettings, Arg, ArgFlags, ArgGroup, ArgSettings, PossibleValue, ValueHint, +}; +pub use crate::error::Error; +pub use crate::parse::{ArgMatches, Indices, OsValues, Values}; #[cfg(feature = "color")] pub use crate::util::color::ColorChoice; -pub use crate::{ - build::{ - App, AppFlags, AppSettings, Arg, ArgFlags, ArgGroup, ArgSettings, PossibleValue, ValueHint, - }, - parse::error::Error, - parse::{ArgMatches, Indices, OsValues, Values}, -}; pub use crate::derive::{ArgEnum, Args, FromArgMatches, IntoApp, Parser, Subcommand}; +pub use crate::error::{ErrorKind, Result}; + #[cfg(feature = "yaml")] #[doc(hidden)] #[deprecated( @@ -69,6 +67,8 @@ mod derive; #[cfg(feature = "regex")] pub use crate::build::arg::RegexRef; +pub mod error; + mod build; mod mkeymap; mod output; diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 184f115f..0a289a9e 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,4 +1,3 @@ -pub mod error; pub mod features; mod arg_matcher; diff --git a/src/parse/parser.rs b/src/parse/parser.rs index f39dd4eb..e2b4f126 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -9,20 +9,18 @@ use std::{ use os_str_bytes::RawOsStr; // Internal -use crate::{ - build::AppSettings as AS, - build::{App, Arg, ArgSettings}, - mkeymap::KeyType, - output::{fmt::Colorizer, Help, HelpWriter, Usage}, - parse::error::Error as ClapError, - parse::error::ErrorKind, - parse::error::Result as ClapResult, - parse::features::suggestions, - parse::{ArgMatcher, SubCommand}, - parse::{Validator, ValueType}, - util::{color::ColorChoice, ChildGraph, Id}, - INTERNAL_ERROR_MSG, INVALID_UTF8, -}; +use crate::build::AppSettings as AS; +use crate::build::{App, Arg, ArgSettings}; +use crate::error::Error as ClapError; +use crate::error::ErrorKind; +use crate::error::Result as ClapResult; +use crate::mkeymap::KeyType; +use crate::output::{fmt::Colorizer, Help, HelpWriter, Usage}; +use crate::parse::features::suggestions; +use crate::parse::{ArgMatcher, SubCommand}; +use crate::parse::{Validator, ValueType}; +use crate::util::{color::ColorChoice, ChildGraph, Id}; +use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8}; pub(crate) struct Parser<'help, 'app> { pub(crate) app: &'app mut App<'help>, diff --git a/src/parse/validator.rs b/src/parse/validator.rs index b56d0b88..a1a61fc6 100644 --- a/src/parse/validator.rs +++ b/src/parse/validator.rs @@ -1,14 +1,10 @@ // Internal -use crate::{ - build::{arg::PossibleValue, App, AppSettings as AS, Arg, ArgSettings}, - output::Usage, - parse::{ - error::{Error, ErrorKind, Result as ClapResult}, - ArgMatcher, MatchedArg, ParseState, Parser, - }, - util::Id, - INTERNAL_ERROR_MSG, INVALID_UTF8, -}; +use crate::build::{arg::PossibleValue, App, AppSettings as AS, Arg, ArgSettings}; +use crate::error::{Error, ErrorKind, Result as ClapResult}; +use crate::output::Usage; +use crate::parse::{ArgMatcher, MatchedArg, ParseState, Parser}; +use crate::util::Id; +use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8}; pub(crate) struct Validator<'help, 'app, 'parser> { p: &'parser mut Parser<'help, 'app>, From 59b63aea51ba3669b6e4fe17c2956105919c57a3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 2 Feb 2022 16:08:14 -0600 Subject: [PATCH 2/2] refactor(error): Pull out kind mod --- src/error/kind.rs | 401 +++++++++++++++++++++++++++++++++++++++++++++ src/error/mod.rs | 406 +--------------------------------------------- 2 files changed, 405 insertions(+), 402 deletions(-) create mode 100644 src/error/kind.rs diff --git a/src/error/kind.rs b/src/error/kind.rs new file mode 100644 index 00000000..aad353ac --- /dev/null +++ b/src/error/kind.rs @@ -0,0 +1,401 @@ +/// Command line argument parser kind of error +#[derive(Debug, Copy, Clone, PartialEq)] +#[non_exhaustive] +pub enum ErrorKind { + /// Occurs when an [`Arg`][crate::Arg] has a set of possible values, + /// and the user provides a value which isn't in that set. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("speed") + /// .possible_value("fast") + /// .possible_value("slow")) + /// .try_get_matches_from(vec!["prog", "other"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); + /// ``` + InvalidValue, + + /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(arg!(--flag "some flag")) + /// .try_get_matches_from(vec!["prog", "--other"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnknownArgument); + /// ``` + UnknownArgument, + + /// Occurs when the user provides an unrecognized [`Subcommand`] which meets the threshold for + /// being similar enough to an existing subcommand. + /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, + /// the more general [`UnknownArgument`] error is returned. + /// + /// # Examples + /// + #[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")] + #[cfg_attr(feature = "suggestions", doc = " ```")] + /// # use clap::{App, Arg, ErrorKind, }; + /// let result = App::new("prog") + /// .subcommand(App::new("config") + /// .about("Used for configuration") + /// .arg(Arg::new("config_file") + /// .help("The configuration file to use") + /// .index(1))) + /// .try_get_matches_from(vec!["prog", "confi"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand); + /// ``` + /// + /// [`Subcommand`]: crate::Subcommand + /// [`UnknownArgument`]: ErrorKind::UnknownArgument + InvalidSubcommand, + + /// Occurs when the user provides an unrecognized [`Subcommand`] which either + /// doesn't meet the threshold for being similar enough to an existing subcommand, + /// or the 'suggestions' feature is disabled. + /// Otherwise the more detailed [`InvalidSubcommand`] error is returned. + /// + /// This error typically happens when passing additional subcommand names to the `help` + /// subcommand. Otherwise, the more general [`UnknownArgument`] error is used. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind, }; + /// let result = App::new("prog") + /// .subcommand(App::new("config") + /// .about("Used for configuration") + /// .arg(Arg::new("config_file") + /// .help("The configuration file to use") + /// .index(1))) + /// .try_get_matches_from(vec!["prog", "help", "nothing"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnrecognizedSubcommand); + /// ``` + /// + /// [`Subcommand`]: crate::Subcommand + /// [`InvalidSubcommand`]: ErrorKind::InvalidSubcommand + /// [`UnknownArgument`]: ErrorKind::UnknownArgument + UnrecognizedSubcommand, + + /// Occurs when the user provides an empty value for an option that does not allow empty + /// values. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::new("color") + /// .takes_value(true) + /// .forbid_empty_values(true) + /// .long("color")) + /// .try_get_matches_from(vec!["prog", "--color="]); + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind(), ErrorKind::EmptyValue); + /// ``` + EmptyValue, + + /// Occurs when the user doesn't use equals for an option that requires equal + /// sign to provide values. + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let res = App::new("prog") + /// .arg(Arg::new("color") + /// .takes_value(true) + /// .require_equals(true) + /// .long("color")) + /// .try_get_matches_from(vec!["prog", "--color", "red"]); + /// assert!(res.is_err()); + /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals); + /// ``` + NoEquals, + + /// Occurs when the user provides a value for an argument with a custom validation and the + /// value fails that validation. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// fn is_numeric(val: &str) -> Result<(), String> { + /// match val.parse::() { + /// Ok(..) => Ok(()), + /// Err(..) => Err(String::from("Value wasn't a number!")), + /// } + /// } + /// + /// let result = App::new("prog") + /// .arg(Arg::new("num") + /// .validator(is_numeric)) + /// .try_get_matches_from(vec!["prog", "NotANumber"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation); + /// ``` + ValueValidation, + + /// Occurs when a user provides more values for an argument than were defined by setting + /// [`Arg::max_values`]. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("arg") + /// .max_values(2)) + /// .try_get_matches_from(vec!["prog", "too", "many", "values"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues); + /// ``` + /// [`Arg::max_values`]: crate::Arg::max_values() + TooManyValues, + + /// Occurs when the user provides fewer values for an argument than were defined by setting + /// [`Arg::min_values`]. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("some_opt") + /// .long("opt") + /// .min_values(3)) + /// .try_get_matches_from(vec!["prog", "--opt", "too", "few"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues); + /// ``` + /// [`Arg::min_values`]: crate::Arg::min_values() + TooFewValues, + + /// Occurs when a user provides more occurrences for an argument than were defined by setting + /// [`Arg::max_occurrences`]. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("verbosity") + /// .short('v') + /// .max_occurrences(2)) + /// .try_get_matches_from(vec!["prog", "-vvv"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyOccurrences); + /// ``` + /// [`Arg::max_occurrences`]: crate::Arg::max_occurrences() + TooManyOccurrences, + + /// Occurs when the user provides a different number of values for an argument than what's + /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by + /// [`Arg::value_names`]. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("some_opt") + /// .long("opt") + /// .takes_value(true) + /// .number_of_values(2)) + /// .try_get_matches_from(vec!["prog", "--opt", "wrong"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues); + /// ``` + /// + /// [`Arg::number_of_values`]: crate::Arg::number_of_values() + /// [`Arg::value_names`]: crate::Arg::value_names() + WrongNumberOfValues, + + /// Occurs when the user provides two values which conflict with each other and can't be used + /// together. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("debug") + /// .long("debug") + /// .conflicts_with("color")) + /// .arg(Arg::new("color") + /// .long("color")) + /// .try_get_matches_from(vec!["prog", "--debug", "--color"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); + /// ``` + ArgumentConflict, + + /// Occurs when the user does not provide one or more required arguments. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("debug") + /// .required(true)) + /// .try_get_matches_from(vec!["prog"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); + /// ``` + MissingRequiredArgument, + + /// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]), + /// but the user does not provide one. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, AppSettings, ErrorKind}; + /// let err = App::new("prog") + /// .setting(AppSettings::SubcommandRequired) + /// .subcommand(App::new("test")) + /// .try_get_matches_from(vec![ + /// "myprog", + /// ]); + /// assert!(err.is_err()); + /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand); + /// # ; + /// ``` + /// + /// [`AppSettings::SubcommandRequired`]: crate::AppSettings::SubcommandRequired + MissingSubcommand, + + /// Occurs when the user provides multiple values to an argument which doesn't allow that. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .arg(Arg::new("debug") + /// .long("debug") + /// .multiple_occurrences(false)) + /// .try_get_matches_from(vec!["prog", "--debug", "--debug"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnexpectedMultipleUsage); + /// ``` + UnexpectedMultipleUsage, + + /// Occurs when the user provides a value containing invalid UTF-8. + /// + /// To allow arbitrary data + /// - Set [`Arg::allow_invalid_utf8`] for argument values + /// - Set [`AppSettings::AllowInvalidUtf8ForExternalSubcommands`] for external-subcommand + /// values + /// + /// # Platform Specific + /// + /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.) + /// + /// # Examples + /// + #[cfg_attr(not(unix), doc = " ```ignore")] + #[cfg_attr(unix, doc = " ```")] + /// # use clap::{App, Arg, ErrorKind, AppSettings}; + /// # use std::os::unix::ffi::OsStringExt; + /// # use std::ffi::OsString; + /// let result = App::new("prog") + /// .arg(Arg::new("utf8") + /// .short('u') + /// .takes_value(true)) + /// .try_get_matches_from(vec![OsString::from("myprog"), + /// OsString::from("-u"), + /// OsString::from_vec(vec![0xE9])]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8); + /// ``` + /// + /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8 + /// [`AppSettings::AllowInvalidUtf8ForExternalSubcommands`]: crate::AppSettings::AllowInvalidUtf8ForExternalSubcommands + InvalidUtf8, + + /// Not a true "error" as it means `--help` or similar was used. + /// The help message will be sent to `stdout`. + /// + /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will + /// be sent to `stderr` instead of `stdout`. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .try_get_matches_from(vec!["prog", "--help"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp); + /// ``` + DisplayHelp, + + /// Occurs when either an argument or a [`Subcommand`] is required, as defined by + /// [`AppSettings::ArgRequiredElseHelp`] and + /// [`AppSettings::SubcommandRequiredElseHelp`], but the user did not provide + /// one. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, AppSettings, ErrorKind, }; + /// let result = App::new("prog") + /// .setting(AppSettings::ArgRequiredElseHelp) + /// .subcommand(App::new("config") + /// .about("Used for configuration") + /// .arg(Arg::new("config_file") + /// .help("The configuration file to use"))) + /// .try_get_matches_from(vec!["prog"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand); + /// ``` + /// + /// [`Subcommand`]: crate::Subcommand + /// [`AppSettings::ArgRequiredElseHelp`]: crate::AppSettings::ArgRequiredElseHelp + /// [`AppSettings::SubcommandRequiredElseHelp`]: crate::AppSettings::SubcommandRequiredElseHelp + DisplayHelpOnMissingArgumentOrSubcommand, + + /// Not a true "error" as it means `--version` or similar was used. + /// The message will be sent to `stdout`. + /// + /// # Examples + /// + /// ```rust + /// # use clap::{App, Arg, ErrorKind}; + /// let result = App::new("prog") + /// .version("3.0") + /// .try_get_matches_from(vec!["prog", "--version"]); + /// assert!(result.is_err()); + /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion); + /// ``` + DisplayVersion, + + /// Occurs when using the [`ArgMatches::value_of_t`] and friends to convert an argument value + /// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument + /// with name `config` to be converted, but `config` wasn't used by the user. + /// + /// [`ArgMatches::value_of_t`]: crate::ArgMatches::value_of_t() + ArgumentNotFound, + + /// Represents an [I/O error]. + /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. + /// + /// [I/O error]: std::io::Error + Io, + + /// Represents a [Format error] (which is a part of [`Display`]). + /// Typically caused by writing to `stderr` or `stdout`. + /// + /// [`Display`]: std::fmt::Display + /// [Format error]: std::fmt::Error + Format, +} diff --git a/src/error/mod.rs b/src/error/mod.rs index 68733980..6349661a 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -19,413 +19,15 @@ use crate::{ App, AppSettings, }; +mod kind; + +pub use kind::ErrorKind; + /// Short hand for [`Result`] type /// /// [`Result`]: std::result::Result pub type Result = StdResult; -/// Command line argument parser kind of error -#[derive(Debug, Copy, Clone, PartialEq)] -#[non_exhaustive] -pub enum ErrorKind { - /// Occurs when an [`Arg`] has a set of possible values, - /// and the user provides a value which isn't in that set. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("speed") - /// .possible_value("fast") - /// .possible_value("slow")) - /// .try_get_matches_from(vec!["prog", "other"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); - /// ``` - InvalidValue, - - /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(arg!(--flag "some flag")) - /// .try_get_matches_from(vec!["prog", "--other"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnknownArgument); - /// ``` - UnknownArgument, - - /// Occurs when the user provides an unrecognized [`Subcommand`] which meets the threshold for - /// being similar enough to an existing subcommand. - /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, - /// the more general [`UnknownArgument`] error is returned. - /// - /// # Examples - /// - #[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")] - #[cfg_attr(feature = "suggestions", doc = " ```")] - /// # use clap::{App, Arg, ErrorKind, }; - /// let result = App::new("prog") - /// .subcommand(App::new("config") - /// .about("Used for configuration") - /// .arg(Arg::new("config_file") - /// .help("The configuration file to use") - /// .index(1))) - /// .try_get_matches_from(vec!["prog", "confi"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand); - /// ``` - /// - /// [`Subcommand`]: crate::Subcommand - /// [`UnknownArgument`]: ErrorKind::UnknownArgument - InvalidSubcommand, - - /// Occurs when the user provides an unrecognized [`Subcommand`] which either - /// doesn't meet the threshold for being similar enough to an existing subcommand, - /// or the 'suggestions' feature is disabled. - /// Otherwise the more detailed [`InvalidSubcommand`] error is returned. - /// - /// This error typically happens when passing additional subcommand names to the `help` - /// subcommand. Otherwise, the more general [`UnknownArgument`] error is used. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind, }; - /// let result = App::new("prog") - /// .subcommand(App::new("config") - /// .about("Used for configuration") - /// .arg(Arg::new("config_file") - /// .help("The configuration file to use") - /// .index(1))) - /// .try_get_matches_from(vec!["prog", "help", "nothing"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnrecognizedSubcommand); - /// ``` - /// - /// [`Subcommand`]: crate::Subcommand - /// [`InvalidSubcommand`]: ErrorKind::InvalidSubcommand - /// [`UnknownArgument`]: ErrorKind::UnknownArgument - UnrecognizedSubcommand, - - /// Occurs when the user provides an empty value for an option that does not allow empty - /// values. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("prog") - /// .arg(Arg::new("color") - /// .takes_value(true) - /// .forbid_empty_values(true) - /// .long("color")) - /// .try_get_matches_from(vec!["prog", "--color="]); - /// assert!(res.is_err()); - /// assert_eq!(res.unwrap_err().kind(), ErrorKind::EmptyValue); - /// ``` - EmptyValue, - - /// Occurs when the user doesn't use equals for an option that requires equal - /// sign to provide values. - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let res = App::new("prog") - /// .arg(Arg::new("color") - /// .takes_value(true) - /// .require_equals(true) - /// .long("color")) - /// .try_get_matches_from(vec!["prog", "--color", "red"]); - /// assert!(res.is_err()); - /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals); - /// ``` - NoEquals, - - /// Occurs when the user provides a value for an argument with a custom validation and the - /// value fails that validation. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// fn is_numeric(val: &str) -> Result<(), String> { - /// match val.parse::() { - /// Ok(..) => Ok(()), - /// Err(..) => Err(String::from("Value wasn't a number!")), - /// } - /// } - /// - /// let result = App::new("prog") - /// .arg(Arg::new("num") - /// .validator(is_numeric)) - /// .try_get_matches_from(vec!["prog", "NotANumber"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation); - /// ``` - ValueValidation, - - /// Occurs when a user provides more values for an argument than were defined by setting - /// [`Arg::max_values`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("arg") - /// .max_values(2)) - /// .try_get_matches_from(vec!["prog", "too", "many", "values"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues); - /// ``` - /// [`Arg::max_values`]: Arg::max_values() - TooManyValues, - - /// Occurs when the user provides fewer values for an argument than were defined by setting - /// [`Arg::min_values`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("some_opt") - /// .long("opt") - /// .min_values(3)) - /// .try_get_matches_from(vec!["prog", "--opt", "too", "few"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues); - /// ``` - /// [`Arg::min_values`]: Arg::min_values() - TooFewValues, - - /// Occurs when a user provides more occurrences for an argument than were defined by setting - /// [`Arg::max_occurrences`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("verbosity") - /// .short('v') - /// .max_occurrences(2)) - /// .try_get_matches_from(vec!["prog", "-vvv"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyOccurrences); - /// ``` - /// [`Arg::max_occurrences`]: Arg::max_occurrences() - TooManyOccurrences, - - /// Occurs when the user provides a different number of values for an argument than what's - /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by - /// [`Arg::value_names`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("some_opt") - /// .long("opt") - /// .takes_value(true) - /// .number_of_values(2)) - /// .try_get_matches_from(vec!["prog", "--opt", "wrong"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues); - /// ``` - /// - /// [`Arg::number_of_values`]: Arg::number_of_values() - /// [`Arg::value_names`]: Arg::value_names() - WrongNumberOfValues, - - /// Occurs when the user provides two values which conflict with each other and can't be used - /// together. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("debug") - /// .long("debug") - /// .conflicts_with("color")) - /// .arg(Arg::new("color") - /// .long("color")) - /// .try_get_matches_from(vec!["prog", "--debug", "--color"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); - /// ``` - ArgumentConflict, - - /// Occurs when the user does not provide one or more required arguments. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("debug") - /// .required(true)) - /// .try_get_matches_from(vec!["prog"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); - /// ``` - MissingRequiredArgument, - - /// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]), - /// but the user does not provide one. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, AppSettings, ErrorKind}; - /// let err = App::new("prog") - /// .setting(AppSettings::SubcommandRequired) - /// .subcommand(App::new("test")) - /// .try_get_matches_from(vec![ - /// "myprog", - /// ]); - /// assert!(err.is_err()); - /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand); - /// # ; - /// ``` - /// - /// [`AppSettings::SubcommandRequired`]: crate::AppSettings::SubcommandRequired - MissingSubcommand, - - /// Occurs when the user provides multiple values to an argument which doesn't allow that. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .arg(Arg::new("debug") - /// .long("debug") - /// .multiple_occurrences(false)) - /// .try_get_matches_from(vec!["prog", "--debug", "--debug"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnexpectedMultipleUsage); - /// ``` - UnexpectedMultipleUsage, - - /// Occurs when the user provides a value containing invalid UTF-8. - /// - /// To allow arbitrary data - /// - Set [`Arg::allow_invalid_utf8`] for argument values - /// - Set [`AppSettings::AllowInvalidUtf8ForExternalSubcommands`] for external-subcommand - /// values - /// - /// # Platform Specific - /// - /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.) - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```")] - /// # use clap::{App, Arg, ErrorKind, AppSettings}; - /// # use std::os::unix::ffi::OsStringExt; - /// # use std::ffi::OsString; - /// let result = App::new("prog") - /// .arg(Arg::new("utf8") - /// .short('u') - /// .takes_value(true)) - /// .try_get_matches_from(vec![OsString::from("myprog"), - /// OsString::from("-u"), - /// OsString::from_vec(vec![0xE9])]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8); - /// ``` - /// - /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8 - /// [`AppSettings::AllowInvalidUtf8ForExternalSubcommands`]: crate::AppSettings::AllowInvalidUtf8ForExternalSubcommands - InvalidUtf8, - - /// Not a true "error" as it means `--help` or similar was used. - /// The help message will be sent to `stdout`. - /// - /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will - /// be sent to `stderr` instead of `stdout`. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .try_get_matches_from(vec!["prog", "--help"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp); - /// ``` - DisplayHelp, - - /// Occurs when either an argument or a [`Subcommand`] is required, as defined by - /// [`AppSettings::ArgRequiredElseHelp`] and - /// [`AppSettings::SubcommandRequiredElseHelp`], but the user did not provide - /// one. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, AppSettings, ErrorKind, }; - /// let result = App::new("prog") - /// .setting(AppSettings::ArgRequiredElseHelp) - /// .subcommand(App::new("config") - /// .about("Used for configuration") - /// .arg(Arg::new("config_file") - /// .help("The configuration file to use"))) - /// .try_get_matches_from(vec!["prog"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand); - /// ``` - /// - /// [`Subcommand`]: crate::Subcommand - /// [`AppSettings::ArgRequiredElseHelp`]: crate::AppSettings::ArgRequiredElseHelp - /// [`AppSettings::SubcommandRequiredElseHelp`]: crate::AppSettings::SubcommandRequiredElseHelp - DisplayHelpOnMissingArgumentOrSubcommand, - - /// Not a true "error" as it means `--version` or similar was used. - /// The message will be sent to `stdout`. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{App, Arg, ErrorKind}; - /// let result = App::new("prog") - /// .version("3.0") - /// .try_get_matches_from(vec!["prog", "--version"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion); - /// ``` - DisplayVersion, - - /// Occurs when using the [`ArgMatches::value_of_t`] and friends to convert an argument value - /// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument - /// with name `config` to be converted, but `config` wasn't used by the user. - /// - /// [`ArgMatches::value_of_t`]: crate::ArgMatches::value_of_t() - ArgumentNotFound, - - /// Represents an [I/O error]. - /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. - /// - /// [I/O error]: std::io::Error - Io, - - /// Represents a [Format error] (which is a part of [`Display`]). - /// Typically caused by writing to `stderr` or `stdout`. - /// - /// [`Display`]: std::fmt::Display - /// [Format error]: std::fmt::Error - Format, -} - /// Command Line Argument Parser Error /// /// See [`App::error`] to create an error.