runi_cli/launcher/
error.rs1use std::fmt;
2
3#[derive(Debug)]
5pub enum Error {
6 UnknownOption(String),
7 UnknownSubcommand {
8 name: String,
9 available: Vec<String>,
10 },
11 MissingValue(String),
12 UnexpectedValue(String),
13 MissingOption(String),
17 MissingArgument(String),
18 MissingSubcommand {
19 available: Vec<String>,
20 },
21 ExtraArgument(String),
22 InvalidValue {
23 name: String,
24 value: String,
25 message: String,
26 },
27 HelpRequested,
29 InSubcommand {
33 path: Vec<String>,
34 source: Box<Error>,
35 },
36 Runtime(Box<Error>),
43 Custom(String),
44}
45
46impl Error {
47 pub fn invalid_value(
48 name: impl Into<String>,
49 value: impl Into<String>,
50 message: impl Into<String>,
51 ) -> Self {
52 Self::InvalidValue {
53 name: name.into(),
54 value: value.into(),
55 message: message.into(),
56 }
57 }
58
59 pub fn custom(message: impl Into<String>) -> Self {
60 Self::Custom(message.into())
61 }
62
63 pub fn is_parse_error(&self) -> bool {
67 matches!(
68 self,
69 Error::UnknownOption(_)
70 | Error::UnknownSubcommand { .. }
71 | Error::MissingValue(_)
72 | Error::UnexpectedValue(_)
73 | Error::MissingOption(_)
74 | Error::MissingArgument(_)
75 | Error::MissingSubcommand { .. }
76 | Error::ExtraArgument(_)
77 | Error::InvalidValue { .. }
78 | Error::HelpRequested
79 | Error::InSubcommand { .. }
80 )
81 }
82}
83
84impl fmt::Display for Error {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self {
87 Error::UnknownOption(opt) => write!(f, "unknown option: {opt}"),
88 Error::UnknownSubcommand { name, available } => {
89 write!(f, "unknown subcommand: {name}")?;
90 if !available.is_empty() {
91 write!(f, " (available: {})", available.join(", "))?;
92 }
93 Ok(())
94 }
95 Error::MissingValue(opt) => write!(f, "missing value for option: {opt}"),
96 Error::UnexpectedValue(opt) => write!(f, "option {opt} does not take a value"),
97 Error::MissingOption(name) => write!(f, "missing required option: {name}"),
98 Error::MissingArgument(name) => write!(f, "missing required argument: <{name}>"),
99 Error::MissingSubcommand { available } => {
100 write!(f, "a subcommand is required")?;
101 if !available.is_empty() {
102 write!(f, " (available: {})", available.join(", "))?;
103 }
104 Ok(())
105 }
106 Error::ExtraArgument(arg) => write!(f, "unexpected argument: {arg}"),
107 Error::InvalidValue {
108 name,
109 value,
110 message,
111 } => {
112 write!(f, "invalid value '{value}' for {name}: {message}")
113 }
114 Error::HelpRequested => write!(f, "help requested"),
115 Error::InSubcommand { path, source } => {
116 write!(f, "in subcommand '{}': {}", path.join(" "), source)
117 }
118 Error::Runtime(inner) => write!(f, "{inner}"),
119 Error::Custom(msg) => write!(f, "{msg}"),
120 }
121 }
122}
123
124impl std::error::Error for Error {}
125
126pub type Result<T> = std::result::Result<T, Error>;