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