| 1 | /// Command line argument parser kind of error |
| 2 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Hash)] |
| 3 | #[non_exhaustive ] |
| 4 | pub enum ErrorKind { |
| 5 | /// Occurs when an [`Arg`][crate::Arg] has a set of possible values, |
| 6 | /// and the user provides a value which isn't in that set. |
| 7 | /// |
| 8 | /// # Examples |
| 9 | /// |
| 10 | /// ```rust |
| 11 | /// # use clap_builder as clap; |
| 12 | /// # use clap::{Command, Arg, error::ErrorKind}; |
| 13 | /// let result = Command::new("prog" ) |
| 14 | /// .arg(Arg::new("speed" ) |
| 15 | /// .value_parser(["fast" , "slow" ])) |
| 16 | /// .try_get_matches_from(vec!["prog" , "other" ]); |
| 17 | /// assert!(result.is_err()); |
| 18 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); |
| 19 | /// ``` |
| 20 | InvalidValue, |
| 21 | |
| 22 | /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. |
| 23 | /// |
| 24 | /// # Examples |
| 25 | /// |
| 26 | /// ```rust |
| 27 | /// # use clap_builder as clap; |
| 28 | /// # use clap::{Command, arg, error::ErrorKind}; |
| 29 | /// let result = Command::new("prog" ) |
| 30 | /// .arg(arg!(--flag "some flag" )) |
| 31 | /// .try_get_matches_from(vec!["prog" , "--other" ]); |
| 32 | /// assert!(result.is_err()); |
| 33 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnknownArgument); |
| 34 | /// ``` |
| 35 | UnknownArgument, |
| 36 | |
| 37 | /// Occurs when the user provides an unrecognized [`Subcommand`] which meets the threshold for |
| 38 | /// being similar enough to an existing subcommand. |
| 39 | /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, |
| 40 | /// the more general [`UnknownArgument`] error is returned. |
| 41 | /// |
| 42 | /// # Examples |
| 43 | /// |
| 44 | /// ```rust |
| 45 | /// # #[cfg (feature = "suggestions" )] { |
| 46 | /// # use clap_builder as clap; |
| 47 | /// # use clap::{Command, Arg, error::ErrorKind, }; |
| 48 | /// let result = Command::new("prog" ) |
| 49 | /// .subcommand(Command::new("config" ) |
| 50 | /// .about("Used for configuration" ) |
| 51 | /// .arg(Arg::new("config_file" ) |
| 52 | /// .help("The configuration file to use" ))) |
| 53 | /// .try_get_matches_from(vec!["prog" , "confi" ]); |
| 54 | /// assert!(result.is_err()); |
| 55 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand); |
| 56 | /// # } |
| 57 | /// ``` |
| 58 | /// |
| 59 | /// [`Subcommand`]: crate::Subcommand |
| 60 | /// [`UnknownArgument`]: ErrorKind::UnknownArgument |
| 61 | InvalidSubcommand, |
| 62 | |
| 63 | /// Occurs when the user doesn't use equals for an option that requires equal |
| 64 | /// sign to provide values. |
| 65 | /// |
| 66 | /// ```rust |
| 67 | /// # use clap_builder as clap; |
| 68 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
| 69 | /// let res = Command::new("prog" ) |
| 70 | /// .arg(Arg::new("color" ) |
| 71 | /// .action(ArgAction::Set) |
| 72 | /// .require_equals(true) |
| 73 | /// .long("color" )) |
| 74 | /// .try_get_matches_from(vec!["prog" , "--color" , "red" ]); |
| 75 | /// assert!(res.is_err()); |
| 76 | /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals); |
| 77 | /// ``` |
| 78 | NoEquals, |
| 79 | |
| 80 | /// Occurs when the user provides a value for an argument with a custom validation and the |
| 81 | /// value fails that validation. |
| 82 | /// |
| 83 | /// # Examples |
| 84 | /// |
| 85 | /// ```rust |
| 86 | /// # use clap_builder as clap; |
| 87 | /// # use clap::{Command, Arg, error::ErrorKind, value_parser}; |
| 88 | /// fn is_numeric(val: &str) -> Result<(), String> { |
| 89 | /// match val.parse::<i64>() { |
| 90 | /// Ok(..) => Ok(()), |
| 91 | /// Err(..) => Err(String::from("value wasn't a number!" )), |
| 92 | /// } |
| 93 | /// } |
| 94 | /// |
| 95 | /// let result = Command::new("prog" ) |
| 96 | /// .arg(Arg::new("num" ) |
| 97 | /// .value_parser(value_parser!(u8))) |
| 98 | /// .try_get_matches_from(vec!["prog" , "NotANumber" ]); |
| 99 | /// assert!(result.is_err()); |
| 100 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation); |
| 101 | /// ``` |
| 102 | ValueValidation, |
| 103 | |
| 104 | /// Occurs when a user provides more values for an argument than were defined by setting |
| 105 | /// [`Arg::num_args`]. |
| 106 | /// |
| 107 | /// # Examples |
| 108 | /// |
| 109 | /// ```rust |
| 110 | /// # use clap_builder as clap; |
| 111 | /// # use clap::{Command, Arg, error::ErrorKind}; |
| 112 | /// let result = Command::new("prog" ) |
| 113 | /// .arg(Arg::new("arg" ) |
| 114 | /// .num_args(1..=2)) |
| 115 | /// .try_get_matches_from(vec!["prog" , "too" , "many" , "values" ]); |
| 116 | /// assert!(result.is_err()); |
| 117 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues); |
| 118 | /// ``` |
| 119 | /// [`Arg::num_args`]: crate::Arg::num_args() |
| 120 | TooManyValues, |
| 121 | |
| 122 | /// Occurs when the user provides fewer values for an argument than were defined by setting |
| 123 | /// [`Arg::num_args`]. |
| 124 | /// |
| 125 | /// # Examples |
| 126 | /// |
| 127 | /// ```rust |
| 128 | /// # use clap_builder as clap; |
| 129 | /// # use clap::{Command, Arg, error::ErrorKind}; |
| 130 | /// let result = Command::new("prog" ) |
| 131 | /// .arg(Arg::new("some_opt" ) |
| 132 | /// .long("opt" ) |
| 133 | /// .num_args(3..)) |
| 134 | /// .try_get_matches_from(vec!["prog" , "--opt" , "too" , "few" ]); |
| 135 | /// assert!(result.is_err()); |
| 136 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues); |
| 137 | /// ``` |
| 138 | /// [`Arg::num_args`]: crate::Arg::num_args() |
| 139 | TooFewValues, |
| 140 | |
| 141 | /// Occurs when the user provides a different number of values for an argument than what's |
| 142 | /// been defined by setting [`Arg::num_args`] or than was implicitly set by |
| 143 | /// [`Arg::value_names`]. |
| 144 | /// |
| 145 | /// # Examples |
| 146 | /// |
| 147 | /// ```rust |
| 148 | /// # use clap_builder as clap; |
| 149 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
| 150 | /// let result = Command::new("prog" ) |
| 151 | /// .arg(Arg::new("some_opt" ) |
| 152 | /// .long("opt" ) |
| 153 | /// .action(ArgAction::Set) |
| 154 | /// .num_args(2)) |
| 155 | /// .try_get_matches_from(vec!["prog" , "--opt" , "wrong" ]); |
| 156 | /// assert!(result.is_err()); |
| 157 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues); |
| 158 | /// ``` |
| 159 | /// |
| 160 | /// [`Arg::num_args`]: crate::Arg::num_args() |
| 161 | /// [`Arg::value_names`]: crate::Arg::value_names() |
| 162 | WrongNumberOfValues, |
| 163 | |
| 164 | /// Occurs when the user provides two values which conflict with each other and can't be used |
| 165 | /// together. |
| 166 | /// |
| 167 | /// # Examples |
| 168 | /// |
| 169 | /// ```rust |
| 170 | /// # use clap_builder as clap; |
| 171 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
| 172 | /// let result = Command::new("prog" ) |
| 173 | /// .arg(Arg::new("debug" ) |
| 174 | /// .long("debug" ) |
| 175 | /// .action(ArgAction::SetTrue) |
| 176 | /// .conflicts_with("color" )) |
| 177 | /// .arg(Arg::new("color" ) |
| 178 | /// .long("color" ) |
| 179 | /// .action(ArgAction::SetTrue)) |
| 180 | /// .try_get_matches_from(vec!["prog" , "--debug" , "--color" ]); |
| 181 | /// assert!(result.is_err()); |
| 182 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); |
| 183 | /// ``` |
| 184 | ArgumentConflict, |
| 185 | |
| 186 | /// Occurs when the user does not provide one or more required arguments. |
| 187 | /// |
| 188 | /// # Examples |
| 189 | /// |
| 190 | /// ```rust |
| 191 | /// # use clap_builder as clap; |
| 192 | /// # use clap::{Command, Arg, error::ErrorKind}; |
| 193 | /// let result = Command::new("prog" ) |
| 194 | /// .arg(Arg::new("debug" ) |
| 195 | /// .required(true)) |
| 196 | /// .try_get_matches_from(vec!["prog" ]); |
| 197 | /// assert!(result.is_err()); |
| 198 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); |
| 199 | /// ``` |
| 200 | MissingRequiredArgument, |
| 201 | |
| 202 | /// Occurs when a subcommand is required (as defined by [`Command::subcommand_required`]), |
| 203 | /// but the user does not provide one. |
| 204 | /// |
| 205 | /// # Examples |
| 206 | /// |
| 207 | /// ```rust |
| 208 | /// # use clap_builder as clap; |
| 209 | /// # use clap::{Command, error::ErrorKind}; |
| 210 | /// let err = Command::new("prog" ) |
| 211 | /// .subcommand_required(true) |
| 212 | /// .subcommand(Command::new("test" )) |
| 213 | /// .try_get_matches_from(vec![ |
| 214 | /// "myprog" , |
| 215 | /// ]); |
| 216 | /// assert!(err.is_err()); |
| 217 | /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand); |
| 218 | /// # ; |
| 219 | /// ``` |
| 220 | /// |
| 221 | /// [`Command::subcommand_required`]: crate::Command::subcommand_required |
| 222 | MissingSubcommand, |
| 223 | |
| 224 | /// Occurs when the user provides a value containing invalid UTF-8. |
| 225 | /// |
| 226 | /// To allow arbitrary data |
| 227 | /// - Set [`Arg::value_parser(value_parser!(OsString))`] for argument values |
| 228 | /// - Set [`Command::external_subcommand_value_parser`] for external-subcommand |
| 229 | /// values |
| 230 | /// |
| 231 | /// # Platform Specific |
| 232 | /// |
| 233 | /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.) |
| 234 | /// |
| 235 | /// # Examples |
| 236 | /// |
| 237 | /// ```rust |
| 238 | /// # #[cfg (unix)] { |
| 239 | /// # use clap_builder as clap; |
| 240 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
| 241 | /// # use std::os::unix::ffi::OsStringExt; |
| 242 | /// # use std::ffi::OsString; |
| 243 | /// let result = Command::new("prog" ) |
| 244 | /// .arg(Arg::new("utf8" ) |
| 245 | /// .short('u' ) |
| 246 | /// .action(ArgAction::Set)) |
| 247 | /// .try_get_matches_from(vec![OsString::from("myprog" ), |
| 248 | /// OsString::from("-u" ), |
| 249 | /// OsString::from_vec(vec![0xE9])]); |
| 250 | /// assert!(result.is_err()); |
| 251 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8); |
| 252 | /// # } |
| 253 | /// ``` |
| 254 | /// |
| 255 | /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8 |
| 256 | /// [`Command::external_subcommand_value_parser`]: crate::Command::external_subcommand_value_parser |
| 257 | InvalidUtf8, |
| 258 | |
| 259 | /// Not a true "error" as it means `--help` or similar was used. |
| 260 | /// The help message will be sent to `stdout`. |
| 261 | /// |
| 262 | /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will |
| 263 | /// be sent to `stderr` instead of `stdout`. |
| 264 | /// |
| 265 | /// # Examples |
| 266 | /// |
| 267 | /// ```rust |
| 268 | /// # #[cfg (feature = "help" )] { |
| 269 | /// # use clap_builder as clap; |
| 270 | /// # use clap::{Command, Arg, error::ErrorKind}; |
| 271 | /// let result = Command::new("prog" ) |
| 272 | /// .try_get_matches_from(vec!["prog" , "--help" ]); |
| 273 | /// assert!(result.is_err()); |
| 274 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp); |
| 275 | /// # } |
| 276 | /// ``` |
| 277 | DisplayHelp, |
| 278 | |
| 279 | /// Occurs when either an argument or a [`Subcommand`] is required, as defined by |
| 280 | /// [`Command::arg_required_else_help`] , but the user did not provide |
| 281 | /// one. |
| 282 | /// |
| 283 | /// # Examples |
| 284 | /// |
| 285 | /// ```rust |
| 286 | /// # use clap_builder as clap; |
| 287 | /// # use clap::{Command, Arg, error::ErrorKind, }; |
| 288 | /// let result = Command::new("prog" ) |
| 289 | /// .arg_required_else_help(true) |
| 290 | /// .subcommand(Command::new("config" ) |
| 291 | /// .about("Used for configuration" ) |
| 292 | /// .arg(Arg::new("config_file" ) |
| 293 | /// .help("The configuration file to use" ))) |
| 294 | /// .try_get_matches_from(vec!["prog" ]); |
| 295 | /// assert!(result.is_err()); |
| 296 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand); |
| 297 | /// ``` |
| 298 | /// |
| 299 | /// [`Subcommand`]: crate::Subcommand |
| 300 | /// [`Command::arg_required_else_help`]: crate::Command::arg_required_else_help |
| 301 | DisplayHelpOnMissingArgumentOrSubcommand, |
| 302 | |
| 303 | /// Not a true "error" as it means `--version` or similar was used. |
| 304 | /// The message will be sent to `stdout`. |
| 305 | /// |
| 306 | /// # Examples |
| 307 | /// |
| 308 | /// ```rust |
| 309 | /// # use clap_builder as clap; |
| 310 | /// # use clap::{Command, Arg, error::ErrorKind}; |
| 311 | /// let result = Command::new("prog" ) |
| 312 | /// .version("3.0" ) |
| 313 | /// .try_get_matches_from(vec!["prog" , "--version" ]); |
| 314 | /// assert!(result.is_err()); |
| 315 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion); |
| 316 | /// ``` |
| 317 | DisplayVersion, |
| 318 | |
| 319 | /// Represents an [I/O error]. |
| 320 | /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. |
| 321 | /// |
| 322 | /// [I/O error]: std::io::Error |
| 323 | Io, |
| 324 | |
| 325 | /// Represents a [Format error] (which is a part of [`Display`]). |
| 326 | /// Typically caused by writing to `stderr` or `stdout`. |
| 327 | /// |
| 328 | /// [`Display`]: std::fmt::Display |
| 329 | /// [Format error]: std::fmt::Error |
| 330 | Format, |
| 331 | } |
| 332 | |
| 333 | impl ErrorKind { |
| 334 | /// End-user description of the error case, where relevant |
| 335 | pub fn as_str(self) -> Option<&'static str> { |
| 336 | match self { |
| 337 | Self::InvalidValue => Some("one of the values isn't valid for an argument" ), |
| 338 | Self::UnknownArgument => Some("unexpected argument found" ), |
| 339 | Self::InvalidSubcommand => Some("unrecognized subcommand" ), |
| 340 | Self::NoEquals => Some("equal is needed when assigning values to one of the arguments" ), |
| 341 | Self::ValueValidation => Some("invalid value for one of the arguments" ), |
| 342 | Self::TooManyValues => Some("unexpected value for an argument found" ), |
| 343 | Self::TooFewValues => Some("more values required for an argument" ), |
| 344 | Self::WrongNumberOfValues => Some("too many or too few values for an argument" ), |
| 345 | Self::ArgumentConflict => { |
| 346 | Some("an argument cannot be used with one or more of the other specified arguments" ) |
| 347 | } |
| 348 | Self::MissingRequiredArgument => { |
| 349 | Some("one or more required arguments were not provided" ) |
| 350 | } |
| 351 | Self::MissingSubcommand => Some("a subcommand is required but one was not provided" ), |
| 352 | Self::InvalidUtf8 => Some("invalid UTF-8 was detected in one or more arguments" ), |
| 353 | Self::DisplayHelp => None, |
| 354 | Self::DisplayHelpOnMissingArgumentOrSubcommand => None, |
| 355 | Self::DisplayVersion => None, |
| 356 | Self::Io => None, |
| 357 | Self::Format => None, |
| 358 | } |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | impl std::fmt::Display for ErrorKind { |
| 363 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 364 | self.as_str().unwrap_or_default().fmt(f) |
| 365 | } |
| 366 | } |
| 367 | |