1 // Std 2 use std::convert::From; 3 use std::error::Error as StdError; 4 use std::fmt as std_fmt; 5 use std::fmt::Display; 6 use std::io::{self, Write}; 7 use std::process; 8 use std::result::Result as StdResult; 9 10 // Internal 11 use args::{AnyArg, FlagBuilder}; 12 use fmt::{ColorWhen, Colorizer, ColorizerOption}; 13 use suggestions; 14 15 /// Short hand for [`Result`] type 16 /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html 17 pub type Result<T> = StdResult<T, Error>; 18 19 /// Command line argument parser kind of error 20 #[derive(Debug, Copy, Clone, PartialEq)] 21 pub enum ErrorKind { 22 /// Occurs when an [`Arg`] has a set of possible values, 23 /// and the user provides a value which isn't in that set. 24 /// 25 /// # Examples 26 /// 27 /// ```rust 28 /// # use clap::{App, Arg, ErrorKind}; 29 /// let result = App::new("prog") 30 /// .arg(Arg::with_name("speed") 31 /// .possible_value("fast") 32 /// .possible_value("slow")) 33 /// .get_matches_from_safe(vec!["prog", "other"]); 34 /// assert!(result.is_err()); 35 /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidValue); 36 /// ``` 37 /// [`Arg`]: ./struct.Arg.html 38 InvalidValue, 39 40 /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. 41 /// 42 /// # Examples 43 /// 44 /// ```rust 45 /// # use clap::{App, Arg, ErrorKind}; 46 /// let result = App::new("prog") 47 /// .arg(Arg::from_usage("--flag 'some flag'")) 48 /// .get_matches_from_safe(vec!["prog", "--other"]); 49 /// assert!(result.is_err()); 50 /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnknownArgument); 51 /// ``` 52 UnknownArgument, 53 54 /// Occurs when the user provides an unrecognized [`SubCommand`] which meets the threshold for 55 /// being similar enough to an existing subcommand. 56 /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, 57 /// the more general [`UnknownArgument`] error is returned. 58 /// 59 /// # Examples 60 /// 61 #[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")] 62 #[cfg_attr(feature = "suggestions", doc = " ```")] 63 /// # use clap::{App, Arg, ErrorKind, SubCommand}; 64 /// let result = App::new("prog") 65 /// .subcommand(SubCommand::with_name("config") 66 /// .about("Used for configuration") 67 /// .arg(Arg::with_name("config_file") 68 /// .help("The configuration file to use") 69 /// .index(1))) 70 /// .get_matches_from_safe(vec!["prog", "confi"]); 71 /// assert!(result.is_err()); 72 /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidSubcommand); 73 /// ``` 74 /// [`SubCommand`]: ./struct.SubCommand.html 75 /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument 76 InvalidSubcommand, 77 78 /// Occurs when the user provides an unrecognized [`SubCommand`] which either 79 /// doesn't meet the threshold for being similar enough to an existing subcommand, 80 /// or the 'sggestions' feature is disabled. 81 /// Otherwise the more detailed [`InvalidSubcommand`] error is returned. 82 /// 83 /// This error typically happens when passing additional subcommand names to the `help` 84 /// subcommand. Otherwise, the more general [`UnknownArgument`] error is used. 85 /// 86 /// # Examples 87 /// 88 /// ```rust 89 /// # use clap::{App, Arg, ErrorKind, SubCommand}; 90 /// let result = App::new("prog") 91 /// .subcommand(SubCommand::with_name("config") 92 /// .about("Used for configuration") 93 /// .arg(Arg::with_name("config_file") 94 /// .help("The configuration file to use") 95 /// .index(1))) 96 /// .get_matches_from_safe(vec!["prog", "help", "nothing"]); 97 /// assert!(result.is_err()); 98 /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand); 99 /// ``` 100 /// [`SubCommand`]: ./struct.SubCommand.html 101 /// [`InvalidSubcommand`]: ./enum.ErrorKind.html#variant.InvalidSubcommand 102 /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument 103 UnrecognizedSubcommand, 104 105 /// Occurs when the user provides an empty value for an option that does not allow empty 106 /// values. 107 /// 108 /// # Examples 109 /// 110 /// ```rust 111 /// # use clap::{App, Arg, ErrorKind}; 112 /// let res = App::new("prog") 113 /// .arg(Arg::with_name("color") 114 /// .long("color") 115 /// .empty_values(false)) 116 /// .get_matches_from_safe(vec!["prog", "--color="]); 117 /// assert!(res.is_err()); 118 /// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue); 119 /// ``` 120 EmptyValue, 121 122 /// Occurs when the user provides a value for an argument with a custom validation and the 123 /// value fails that validation. 124 /// 125 /// # Examples 126 /// 127 /// ```rust 128 /// # use clap::{App, Arg, ErrorKind}; 129 /// fn is_numeric(val: String) -> Result<(), String> { 130 /// match val.parse::<i64>() { 131 /// Ok(..) => Ok(()), 132 /// Err(..) => Err(String::from("Value wasn't a number!")), 133 /// } 134 /// } 135 /// 136 /// let result = App::new("prog") 137 /// .arg(Arg::with_name("num") 138 /// .validator(is_numeric)) 139 /// .get_matches_from_safe(vec!["prog", "NotANumber"]); 140 /// assert!(result.is_err()); 141 /// assert_eq!(result.unwrap_err().kind, ErrorKind::ValueValidation); 142 /// ``` 143 ValueValidation, 144 145 /// Occurs when a user provides more values for an argument than were defined by setting 146 /// [`Arg::max_values`]. 147 /// 148 /// # Examples 149 /// 150 /// ```rust 151 /// # use clap::{App, Arg, ErrorKind}; 152 /// let result = App::new("prog") 153 /// .arg(Arg::with_name("arg") 154 /// .multiple(true) 155 /// .max_values(2)) 156 /// .get_matches_from_safe(vec!["prog", "too", "many", "values"]); 157 /// assert!(result.is_err()); 158 /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooManyValues); 159 /// ``` 160 /// [`Arg::max_values`]: ./struct.Arg.html#method.max_values 161 TooManyValues, 162 163 /// Occurs when the user provides fewer values for an argument than were defined by setting 164 /// [`Arg::min_values`]. 165 /// 166 /// # Examples 167 /// 168 /// ```rust 169 /// # use clap::{App, Arg, ErrorKind}; 170 /// let result = App::new("prog") 171 /// .arg(Arg::with_name("some_opt") 172 /// .long("opt") 173 /// .min_values(3)) 174 /// .get_matches_from_safe(vec!["prog", "--opt", "too", "few"]); 175 /// assert!(result.is_err()); 176 /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooFewValues); 177 /// ``` 178 /// [`Arg::min_values`]: ./struct.Arg.html#method.min_values 179 TooFewValues, 180 181 /// Occurs when the user provides a different number of values for an argument than what's 182 /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by 183 /// [`Arg::value_names`]. 184 /// 185 /// # Examples 186 /// 187 /// ```rust 188 /// # use clap::{App, Arg, ErrorKind}; 189 /// let result = App::new("prog") 190 /// .arg(Arg::with_name("some_opt") 191 /// .long("opt") 192 /// .takes_value(true) 193 /// .number_of_values(2)) 194 /// .get_matches_from_safe(vec!["prog", "--opt", "wrong"]); 195 /// assert!(result.is_err()); 196 /// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues); 197 /// ``` 198 /// [`Arg::number_of_values`] 199 /// [`Arg::number_of_values`]: ./struct.Arg.html#method.number_of_values 200 /// [`Arg::value_names`]: ./struct.Arg.html#method.value_names 201 WrongNumberOfValues, 202 203 /// Occurs when the user provides two values which conflict with each other and can't be used 204 /// together. 205 /// 206 /// # Examples 207 /// 208 /// ```rust 209 /// # use clap::{App, Arg, ErrorKind}; 210 /// let result = App::new("prog") 211 /// .arg(Arg::with_name("debug") 212 /// .long("debug") 213 /// .conflicts_with("color")) 214 /// .arg(Arg::with_name("color") 215 /// .long("color")) 216 /// .get_matches_from_safe(vec!["prog", "--debug", "--color"]); 217 /// assert!(result.is_err()); 218 /// assert_eq!(result.unwrap_err().kind, ErrorKind::ArgumentConflict); 219 /// ``` 220 ArgumentConflict, 221 222 /// Occurs when the user does not provide one or more required arguments. 223 /// 224 /// # Examples 225 /// 226 /// ```rust 227 /// # use clap::{App, Arg, ErrorKind}; 228 /// let result = App::new("prog") 229 /// .arg(Arg::with_name("debug") 230 /// .required(true)) 231 /// .get_matches_from_safe(vec!["prog"]); 232 /// assert!(result.is_err()); 233 /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingRequiredArgument); 234 /// ``` 235 MissingRequiredArgument, 236 237 /// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]), 238 /// but the user does not provide one. 239 /// 240 /// # Examples 241 /// 242 /// ```rust 243 /// # use clap::{App, AppSettings, SubCommand, ErrorKind}; 244 /// let err = App::new("prog") 245 /// .setting(AppSettings::SubcommandRequired) 246 /// .subcommand(SubCommand::with_name("test")) 247 /// .get_matches_from_safe(vec![ 248 /// "myprog", 249 /// ]); 250 /// assert!(err.is_err()); 251 /// assert_eq!(err.unwrap_err().kind, ErrorKind::MissingSubcommand); 252 /// # ; 253 /// ``` 254 /// [`AppSettings::SubcommandRequired`]: ./enum.AppSettings.html#variant.SubcommandRequired 255 MissingSubcommand, 256 257 /// Occurs when either an argument or [`SubCommand`] is required, as defined by 258 /// [`AppSettings::ArgRequiredElseHelp`], but the user did not provide one. 259 /// 260 /// # Examples 261 /// 262 /// ```rust 263 /// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand}; 264 /// let result = App::new("prog") 265 /// .setting(AppSettings::ArgRequiredElseHelp) 266 /// .subcommand(SubCommand::with_name("config") 267 /// .about("Used for configuration") 268 /// .arg(Arg::with_name("config_file") 269 /// .help("The configuration file to use"))) 270 /// .get_matches_from_safe(vec!["prog"]); 271 /// assert!(result.is_err()); 272 /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingArgumentOrSubcommand); 273 /// ``` 274 /// [`SubCommand`]: ./struct.SubCommand.html 275 /// [`AppSettings::ArgRequiredElseHelp`]: ./enum.AppSettings.html#variant.ArgRequiredElseHelp 276 MissingArgumentOrSubcommand, 277 278 /// Occurs when the user provides multiple values to an argument which doesn't allow that. 279 /// 280 /// # Examples 281 /// 282 /// ```rust 283 /// # use clap::{App, Arg, ErrorKind}; 284 /// let result = App::new("prog") 285 /// .arg(Arg::with_name("debug") 286 /// .long("debug") 287 /// .multiple(false)) 288 /// .get_matches_from_safe(vec!["prog", "--debug", "--debug"]); 289 /// assert!(result.is_err()); 290 /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage); 291 /// ``` 292 UnexpectedMultipleUsage, 293 294 /// Occurs when the user provides a value containing invalid UTF-8 for an argument and 295 /// [`AppSettings::StrictUtf8`] is set. 296 /// 297 /// # Platform Speicific 298 /// 299 /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.) 300 /// 301 /// # Examples 302 /// 303 #[cfg_attr(not(unix), doc = " ```ignore")] 304 #[cfg_attr(unix, doc = " ```")] 305 /// # use clap::{App, Arg, ErrorKind, AppSettings}; 306 /// # use std::os::unix::ffi::OsStringExt; 307 /// # use std::ffi::OsString; 308 /// let result = App::new("prog") 309 /// .setting(AppSettings::StrictUtf8) 310 /// .arg(Arg::with_name("utf8") 311 /// .short("u") 312 /// .takes_value(true)) 313 /// .get_matches_from_safe(vec![OsString::from("myprog"), 314 /// OsString::from("-u"), 315 /// OsString::from_vec(vec![0xE9])]); 316 /// assert!(result.is_err()); 317 /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidUtf8); 318 /// ``` 319 /// [`AppSettings::StrictUtf8`]: ./enum.AppSettings.html#variant.StrictUtf8 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::{App, Arg, ErrorKind}; 332 /// let result = App::new("prog") 333 /// .get_matches_from_safe(vec!["prog", "--help"]); 334 /// assert!(result.is_err()); 335 /// assert_eq!(result.unwrap_err().kind, ErrorKind::HelpDisplayed); 336 /// ``` 337 HelpDisplayed, 338 339 /// Not a true "error" as it means `--version` or similar was used. 340 /// The message will be sent to `stdout`. 341 /// 342 /// # Examples 343 /// 344 /// ```rust 345 /// # use clap::{App, Arg, ErrorKind}; 346 /// let result = App::new("prog") 347 /// .get_matches_from_safe(vec!["prog", "--version"]); 348 /// assert!(result.is_err()); 349 /// assert_eq!(result.unwrap_err().kind, ErrorKind::VersionDisplayed); 350 /// ``` 351 VersionDisplayed, 352 353 /// Occurs when using the [`value_t!`] and [`values_t!`] macros to convert an argument value 354 /// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument 355 /// with name `config` to be converted, but `config` wasn't used by the user. 356 /// [`value_t!`]: ./macro.value_t!.html 357 /// [`values_t!`]: ./macro.values_t!.html 358 ArgumentNotFound, 359 360 /// Represents an [I/O error]. 361 /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. 362 /// [I/O error]: https://doc.rust-lang.org/std/io/struct.Error.html 363 Io, 364 365 /// Represents a [Format error] (which is a part of [`Display`]). 366 /// Typically caused by writing to `stderr` or `stdout`. 367 /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html 368 /// [Format error]: https://doc.rust-lang.org/std/fmt/struct.Error.html 369 Format, 370 } 371 372 /// Command Line Argument Parser Error 373 #[derive(Debug)] 374 pub struct Error { 375 /// Formated error message 376 pub message: String, 377 /// The type of error 378 pub kind: ErrorKind, 379 /// Any additional information passed along, such as the argument name that caused the error 380 pub info: Option<Vec<String>>, 381 } 382 383 impl Error { 384 /// Should the message be written to `stdout` or not use_stderr(&self) -> bool385 pub fn use_stderr(&self) -> bool { 386 match self.kind { 387 ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => false, 388 _ => true, 389 } 390 } 391 392 /// Prints the error to `stderr` and exits with a status of `1` exit(&self) -> !393 pub fn exit(&self) -> ! { 394 if self.use_stderr() { 395 wlnerr!("{}", self.message); 396 process::exit(1); 397 } 398 let out = io::stdout(); 399 writeln!(&mut out.lock(), "{}", self.message).expect("Error writing Error to stdout"); 400 process::exit(0); 401 } 402 403 #[doc(hidden)] write_to<W: Write>(&self, w: &mut W) -> io::Result<()>404 pub fn write_to<W: Write>(&self, w: &mut W) -> io::Result<()> { write!(w, "{}", self.message) } 405 406 #[doc(hidden)] argument_conflict<'a, 'b, A, O, U>( arg: &A, other: Option<O>, usage: U, color: ColorWhen, ) -> Self where A: AnyArg<'a, 'b> + Display, O: Into<String>, U: Display,407 pub fn argument_conflict<'a, 'b, A, O, U>( 408 arg: &A, 409 other: Option<O>, 410 usage: U, 411 color: ColorWhen, 412 ) -> Self 413 where 414 A: AnyArg<'a, 'b> + Display, 415 O: Into<String>, 416 U: Display, 417 { 418 let mut v = vec![arg.name().to_owned()]; 419 let c = Colorizer::new(ColorizerOption { 420 use_stderr: true, 421 when: color, 422 }); 423 Error { 424 message: format!( 425 "{} The argument '{}' cannot be used with {}\n\n\ 426 {}\n\n\ 427 For more information try {}", 428 c.error("error:"), 429 c.warning(&*arg.to_string()), 430 match other { 431 Some(name) => { 432 let n = name.into(); 433 v.push(n.clone()); 434 c.warning(format!("'{}'", n)) 435 } 436 None => c.none("one or more of the other specified arguments".to_owned()), 437 }, 438 usage, 439 c.good("--help") 440 ), 441 kind: ErrorKind::ArgumentConflict, 442 info: Some(v), 443 } 444 } 445 446 #[doc(hidden)] empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display,447 pub fn empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self 448 where 449 A: AnyArg<'a, 'b> + Display, 450 U: Display, 451 { 452 let c = Colorizer::new(ColorizerOption { 453 use_stderr: true, 454 when: color, 455 }); 456 Error { 457 message: format!( 458 "{} The argument '{}' requires a value but none was supplied\ 459 \n\n\ 460 {}\n\n\ 461 For more information try {}", 462 c.error("error:"), 463 c.warning(arg.to_string()), 464 usage, 465 c.good("--help") 466 ), 467 kind: ErrorKind::EmptyValue, 468 info: Some(vec![arg.name().to_owned()]), 469 } 470 } 471 472 #[doc(hidden)] invalid_value<'a, 'b, B, G, A, U>( bad_val: B, good_vals: &[G], arg: &A, usage: U, color: ColorWhen, ) -> Self where B: AsRef<str>, G: AsRef<str> + Display, A: AnyArg<'a, 'b> + Display, U: Display,473 pub fn invalid_value<'a, 'b, B, G, A, U>( 474 bad_val: B, 475 good_vals: &[G], 476 arg: &A, 477 usage: U, 478 color: ColorWhen, 479 ) -> Self 480 where 481 B: AsRef<str>, 482 G: AsRef<str> + Display, 483 A: AnyArg<'a, 'b> + Display, 484 U: Display, 485 { 486 let c = Colorizer::new(ColorizerOption { 487 use_stderr: true, 488 when: color, 489 }); 490 let suffix = suggestions::did_you_mean_value_suffix(bad_val.as_ref(), good_vals.iter()); 491 492 let mut sorted = vec![]; 493 for v in good_vals { 494 let val = format!("{}", c.good(v)); 495 sorted.push(val); 496 } 497 sorted.sort(); 498 let valid_values = sorted.join(", "); 499 Error { 500 message: format!( 501 "{} '{}' isn't a valid value for '{}'\n\t\ 502 [values: {}]\n\ 503 {}\n\n\ 504 {}\n\n\ 505 For more information try {}", 506 c.error("error:"), 507 c.warning(bad_val.as_ref()), 508 c.warning(arg.to_string()), 509 valid_values, 510 suffix.0, 511 usage, 512 c.good("--help") 513 ), 514 kind: ErrorKind::InvalidValue, 515 info: Some(vec![arg.name().to_owned(), bad_val.as_ref().to_owned()]), 516 } 517 } 518 519 #[doc(hidden)] invalid_subcommand<S, D, N, U>( subcmd: S, did_you_mean: D, name: N, usage: U, color: ColorWhen, ) -> Self where S: Into<String>, D: AsRef<str> + Display, N: Display, U: Display,520 pub fn invalid_subcommand<S, D, N, U>( 521 subcmd: S, 522 did_you_mean: D, 523 name: N, 524 usage: U, 525 color: ColorWhen, 526 ) -> Self 527 where 528 S: Into<String>, 529 D: AsRef<str> + Display, 530 N: Display, 531 U: Display, 532 { 533 let s = subcmd.into(); 534 let c = Colorizer::new(ColorizerOption { 535 use_stderr: true, 536 when: color, 537 }); 538 Error { 539 message: format!( 540 "{} The subcommand '{}' wasn't recognized\n\t\ 541 Did you mean '{}'?\n\n\ 542 If you believe you received this message in error, try \ 543 re-running with '{} {} {}'\n\n\ 544 {}\n\n\ 545 For more information try {}", 546 c.error("error:"), 547 c.warning(&*s), 548 c.good(did_you_mean.as_ref()), 549 name, 550 c.good("--"), 551 &*s, 552 usage, 553 c.good("--help") 554 ), 555 kind: ErrorKind::InvalidSubcommand, 556 info: Some(vec![s]), 557 } 558 } 559 560 #[doc(hidden)] unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self where S: Into<String>, N: Display,561 pub fn unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self 562 where 563 S: Into<String>, 564 N: Display, 565 { 566 let s = subcmd.into(); 567 let c = Colorizer::new(ColorizerOption { 568 use_stderr: true, 569 when: color, 570 }); 571 Error { 572 message: format!( 573 "{} The subcommand '{}' wasn't recognized\n\n\ 574 {}\n\t\ 575 {} help <subcommands>...\n\n\ 576 For more information try {}", 577 c.error("error:"), 578 c.warning(&*s), 579 c.warning("USAGE:"), 580 name, 581 c.good("--help") 582 ), 583 kind: ErrorKind::UnrecognizedSubcommand, 584 info: Some(vec![s]), 585 } 586 } 587 588 #[doc(hidden)] missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self where R: Display, U: Display,589 pub fn missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self 590 where 591 R: Display, 592 U: Display, 593 { 594 let c = Colorizer::new(ColorizerOption { 595 use_stderr: true, 596 when: color, 597 }); 598 Error { 599 message: format!( 600 "{} The following required arguments were not provided:{}\n\n\ 601 {}\n\n\ 602 For more information try {}", 603 c.error("error:"), 604 required, 605 usage, 606 c.good("--help") 607 ), 608 kind: ErrorKind::MissingRequiredArgument, 609 info: None, 610 } 611 } 612 613 #[doc(hidden)] missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self where N: AsRef<str> + Display, U: Display,614 pub fn missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self 615 where 616 N: AsRef<str> + Display, 617 U: Display, 618 { 619 let c = Colorizer::new(ColorizerOption { 620 use_stderr: true, 621 when: color, 622 }); 623 Error { 624 message: format!( 625 "{} '{}' requires a subcommand, but one was not provided\n\n\ 626 {}\n\n\ 627 For more information try {}", 628 c.error("error:"), 629 c.warning(name), 630 usage, 631 c.good("--help") 632 ), 633 kind: ErrorKind::MissingSubcommand, 634 info: None, 635 } 636 } 637 638 639 #[doc(hidden)] invalid_utf8<U>(usage: U, color: ColorWhen) -> Self where U: Display,640 pub fn invalid_utf8<U>(usage: U, color: ColorWhen) -> Self 641 where 642 U: Display, 643 { 644 let c = Colorizer::new(ColorizerOption { 645 use_stderr: true, 646 when: color, 647 }); 648 Error { 649 message: format!( 650 "{} Invalid UTF-8 was detected in one or more arguments\n\n\ 651 {}\n\n\ 652 For more information try {}", 653 c.error("error:"), 654 usage, 655 c.good("--help") 656 ), 657 kind: ErrorKind::InvalidUtf8, 658 info: None, 659 } 660 } 661 662 #[doc(hidden)] too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, color: ColorWhen) -> Self where V: AsRef<str> + Display + ToOwned, A: AnyArg<'a, 'b> + Display, U: Display,663 pub fn too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, color: ColorWhen) -> Self 664 where 665 V: AsRef<str> + Display + ToOwned, 666 A: AnyArg<'a, 'b> + Display, 667 U: Display, 668 { 669 let v = val.as_ref(); 670 let c = Colorizer::new(ColorizerOption { 671 use_stderr: true, 672 when: color, 673 }); 674 Error { 675 message: format!( 676 "{} The value '{}' was provided to '{}', but it wasn't expecting \ 677 any more values\n\n\ 678 {}\n\n\ 679 For more information try {}", 680 c.error("error:"), 681 c.warning(v), 682 c.warning(arg.to_string()), 683 usage, 684 c.good("--help") 685 ), 686 kind: ErrorKind::TooManyValues, 687 info: Some(vec![arg.name().to_owned(), v.to_owned()]), 688 } 689 } 690 691 #[doc(hidden)] too_few_values<'a, 'b, A, U>( arg: &A, min_vals: u64, curr_vals: usize, usage: U, color: ColorWhen, ) -> Self where A: AnyArg<'a, 'b> + Display, U: Display,692 pub fn too_few_values<'a, 'b, A, U>( 693 arg: &A, 694 min_vals: u64, 695 curr_vals: usize, 696 usage: U, 697 color: ColorWhen, 698 ) -> Self 699 where 700 A: AnyArg<'a, 'b> + Display, 701 U: Display, 702 { 703 let c = Colorizer::new(ColorizerOption { 704 use_stderr: true, 705 when: color, 706 }); 707 Error { 708 message: format!( 709 "{} The argument '{}' requires at least {} values, but only {} w{} \ 710 provided\n\n\ 711 {}\n\n\ 712 For more information try {}", 713 c.error("error:"), 714 c.warning(arg.to_string()), 715 c.warning(min_vals.to_string()), 716 c.warning(curr_vals.to_string()), 717 if curr_vals > 1 { "ere" } else { "as" }, 718 usage, 719 c.good("--help") 720 ), 721 kind: ErrorKind::TooFewValues, 722 info: Some(vec![arg.name().to_owned()]), 723 } 724 } 725 726 #[doc(hidden)] value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display,727 pub fn value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: ColorWhen) -> Self 728 where 729 A: AnyArg<'a, 'b> + Display, 730 { 731 let c = Colorizer::new(ColorizerOption { 732 use_stderr: true, 733 when: color, 734 }); 735 Error { 736 message: format!( 737 "{} Invalid value{}: {}", 738 c.error("error:"), 739 if let Some(a) = arg { 740 format!(" for '{}'", c.warning(a.to_string())) 741 } else { 742 "".to_string() 743 }, 744 err 745 ), 746 kind: ErrorKind::ValueValidation, 747 info: None, 748 } 749 } 750 751 #[doc(hidden)] value_validation_auto(err: String) -> Self752 pub fn value_validation_auto(err: String) -> Self { 753 let n: Option<&FlagBuilder> = None; 754 Error::value_validation(n, err, ColorWhen::Auto) 755 } 756 757 #[doc(hidden)] wrong_number_of_values<'a, 'b, A, S, U>( arg: &A, num_vals: u64, curr_vals: usize, suffix: S, usage: U, color: ColorWhen, ) -> Self where A: AnyArg<'a, 'b> + Display, S: Display, U: Display,758 pub fn wrong_number_of_values<'a, 'b, A, S, U>( 759 arg: &A, 760 num_vals: u64, 761 curr_vals: usize, 762 suffix: S, 763 usage: U, 764 color: ColorWhen, 765 ) -> Self 766 where 767 A: AnyArg<'a, 'b> + Display, 768 S: Display, 769 U: Display, 770 { 771 let c = Colorizer::new(ColorizerOption { 772 use_stderr: true, 773 when: color, 774 }); 775 Error { 776 message: format!( 777 "{} The argument '{}' requires {} values, but {} w{} \ 778 provided\n\n\ 779 {}\n\n\ 780 For more information try {}", 781 c.error("error:"), 782 c.warning(arg.to_string()), 783 c.warning(num_vals.to_string()), 784 c.warning(curr_vals.to_string()), 785 suffix, 786 usage, 787 c.good("--help") 788 ), 789 kind: ErrorKind::WrongNumberOfValues, 790 info: Some(vec![arg.name().to_owned()]), 791 } 792 } 793 794 #[doc(hidden)] unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display,795 pub fn unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self 796 where 797 A: AnyArg<'a, 'b> + Display, 798 U: Display, 799 { 800 let c = Colorizer::new(ColorizerOption { 801 use_stderr: true, 802 when: color, 803 }); 804 Error { 805 message: format!( 806 "{} The argument '{}' was provided more than once, but cannot \ 807 be used multiple times\n\n\ 808 {}\n\n\ 809 For more information try {}", 810 c.error("error:"), 811 c.warning(arg.to_string()), 812 usage, 813 c.good("--help") 814 ), 815 kind: ErrorKind::UnexpectedMultipleUsage, 816 info: Some(vec![arg.name().to_owned()]), 817 } 818 } 819 820 #[doc(hidden)] unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self where A: Into<String>, U: Display,821 pub fn unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self 822 where 823 A: Into<String>, 824 U: Display, 825 { 826 let a = arg.into(); 827 let c = Colorizer::new(ColorizerOption { 828 use_stderr: true, 829 when: color, 830 }); 831 Error { 832 message: format!( 833 "{} Found argument '{}' which wasn't expected, or isn't valid in \ 834 this context{}\n\ 835 {}\n\n\ 836 For more information try {}", 837 c.error("error:"), 838 c.warning(&*a), 839 if did_you_mean.is_empty() { 840 "\n".to_owned() 841 } else { 842 format!("{}\n", did_you_mean) 843 }, 844 usage, 845 c.good("--help") 846 ), 847 kind: ErrorKind::UnknownArgument, 848 info: Some(vec![a]), 849 } 850 } 851 852 #[doc(hidden)] io_error(e: &Error, color: ColorWhen) -> Self853 pub fn io_error(e: &Error, color: ColorWhen) -> Self { 854 let c = Colorizer::new(ColorizerOption { 855 use_stderr: true, 856 when: color, 857 }); 858 Error { 859 message: format!("{} {}", c.error("error:"), e.description()), 860 kind: ErrorKind::Io, 861 info: None, 862 } 863 } 864 865 #[doc(hidden)] argument_not_found_auto<A>(arg: A) -> Self where A: Into<String>,866 pub fn argument_not_found_auto<A>(arg: A) -> Self 867 where 868 A: Into<String>, 869 { 870 let a = arg.into(); 871 let c = Colorizer::new(ColorizerOption { 872 use_stderr: true, 873 when: ColorWhen::Auto, 874 }); 875 Error { 876 message: format!( 877 "{} The argument '{}' wasn't found", 878 c.error("error:"), 879 a.clone() 880 ), 881 kind: ErrorKind::ArgumentNotFound, 882 info: Some(vec![a]), 883 } 884 } 885 886 /// Create an error with a custom description. 887 /// 888 /// This can be used in combination with `Error::exit` to exit your program 889 /// with a custom error message. with_description(description: &str, kind: ErrorKind) -> Self890 pub fn with_description(description: &str, kind: ErrorKind) -> Self { 891 let c = Colorizer::new(ColorizerOption { 892 use_stderr: true, 893 when: ColorWhen::Auto, 894 }); 895 Error { 896 message: format!("{} {}", c.error("error:"), description), 897 kind: kind, 898 info: None, 899 } 900 } 901 } 902 903 impl StdError for Error { description(&self) -> &str904 fn description(&self) -> &str { &*self.message } 905 } 906 907 impl Display for Error { fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result908 fn fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result { writeln!(f, "{}", self.message) } 909 } 910 911 impl From<io::Error> for Error { from(e: io::Error) -> Self912 fn from(e: io::Error) -> Self { Error::with_description(e.description(), ErrorKind::Io) } 913 } 914 915 impl From<std_fmt::Error> for Error { from(e: std_fmt::Error) -> Self916 fn from(e: std_fmt::Error) -> Self { 917 Error::with_description(e.description(), ErrorKind::Format) 918 } 919 } 920