#![allow(dead_code)] #![allow(unused_assignments)]
use miette::Diagnostic;
use thiserror::Error;
use crate::exit_codes;
#[derive(Error, Debug, Diagnostic, Clone)]
pub enum CliError {
#[error("Validation failed: {message}")]
#[diagnostic(code(sherpack::cli::validation))]
Validation {
message: String,
#[help]
help: Option<String>,
},
#[error("Template error: {message}")]
#[diagnostic(code(sherpack::cli::template))]
Template {
message: String,
#[help]
help: Option<String>,
},
#[error("Pack error: {message}")]
#[diagnostic(code(sherpack::cli::pack))]
Pack {
message: String,
#[help]
help: Option<String>,
},
#[error("Linting failed with {errors} error(s) and {warnings} warning(s)")]
#[diagnostic(code(sherpack::cli::lint))]
LintFailed { errors: usize, warnings: usize },
#[error("IO error: {message}")]
#[diagnostic(code(sherpack::cli::io))]
Io { message: String },
#[error("{message}")]
#[diagnostic(code(sherpack::cli::error))]
Other { message: String },
#[error("Internal error: {message}")]
#[diagnostic(code(sherpack::cli::internal))]
Internal { message: String },
}
impl CliError {
pub fn exit_code(&self) -> i32 {
match self {
CliError::Validation { .. } => exit_codes::VALIDATION_ERROR,
CliError::Template { .. } => exit_codes::TEMPLATE_ERROR,
CliError::Pack { .. } => exit_codes::PACK_ERROR,
CliError::LintFailed { .. } => exit_codes::ERROR,
CliError::Io { .. } => exit_codes::IO_ERROR,
CliError::Other { .. } => exit_codes::ERROR,
CliError::Internal { .. } => exit_codes::ERROR,
}
}
pub fn internal(message: impl Into<String>) -> Self {
Self::Internal {
message: message.into(),
}
}
pub fn validation(message: impl Into<String>) -> Self {
Self::Validation {
message: message.into(),
help: None,
}
}
pub fn validation_with_help(message: impl Into<String>, help: impl Into<String>) -> Self {
Self::Validation {
message: message.into(),
help: Some(help.into()),
}
}
pub fn template(message: impl Into<String>) -> Self {
Self::Template {
message: message.into(),
help: None,
}
}
pub fn pack(message: impl Into<String>) -> Self {
Self::Pack {
message: message.into(),
help: None,
}
}
pub fn lint_failed(errors: usize, warnings: usize) -> Self {
Self::LintFailed { errors, warnings }
}
pub fn input(message: impl Into<String>) -> Self {
Self::Validation {
message: message.into(),
help: None,
}
}
pub fn io(err: std::io::Error) -> Self {
Self::Io {
message: err.to_string(),
}
}
}
impl From<std::io::Error> for CliError {
fn from(err: std::io::Error) -> Self {
CliError::Io {
message: err.to_string(),
}
}
}
impl From<miette::Report> for CliError {
fn from(err: miette::Report) -> Self {
CliError::Other {
message: format!("{:?}", err),
}
}
}
pub type Result<T> = std::result::Result<T, CliError>;
pub trait IntoCliResult<T> {
fn into_cli_result(self) -> Result<T>;
}
impl<T> IntoCliResult<T> for miette::Result<T> {
fn into_cli_result(self) -> Result<T> {
self.map_err(CliError::from)
}
}