1use std::path::PathBuf;
2use std::sync::Arc;
3
4#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
5pub struct ExitCode(i32);
6pub const EXIT_OK: ExitCode = ExitCode(0);
7pub const EXIT_KNOWN_ERR: ExitCode = ExitCode(1);
8pub const EXIT_OTHER_ERR: ExitCode = ExitCode(2);
9impl ExitCode {
10 pub fn cmp_and_replace(&mut self, code: ExitCode) {
21 self.0 = std::cmp::max(self.0, code.0);
22 }
23 pub fn code(&self) -> i32 {
24 self.0
25 }
26}
27
28#[derive(Debug, Clone, Copy, Eq, PartialEq)]
29pub enum SysPath {
30 Config,
31 Home,
32}
33#[derive(Debug, Clone, Copy, Eq, PartialEq)]
34pub enum FormatCode {
35 PromptLevel,
36 Config,
37 ScriptName,
38 ScriptType,
39 Regex,
40 RangeQuery,
41 ScriptQuery,
42 Tag,
43 NonEmptyArray,
44 EnvPair,
45 Template, }
47
48impl FormatCode {
49 pub fn to_err(&self, s: String) -> Error {
50 Error::Format(*self, s)
51 }
52 pub fn to_res<T>(&self, s: String) -> Result<T> {
53 Err(Error::Format(*self, s))
54 }
55 pub fn to_display_res<T>(&self, s: String) -> DisplayResult<T> {
56 Err(Error::Format(*self, s).into())
57 }
58}
59
60#[derive(Debug, Clone)]
61pub enum Error {
62 Others(
63 Vec<String>,
64 Option<Arc<dyn 'static + Send + Sync + std::error::Error>>,
65 ),
66 SysPathNotFound(SysPath),
67 EmptyCreate,
68
69 PermissionDenied(Vec<PathBuf>),
70 PathNotFound(Vec<PathBuf>),
72 GeneralFS(Vec<PathBuf>, Arc<std::io::Error>),
73
74 PathExist(PathBuf),
75 ScriptExist(String),
76 ScriptIsFiltered(String),
77 ScriptNotFound(String),
78 NoAlias(String),
79 UnknownType(String),
80 Format(FormatCode, String),
81
82 ScriptError(i32),
83 PreRunError(i32),
84 EditorError(i32, Vec<String>),
85
86 RedundantOpt(RedundantOpt),
87 TagSelectorNotFound(String),
88 DontFuzz,
89 NoPreviousArgs,
90 Empty,
91 Caution,
92
93 Completion,
94}
95
96impl<T: 'static + Send + Sync + std::error::Error> From<T> for Error {
97 fn from(t: T) -> Self {
98 Error::Others(vec![], Some(Arc::new(t)))
99 }
100}
101impl Error {
102 pub fn msg<T: ToString>(s: T) -> Self {
103 Error::Others(vec![s.to_string()], None)
104 }
105 pub fn context<T: ToString>(mut self, s: T) -> Self {
106 log::debug!("附註:{:?} + {}", self, s.to_string());
107 if let Error::Others(msg, ..) = &mut self {
108 msg.push(s.to_string());
109 }
110 self
111 }
112 pub fn code(&self) -> ExitCode {
113 use Error::*;
114 match self {
115 Others(..) | GeneralFS(..) => EXIT_OTHER_ERR,
116 ScriptError(c) | PreRunError(c) | EditorError(c, _) => ExitCode(*c),
117 _ => EXIT_KNOWN_ERR,
118 }
119 }
120}
121
122pub type Result<T = ()> = std::result::Result<T, Error>;
123
124pub trait Contextable<T> {
125 fn context<S: ToString>(self, s: S) -> Result<T>;
126}
127impl<T> Contextable<T> for Result<T> {
128 fn context<S: ToString>(self, s: S) -> Result<T> {
129 match self {
130 Ok(t) => Ok(t),
131 Err(e) => Err(e.context(s)),
132 }
133 }
134}
135
136impl<T, E: 'static + Send + Sync + std::error::Error> Contextable<T> for std::result::Result<T, E> {
137 fn context<S: ToString>(self, s: S) -> Result<T> {
138 match self {
139 Ok(t) => Ok(t),
140 Err(e) => {
141 let e: Error = e.into();
142 Err(e.context(s))
143 }
144 }
145 }
146}
147#[derive(Debug, Clone)]
148pub enum RedundantOpt {
149 Scripts(Vec<String>),
150 Tag,
151 Type,
152 Selector,
153}
154
155impl From<RedundantOpt> for Error {
156 fn from(opt: RedundantOpt) -> Self {
157 Error::RedundantOpt(opt)
158 }
159}
160
161#[derive(Display, Debug)]
163pub struct DisplayError(Error);
164impl From<Error> for DisplayError {
165 fn from(err: Error) -> Self {
166 DisplayError(err)
167 }
168}
169impl DisplayError {
170 pub fn into_err(self) -> Error {
171 self.0
172 }
173}
174impl std::error::Error for DisplayError {}
175pub type DisplayResult<T = ()> = std::result::Result<T, DisplayError>;