use miette::{Diagnostic, NamedSource, SourceSpan};
use thiserror::Error;
#[derive(Error, Diagnostic, Debug)]
#[non_exhaustive]
pub enum UsageErr {
#[error("Invalid flag `{token}`: {reason}")]
InvalidFlag {
token: String,
reason: String,
#[label("{reason}")]
span: SourceSpan,
#[source_code]
input: String,
},
#[error("Missing required flag: --{0} <{0}>")]
MissingFlag(String),
#[error("Flag --{0} cannot be used multiple times")]
DuplicateFlag(String),
#[error("Missing one of the required flags in group {group}: {members}")]
MissingGroup { group: String, members: String },
#[error("Invalid usage config")]
InvalidInput(
String,
#[label = "{0}"] SourceSpan,
#[source_code] NamedSource<String>,
),
#[error("Missing required arg: <{0}>")]
MissingArg(String),
#[error("`{0}` needs a subcommand: one of {1}")]
MissingSubcommand(String, String),
#[error("Argument <{0}> can only be set after a `--` separator")]
ArgRequiresDoubleDash(String),
#[error("{0}")]
Help(String),
#[error("{0}")]
Version(String),
#[error("Invalid usage config")]
#[diagnostic(transparent)]
Miette(#[from] miette::MietteError),
#[error(transparent)]
IO(#[from] std::io::Error),
#[error(transparent)]
Strum(#[from] strum::ParseError),
#[error(transparent)]
FromUtf8Error(#[from] std::string::FromUtf8Error),
#[cfg(feature = "tera")]
#[error(transparent)]
TeraError(#[from] tera::Error),
#[error(transparent)]
#[diagnostic(transparent)]
KdlError(#[from] kdl::KdlError),
#[error("{0}\nFile: {1}")]
#[diagnostic(code(usage::file))]
FileError(std::io::Error, std::path::PathBuf),
#[error("{0}")]
#[diagnostic(code(usage::shell))]
ShellError(String),
#[error("Variadic argument <{name}> requires at least {min} value(s), got {got}")]
VarArgTooFew {
name: String,
min: usize,
got: usize,
},
#[error("Variadic argument <{name}> accepts at most {max} value(s), got {got}")]
VarArgTooMany {
name: String,
max: usize,
got: usize,
},
#[error("Variadic flag --{name} requires at least {min} value(s), got {got}")]
VarFlagTooFew {
name: String,
min: usize,
got: usize,
},
#[error("Variadic flag --{name} accepts at most {max} value(s), got {got}")]
VarFlagTooMany {
name: String,
max: usize,
got: usize,
},
#[error("Invalid file path: {0}")]
InvalidPath(String),
#[error("Invalid spec view: {0}")]
InvalidView(String),
#[error("Invalid value for {name}: {value}: {reason}")]
InvalidValue {
name: String,
value: String,
reason: String,
},
#[error("Unsupported shell: {0}")]
UnsupportedShell(String),
#[error("No injected output was provided for mount command: {0}")]
MissingMountOutput(String),
}
pub type Result<T> = std::result::Result<T, UsageErr>;
#[macro_export]
macro_rules! bail_parse {
($ctx:expr, $span:expr, $fmt:literal) => {{
let span: miette::SourceSpan = ($span.offset(), $span.len()).into();
let msg = format!($fmt);
let err = $ctx.build_err(msg, span);
return std::result::Result::Err(err);
}};
($ctx:expr, $span:expr, $fmt:literal, $($arg:tt)*) => {{
let span: miette::SourceSpan = ($span.offset(), $span.len()).into();
let msg = format!($fmt, $($arg)*);
let err = $ctx.build_err(msg, span);
return std::result::Result::Err(err);
}};
}