Skip to main content

ex_cli/
error.rs

1use std::fmt::Display;
2use std::path::{Path, StripPrefixError};
3use std::{io, num};
4use thiserror::Error;
5
6pub type MyResult<T> = Result<T, MyError>;
7
8#[derive(Debug, Error)]
9pub enum MyError {
10    #[error(transparent)]
11    Chrono(#[from] chrono::ParseError),
12    #[error(transparent)]
13    Clap(#[from] clap::error::Error),
14    #[error(transparent)]
15    Git(#[from] git2::Error),
16    #[error("{0}: {1}")]
17    Glob(glob::PatternError, String),
18    #[error(transparent)]
19    Io(#[from] io::Error),
20    #[error("{0}: {1}")]
21    Io2(io::Error, String),
22    #[error(transparent)]
23    ParseInt(#[from] num::ParseIntError),
24    #[error("{0}: {1}")]
25    PkZip(zip::result::ZipError, String),
26    #[error("{0}: {1}")]
27    Prefix(StripPrefixError, String),
28    #[error(transparent)]
29    Regex(#[from] regex::Error),
30    #[error("{0}: {1}")]
31    SevenZ(sevenz_rust2::Error, String),
32    #[error(transparent)]
33    Walk(#[from] walkdir::Error),
34    #[error("{0}")]
35    Text(String),
36}
37
38impl MyError {
39    pub fn create_clap<T: Display>(option: &str, value: T) -> Self {
40        let message = format!("Invalid {option} option: {value}");
41        let error = clap::Error::raw(clap::error::ErrorKind::ValueValidation, message);
42        Self::Clap(error)
43    }
44
45    pub fn print_error(&self) {
46        if let Some(help) = self.get_help() {
47            let help = help.trim_end();
48            println!("{help}");
49        } else {
50            let error = self.to_string();
51            let error = error.trim_end();
52            eprintln!("{error}");
53        }
54    }
55
56    fn get_help(&self) -> Option<String> {
57        if let Self::Clap(err) = self {
58            match err.kind() {
59                clap::error::ErrorKind::DisplayHelp => Some(err.to_string()),
60                clap::error::ErrorKind::DisplayVersion => Some(err.to_string()),
61                _ => None,
62            }
63        } else {
64            None
65        }
66    }
67}
68
69impl From<(glob::PatternError, &String)> for MyError {
70    fn from(value: (glob::PatternError, &String)) -> Self {
71        let (error, glob) = value;
72        let glob = glob.to_string();
73        Self::Glob(error, glob)
74    }
75}
76
77impl From<(io::Error, &Path)> for MyError {
78    fn from(value: (io::Error, &Path)) -> Self {
79        let (error, path) = value;
80        let path = path.display().to_string();
81        Self::Io2(error, path)
82    }
83}
84
85impl From<(zip::result::ZipError, &Path)> for MyError {
86    fn from(value: (zip::result::ZipError, &Path)) -> Self {
87        let (error, path) = value;
88        let path = path.display().to_string();
89        Self::PkZip(error, path)
90    }
91}
92
93impl From<(StripPrefixError, &Path)> for MyError {
94    fn from(value: (StripPrefixError, &Path)) -> Self {
95        let (error, path) = value;
96        let path = path.display().to_string();
97        Self::Prefix(error, path)
98    }
99}
100
101impl From<(sevenz_rust2::Error, &Path)> for MyError {
102    fn from(value: (sevenz_rust2::Error, &Path)) -> Self {
103        let (error, path) = value;
104        let path = path.display().to_string();
105        Self::SevenZ(error, path)
106    }
107}
108
109impl From<&str> for MyError {
110    fn from(error: &str) -> Self {
111        let error = error.to_string();
112        Self::Text(error)
113    }
114}