cli_forge/error.rs
1//! Parse errors.
2//!
3//! Every way command-line input can be malformed maps to a [`ParseError`]
4//! variant — never a panic. The error carries enough context to tell the user
5//! what was wrong (which flag, which argument), and it renders through the same
6//! output system as everything else: [`App::parse`](crate::App::parse) prints it
7//! to standard error and exits, while
8//! [`App::try_parse_from`](crate::App::try_parse_from) hands it back for the
9//! caller to handle.
10
11use std::error::Error;
12use std::fmt;
13
14/// A failure to parse command-line arguments.
15///
16/// Returned by [`App::try_parse_from`](crate::App::try_parse_from). The variants
17/// are marked `#[non_exhaustive]` so future versions can add cases (for example,
18/// as the help and auth seams land) without a breaking change.
19#[derive(Debug, Clone, PartialEq, Eq)]
20#[non_exhaustive]
21pub enum ParseError {
22 /// A `-x` / `--name` flag was given that no argument at this level declares.
23 UnknownFlag {
24 /// The flag as the user wrote it, e.g. `--verbsoe`.
25 flag: String,
26 },
27 /// An option that takes a value was given without one (it was the last
28 /// token, or followed only by another option).
29 MissingValue {
30 /// The option's name.
31 option: String,
32 },
33 /// A required argument was not provided.
34 MissingRequired {
35 /// The missing argument's name.
36 arg: String,
37 },
38 /// A subcommand name was expected but the token matched no registered
39 /// command.
40 UnknownCommand {
41 /// The unrecognized command name.
42 name: String,
43 },
44 /// A bare value was given that no positional argument or subcommand can
45 /// accept.
46 UnexpectedArgument {
47 /// The surplus value.
48 value: String,
49 },
50 /// Not an error: `-h` / `--help` was requested. Carries the rendered help
51 /// text. [`App::parse`](crate::App::parse) prints it to standard output and
52 /// exits `0`; callers of
53 /// [`App::try_parse_from`](crate::App::try_parse_from) should do the same.
54 HelpRequested(String),
55 /// Not an error: `-V` / `--version` was requested. Carries the version
56 /// string. Handled like [`HelpRequested`](ParseError::HelpRequested).
57 VersionRequested(String),
58}
59
60impl fmt::Display for ParseError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 ParseError::UnknownFlag { flag } => write!(f, "unknown flag: {flag}"),
64 ParseError::MissingValue { option } => {
65 write!(f, "missing value for option: {option}")
66 }
67 ParseError::MissingRequired { arg } => {
68 write!(f, "missing required argument: {arg}")
69 }
70 ParseError::UnknownCommand { name } => write!(f, "unknown command: {name}"),
71 ParseError::UnexpectedArgument { value } => {
72 write!(f, "unexpected argument: {value}")
73 }
74 ParseError::HelpRequested(text) | ParseError::VersionRequested(text) => {
75 write!(f, "{text}")
76 }
77 }
78 }
79}
80
81impl Error for ParseError {}