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 as_str(self) -> Option<&'static str>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 { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result363 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 364 self.as_str().unwrap_or_default().fmt(f) 365 } 366 } 367