1use miette::{Diagnostic, NamedSource, SourceSpan};
2use thiserror::Error;
3
4#[derive(Error, Diagnostic, Debug)]
5pub enum UsageErr {
6 #[error("Invalid flag `{token}`: {reason}")]
7 InvalidFlag {
8 token: String,
9 reason: String,
10 #[label("{reason}")]
11 span: SourceSpan,
12 #[source_code]
13 input: String,
14 },
15
16 #[error("Missing required flag: --{0} <{0}>")]
17 MissingFlag(String),
18
19 #[error("Invalid usage config")]
20 InvalidInput(
21 String,
22 #[label = "{0}"] SourceSpan,
23 #[source_code] NamedSource<String>,
24 ),
25
26 #[error("Missing required arg: <{0}>")]
27 MissingArg(String),
28
29 #[error("Argument <{0}> can only be set after a `--` separator")]
30 ArgRequiresDoubleDash(String),
31
32 #[error("{0}")]
33 Help(String),
34
35 #[error("Invalid usage config")]
36 #[diagnostic(transparent)]
37 Miette(#[from] miette::MietteError),
38
39 #[error(transparent)]
40 IO(#[from] std::io::Error),
41
42 #[error(transparent)]
43 Strum(#[from] strum::ParseError),
44
45 #[error(transparent)]
46 FromUtf8Error(#[from] std::string::FromUtf8Error),
47
48 #[cfg(feature = "tera")]
49 #[error(transparent)]
50 TeraError(#[from] tera::Error),
51
52 #[error(transparent)]
53 #[diagnostic(transparent)]
54 KdlError(#[from] kdl::KdlError),
55
56 #[error(transparent)]
57 #[diagnostic(transparent)]
58 XXError(#[from] xx::error::XXError),
59
60 #[error("Variadic argument <{name}> requires at least {min} value(s), got {got}")]
61 VarArgTooFew {
62 name: String,
63 min: usize,
64 got: usize,
65 },
66
67 #[error("Variadic argument <{name}> accepts at most {max} value(s), got {got}")]
68 VarArgTooMany {
69 name: String,
70 max: usize,
71 got: usize,
72 },
73
74 #[error("Variadic flag --{name} requires at least {min} value(s), got {got}")]
75 VarFlagTooFew {
76 name: String,
77 min: usize,
78 got: usize,
79 },
80
81 #[error("Variadic flag --{name} accepts at most {max} value(s), got {got}")]
82 VarFlagTooMany {
83 name: String,
84 max: usize,
85 got: usize,
86 },
87
88 #[error("Invalid file path: {0}")]
89 InvalidPath(String),
90
91 #[error("Unsupported shell: {0}")]
92 UnsupportedShell(String),
93}
94pub type Result<T> = std::result::Result<T, UsageErr>;
95
96#[macro_export]
97macro_rules! bail_parse {
98 ($ctx:expr, $span:expr, $fmt:literal) => {{
99 let span: miette::SourceSpan = ($span.offset(), $span.len()).into();
100 let msg = format!($fmt);
101 let err = $ctx.build_err(msg, span);
102 return std::result::Result::Err(err);
103 }};
104 ($ctx:expr, $span:expr, $fmt:literal, $($arg:tt)*) => {{
105 let span: miette::SourceSpan = ($span.offset(), $span.len()).into();
106 let msg = format!($fmt, $($arg)*);
107 let err = $ctx.build_err(msg, span);
108 return std::result::Result::Err(err);
109 }};
110}