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