1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use {
custom_error::custom_error,
image::error::ImageError,
regex,
std::io,
};
custom_error! {pub ProgramError
AmbiguousVerbName {name: String} = "Ambiguous name: More than one verb matches {name:?}",
ArgParse {bad: String, valid: String} = "{bad:?} can't be parsed (valid values: {valid:?})",
Conf {source: ConfError} = "Bad configuration: {source}",
ConfFile {path:String, details: ConfError} = "Bad configuration file {path:?} : {details}",
ImageError {source: ImageError } = "{source}",
InternalError {details: String} = "Internal error: {details}", InvalidGlobError {pattern: String} = "Invalid glob: {pattern}",
Io {source: io::Error} = "IO Error : {source}",
LaunchError {program: String, source: io::Error} = "Unable to launch {program}: {source}",
Lfs {details: String} = "Failed to fetch mounts: {details}",
NetError {source: NetError} = "{source}",
OpenError { source: opener::OpenError } = "Open error: {source}",
ShelInstall { source: ShellInstallError } = "{source}",
Svg {source: SvgError} = "SVG error: {source}",
SyntectCrashed { details: String } = "Syntect crashed on {details:?}",
Termimad {source: termimad::Error} = "Termimad Error : {source}",
TreeBuild {source: TreeBuildError} = "{source}",
UnknowShell {shell: String} = "Unknown shell: {shell}",
UnknownVerb {name: String} = "No verb matches {name:?}",
UnmappableFile = "File can't be mapped",
UnmatchingVerbArgs {name: String} = "No matching argument found for verb {name:?}",
UnprintableFile = "File can't be printed", Unrecognized {token: String} = "Unrecognized: {token}",
ZeroLenFile = "File seems empty",
}
custom_error!{pub ShellInstallError
Io {source: io::Error, when: String} = "IO Error {source} on {when}",
}
impl ShellInstallError {
pub fn is_permission_denied(&self) -> bool {
match self {
Self::Io { source, .. } => {
if source.kind() == io::ErrorKind::PermissionDenied {
true
} else if cfg!(windows) && source.raw_os_error().unwrap_or(0) == 1314 {
true
} else {
false
}
}
}
}
}
pub trait IoToShellInstallError<Ok> {
fn context(self, f: &dyn Fn() -> String) -> Result<Ok, ShellInstallError>;
}
impl<Ok> IoToShellInstallError<Ok> for Result<Ok, io::Error> {
fn context(self, f: &dyn Fn() -> String) -> Result<Ok, ShellInstallError> {
self.map_err(|source| ShellInstallError::Io {
source, when: f()
})
}
}
custom_error! {pub TreeBuildError
NotADirectory { path: String } = "Not a directory: {path}",
FileNotFound { path: String } = "File not found: {path}",
Interrupted = "Task Interrupted",
TooManyMatches { max: usize } = "Too many matches (max allowed: {max})",
}
custom_error! {pub ConfError
Io {source: io::Error} = "unable to read from the file: {source}",
ImportNotFound {path: String} = "import file not found: {path:?}",
UnknownFileExtension { path: String} = "unexpected file extension in {path:?}",
Toml {source: toml::de::Error} = "unable to parse TOML: {source}",
Hjson {source: deser_hjson::Error} = "unable to parse Hjson: {source}",
Invalid = "unexpected conf structure", MissingField {txt: String} = "missing field in conf",
InvalidVerbInvocation {invocation: String} = "invalid verb invocation: {invocation}",
InvalidVerbConf {details: String} = "invalid verb conf: {details}",
UnknownInternal {verb: String} = "not a known internal: {verb}",
InvalidSearchMode {details: String} = "invalid search mode: {details}",
InvalidKey {raw: String} = "not a valid key: {raw}",
ParseKey {source: crokey::ParseKeyError} = "{source}",
ReservedKey {key: String} = "reserved key: {key}",
UnexpectedInternalArg {invocation: String} = "unexpected argument for internal: {invocation}",
InvalidCols {details: String} = "invalid cols definition: {details}",
InvalidSkin {source: InvalidSkinError} = "invalid skin: {source}",
InvalidThreadsCount { count: usize } = "invalid threads count: {count}",
InvalidDefaultFlags { flags: String } = "invalid default flags: {flags:?}",
InvalidSyntaxTheme { name: String } = "invalid syntax theme: {name:?}",
}
custom_error! {pub PatternError
InvalidMode { mode: String } = "Invalid search mode: {mode:?}",
InvalidRegex {source: regex::Error} = @{
format!("Invalid Regular Expression: {}", source.to_string().lines().last().unwrap_or(""))
},
UnknownRegexFlag {bad: char} = "Unknown regular expression flag: {bad:?}",
}
custom_error! {pub InvalidSkinError
InvalidColor { raw : String } = "'{raw}' is not a valid color",
InvalidAttribute { raw : String } = "'{raw}' is not a valid style attribute",
InvalidGreyLevel { level: u8 } = "grey level must be between 0 and 23 (got {level})",
InvalidStyle {style: String} = "Invalid skin style : {style}",
}
custom_error! {pub NetError
SocketNotAvailable { path : String } = "Can't open socket: {path} already exists - consider removing it",
Io {source: io::Error} = "error on the socket: {source}",
InvalidMessage = "invalid message received",
}
custom_error! {pub SvgError
Io {source: io::Error} = "IO Error : {source}",
Internal { message: &'static str } = "Internal error : {message}",
Svg {source: usvg::Error} = "SVG Error: {source}",
}