ex-cli 1.21.0

Command line tool to find, filter, sort and list files.
Documentation
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)
    }
}