pub type Result<T> = std::result::Result<T, PmpxError>;
pub const EXIT_OK: u8 = 0;
pub const EXIT_INTERNAL: u8 = 1;
pub const EXIT_USAGE: u8 = 2;
pub const EXIT_NOT_FOUND: u8 = 3;
#[derive(Debug, thiserror::Error)]
pub enum PmpxError {
#[error("{0}")]
Usage(String),
#[error("{0}")]
NotFound(String),
#[error(transparent)]
Other(#[from] anyhow::Error),
#[error("{0}")]
Backend(String, u8),
}
impl PmpxError {
pub fn exit_code(&self) -> u8 {
match self {
PmpxError::Usage(_) => EXIT_USAGE,
PmpxError::NotFound(_) => EXIT_NOT_FOUND,
PmpxError::Other(_) => EXIT_INTERNAL,
PmpxError::Backend(_, code) => *code,
}
}
pub fn not_found(message: impl Into<String>) -> Self {
PmpxError::NotFound(message.into())
}
}
pub fn error_line(body: impl std::fmt::Display) {
anstream::eprintln!(
"{} {}",
crate::style::paint(crate::style::ERROR, "pmpx:"),
crate::style::paint(crate::style::ERROR_BODY, body)
);
}
pub fn note_line(body: impl std::fmt::Display) {
anstream::eprintln!(
"{}",
crate::style::paint(crate::style::DIM, format!("pmpx: {body}"))
);
}
impl From<pmpx_engine::EngineError> for PmpxError {
fn from(error: pmpx_engine::EngineError) -> Self {
use pmpx_engine::EngineError;
match error {
EngineError::Usage(message) => PmpxError::Usage(message),
EngineError::NotFound(message) | EngineError::Setup(message) => {
PmpxError::NotFound(message)
}
EngineError::NoProject(message) => PmpxError::NotFound(message),
EngineError::Detect(failure) => PmpxError::NotFound(failure.message()),
EngineError::Kit(error) => PmpxError::Other(anyhow::Error::new(error)),
EngineError::Call {
plugin,
verb,
error,
} => PmpxError::Backend(
format!("plugin {plugin} cannot do `{verb}`: {error}"),
call_exit_code(&error),
),
EngineError::Start { .. } => PmpxError::Other(anyhow::anyhow!(error)),
}
}
}
fn call_exit_code(error: &pmpx_loader::CallError) -> u8 {
match error {
pmpx_loader::CallError::UnsupportedVerb
| pmpx_loader::CallError::InvalidArgs
| pmpx_loader::CallError::ShortCommand { .. } => EXIT_USAGE,
pmpx_loader::CallError::Internal | pmpx_loader::CallError::Unknown(_) => EXIT_INTERNAL,
}
}