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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
use fmt::Debug;
use crate::{Command, Context};
use std::{error::Error, fmt};
/// `Action` is type for command action. It returns `Result<ActionResult, ActionError>`.
pub type Action = fn(Command, Context) -> Result<ActionResult, ActionError>;
/// `ActionResult` stores result of action.
/// `Command`のアクション結果を格納し、runの結果として返却するためのenum。
#[derive(Debug)]
pub enum ActionResult {
///Done shows that action is done.
Done,
/// `ParentActionRequest` shows that action requested to show help.
/// It is mainly used for help command.
ParentActionRequest(Command, Context),
/// Shows return `Context`, reached `Command` and `Action` as result for parse and run.
/// By using this, it is possible to get parse result and run action without keeping command instances of tree in memory.
Result(Command, Context),
/// Custom result(can have Box including dyn Debug).
Custom(Box<dyn Debug>),
}
impl ActionResult {
/// Returns true if self is done.
pub fn is_done(&self) -> bool {
matches!(self, ActionResult::Done)
}
}
/// `ActionError` stores error of action.
#[derive(Debug)]
pub struct ActionError {
/// `ActionError`'s value
pub value: String,
/// `ActionError`'s Kind
pub kind: ActionErrorKind,
/// command is a field for storing command that error occured
pub command: Box<Command>,
/// context is a field for storing context that error occured
pub context: Box<Context>,
/// If there is an error which is not `ActionError`, this can stores it.
pub related_error: Option<Box<dyn Error>>,
/// printed flag. If this is true, this shows error is not printed yet.
pub printed: bool,
}
/// `ErrorKind` of `ActionError`
#[derive(Debug)]
pub enum ActionErrorKind {
/// Shows a custom(Normal) error
Custom,
/// Shows that no action is registered to specidied command.
NoActionRegistered,
/// Shows None.
None,
}
impl ActionError {
/// Creates new `ActionError`.
pub fn new<T: Into<String>>(
value: T,
kind: ActionErrorKind,
command: Command,
context: Context,
related_error: Option<Box<dyn Error>>,
) -> Self {
Self {
value: value.into(),
kind,
command: Box::new(command),
context: Box::new(context),
related_error,
printed: false,
}
}
/// Creates new `ActionError` without (not action) error info.
pub fn without_related_error(
value: String,
kind: ActionErrorKind,
command: Command,
context: Context,
) -> Self {
Self {
value,
kind,
command: Box::new(command),
context: Box::new(context),
related_error: None,
printed: false,
}
}
}
impl fmt::Display for ActionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
ActionErrorKind::Custom => write!(f, "{}", self.value),
ActionErrorKind::NoActionRegistered => {
write!(f, "{} does not have its own action.", self.value)
}
ActionErrorKind::None => write!(f, "no action error"),
}
}
}
impl Error for ActionError {}
/// bundle is a helper for processing in action.
pub mod bundle {
use std::collections::VecDeque;
use crate::{Command, Context, FlagValue};
/// New-type for help processing in action. Inner is simple tuple - `(Context,Command)`
pub struct Bundle(pub Context, pub Command);
impl From<(Context, Command)> for Bundle {
fn from(val: (Context, Command)) -> Self {
Bundle(val.0, val.1)
}
}
impl From<Bundle> for (Context, Command) {
fn from(val: Bundle) -> Self {
val.unpack()
}
}
impl Bundle {
/// Creates new instance of bundle.
pub fn new(ctx: Context, cmd: Command) -> Self {
Bundle(ctx, cmd)
}
/// Returns inner tuple (Context,Command)
pub fn unpack(self) -> (Context, Command) {
let Bundle(ctx, cmd) = self;
(ctx, cmd)
}
/// Returns ref of `Context`
pub fn context(&self) -> &Context {
&self.0
}
/// Returns ref of `Command`
pub fn command(&self) -> &Command {
&self.1
}
/// Returns mut ref of `Context`
pub fn context_mut(&mut self) -> &mut Context {
&mut self.0
}
/// Returns mut ref of `Command`
pub fn command_mut(&mut self) -> &mut Command {
&mut self.1
}
/// Get `exe_path` as `&str`
pub fn exe_path(&self) -> &str {
self.context().exe_path()
}
/// Takes flag value from context. Different from get, returns `FlagValue` instance own (not reference) that has context.
/// contextからフラグ値を取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はデフォルト値のコピー)そのものを返す
pub fn take_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
self.0.take_flag_value_of(flag_name, &self.1)
}
/// Takes inputted flag value from context. Different from get, returns `FlagValue` instance own (not reference) that has context.
/// contextからフラグ値を(ユーザによりargに指定(入力)されている場合)取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はNoneを)そのものを返す
pub fn take_inputted_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
self.0.take_inputted_flag_value_of(flag_name)
}
/// Takes flag value from context. Different from get, returns `FlagValue` instance own (not reference) that has context.
/// contextからローカルフラグの値を取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はデフォルト値のコピー)そのものを返す
pub fn take_local_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
self.0.take_local_flag_value_of(flag_name, &self.1)
}
/// Takes inputted flag value from context. Different from get, returns `FlagValue` instance own (not reference) that has context.
/// contextからコモンフラグの値を取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はデフォルト値のコピー)そのものを返す
pub fn take_common_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
self.0.take_common_flag_value_of(flag_name, &self.1)
}
/// Takes inputted local flag value from context. Different from get, returns `FlagValue` instance own (not reference) that has context.
/// contextからローカルフラグ値を(ユーザによりargに指定(入力)されている場合)取得する。Getとは違い、参照ではなくcontextに格納されているものそのもの(格納されていない場合はNone)を返す
pub fn take_inputted_local_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
self.0.take_inputted_local_flag_value_of(flag_name)
}
/// Takes inputted common flag value from context. Different from get, returns `FlagValue` instance own (not reference) that has context.
/// contextからコモンフラグ値を(ユーザによりargに指定(入力)されている場合)取得する。Getとは違い、参照ではなくcontextに格納されているものそのもの(格納されていない場合はNone)を返す
pub fn take_inputted_common_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
self.0.take_inputted_common_flag_value_of(flag_name)
}
/// Gets `FlagValue`'s clone of the flag matches `flag_name` from context.
/// contextからフラグ値のcloneを取得する。フラグが設定されていない場合はNoneを返す
/// なお明示的に値が指定されない場合、`Bool`型のフラグであれば`FlagValue::Bool(true)`とし、`String`型のフラグであれば`FlagValue::String(String::new())`、それ以外の型のフラグでは`FlagValue::None`をSomeで包んで返す
pub fn get_flag_value_of(&self, flag_name: &str) -> Option<FlagValue> {
self.0.get_local_flag_value_of(flag_name, &self.1)
}
/// Gets `FlagValue`'s clone of the inputted flag matches `flag_name` from context.
/// contextからユーザから指定された場合のフラグ値のcloneを取得する。ユーザから入力されていない場合はNoneを返す。
pub fn get_inputted_flag_value_of(&self, flag_name: &str) -> Option<FlagValue> {
self.0.get_inputted_flag_value_of(flag_name)
}
/// Gets `FlagValue`'s clone of the common flag matches `flag_name` from context. If it is not defined, Returns None.
/// contextからユーザから指定された場合のローカルフラグ値のcloneを取得する。ユーザから入力されていないが定義されている場合はデフォルト値のクローンを返す。定義もされていない場合はNoneを返す。
/// なお明示的に値が指定されない場合、`Bool`型のフラグであれば`FlagValue::Bool(true)`とし、`String`型のフラグであれば`FlagValue::String(String::new())`、それ以外の型のフラグでは`FlagValue::None`をSomeで包んで返す
pub fn get_local_flag_value_of(&self, flag_name: &str) -> Option<FlagValue> {
self.0.get_local_flag_value_of(flag_name, &self.1)
}
/// Gets the flag value of the local flag matches `flag_name` if inputted. If it is not defined or not inputted, returns None.
/// `flag_name`と`name`が一致するローカルフラグがあり、それがユーザからコマンド引数で指定されていた場合、その値のクローンをSomeで包んで返す。`flag_name`と一致する`name`をどのローカルフラグも持たないか、ユーザがコマンド引数で指定していない場合はNoneを返す。
pub fn get_inputted_local_flag_value_of(&self, flag_name: &str) -> Option<FlagValue> {
self.0.get_inputted_common_flag_value_of(flag_name)
}
/// Gets the flag value of the common flag whose name matches `flag_name`. If it is not defined or not inputted, returns None.
/// `flag_name`と`name`が一致するコモンフラグがあり、それがユーザからコマンド引数で指定されていた場合、その値のクローンをSomeで包んで返す。`flag_name`と一致する`name`をどのコモンフラグも持たないか、ユーザがコマンド引数で指定していない場合はNoneを返す。
pub fn get_inputted_common_flag_value_of(&self, flag_name: &str) -> Option<FlagValue> {
self.0.get_inputted_common_flag_value_of(flag_name)
}
/// Returns true the value of the flag which has specified name is true.
pub fn is_flag_true(&self, name: &str) -> bool {
Some(FlagValue::Bool(true)) == self.0.get_flag_value_of(name, &self.1)
}
/// Returns depth of command - root:0
pub fn depth(&self) -> usize {
self.0.common_flags.len()
}
/// Returns reference of args
pub fn args(&self) -> &VecDeque<String> {
&self.0.args
}
/// Returns n'th arg
pub fn arg(&self, index: usize) -> Option<&String> {
self.0.args.get(index)
}
}
}