use std::fmt::Display;
use std::path::{Path, StripPrefixError};
use std::{io, num};
use thiserror::Error;
pub type MyResult<T> = Result<T, MyError>;
#[derive(Debug, Error)]
pub enum MyError {
#[error(transparent)]
Chrono(#[from] chrono::ParseError),
#[error(transparent)]
Clap(#[from] clap::error::Error),
#[error(transparent)]
Git(#[from] git2::Error),
#[error("{0}: {1}")]
Glob(glob::PatternError, String),
#[error(transparent)]
Io(#[from] io::Error),
#[error("{0}: {1}")]
Io2(io::Error, String),
#[error(transparent)]
ParseInt(#[from] num::ParseIntError),
#[error("{0}: {1}")]
PkZip(zip::result::ZipError, String),
#[error("{0}: {1}")]
Prefix(StripPrefixError, String),
#[error(transparent)]
Regex(#[from] regex::Error),
#[error("{0}: {1}")]
SevenZ(sevenz_rust2::Error, String),
#[error(transparent)]
Walk(#[from] walkdir::Error),
#[error("{0}")]
Text(String),
}
impl MyError {
pub fn create_clap<T: Display>(option: &str, value: T) -> Self {
let message = format!("Invalid {option} option: {value}");
let error = clap::Error::raw(clap::error::ErrorKind::ValueValidation, message);
Self::Clap(error)
}
pub fn print_error(&self) {
if let Some(help) = self.get_help() {
let help = help.trim_end();
println!("{help}");
} else {
let error = self.to_string();
let error = error.trim_end();
eprintln!("{error}");
}
}
fn get_help(&self) -> Option<String> {
if let Self::Clap(err) = self {
match err.kind() {
clap::error::ErrorKind::DisplayHelp => Some(err.to_string()),
clap::error::ErrorKind::DisplayVersion => Some(err.to_string()),
_ => None,
}
} else {
None
}
}
}
impl From<(glob::PatternError, &String)> for MyError {
fn from(value: (glob::PatternError, &String)) -> Self {
let (error, glob) = value;
let glob = glob.to_string();
Self::Glob(error, glob)
}
}
impl From<(io::Error, &Path)> for MyError {
fn from(value: (io::Error, &Path)) -> Self {
let (error, path) = value;
let path = path.display().to_string();
Self::Io2(error, path)
}
}
impl From<(zip::result::ZipError, &Path)> for MyError {
fn from(value: (zip::result::ZipError, &Path)) -> Self {
let (error, path) = value;
let path = path.display().to_string();
Self::PkZip(error, path)
}
}
impl From<(StripPrefixError, &Path)> for MyError {
fn from(value: (StripPrefixError, &Path)) -> Self {
let (error, path) = value;
let path = path.display().to_string();
Self::Prefix(error, path)
}
}
impl From<(sevenz_rust2::Error, &Path)> for MyError {
fn from(value: (sevenz_rust2::Error, &Path)) -> Self {
let (error, path) = value;
let path = path.display().to_string();
Self::SevenZ(error, path)
}
}
impl From<&str> for MyError {
fn from(error: &str) -> Self {
let error = error.to_string();
Self::Text(error)
}
}