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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
use crate::{
	command::License,
	parser::{ErrorInfo, MiddleArg},
	vector::flag::{FlagSearch, LongFound},
	Flag, FlagValue, Vector,
};
use std::collections::VecDeque;

/// Storage information for command execution.
/// This storage raw args, non-flag args, flag values, and etc.
/// コマンドからrunを通ってactionにたどり着くまでの情報およびパース結果を格納する構造体。
/// フラグの値、たどってきたルートなどを保管。
#[derive(Debug, Clone)]
pub struct Context {
	/// raw args
	pub raw_args: Vec<String>,
	/// non-flag args
	pub args: VecDeque<String>,
	/// common_flags of its own and inherited
	pub common_flags: Vector<Vector<Flag>>,
	/// routes of from root to end
	pub routes: Vector<String>,
	/// local flags
	pub local_flags: Vector<Flag>,
	/// exe_path (String, not PathBuf)
	pub exe_path: String,
	/// storage of result of parsing common flags values
	pub common_flags_values: Vector<(String, FlagValue)>,
	/// storage of result of parsing local flags values
	pub local_flags_values: Vector<(String, FlagValue)>,
	/// On parsing, storage of parsing args.
	/// In edge(action), storage of error args
	pub parsing_args: Option<VecDeque<MiddleArg>>,
	/// error inforamation list of parsing
	pub error_info_list: Vector<ErrorInfo>,
	/// authors
	pub now_cmd_authors: String,
	/// version
	pub now_cmd_version: String,
	/// licence information
	pub now_cmd_license: License,
	/// copyright
	pub now_cmd_copyright: String,
}

impl Context {
	/// Creates a new instance of Context
	pub fn new(
		raw_args: Vec<String>,
		args: VecDeque<String>,
		common_flags: Vector<Flag>,
		local_flags: Vector<Flag>,
		routes: Vector<String>,
		exe_path: String,
		now_cmd_authors: String,
		now_cmd_version: String,
		now_cmd_copyright: String,
		now_cmd_license: License,
	) -> Context {
		Context {
			raw_args,
			args,
			common_flags: Vector(Some(vec![common_flags])),
			routes: routes.into(),
			local_flags,
			exe_path,
			common_flags_values: Vector::default(),
			local_flags_values: Vector::default(),
			parsing_args: None,
			error_info_list: Vector::default(),
			now_cmd_version,
			now_cmd_authors,
			now_cmd_copyright,
			now_cmd_license,
		}
	}

	/// Creates a new instance of Context with all options.
	pub fn with_all_field(
		raw_args: Vec<String>,
		args: VecDeque<String>,
		common_flags: Vector<Vector<Flag>>,
		local_flags: Vector<Flag>,
		exe_path: String,
		routes: Vector<String>,
		common_flags_values: Vector<(String, FlagValue)>,
		local_flags_values: Vector<(String, FlagValue)>,
		parsing_args: Option<VecDeque<MiddleArg>>,
		error_info_list: Vector<ErrorInfo>,
		now_cmd_authors: String,
		now_cmd_version: String,
		now_cmd_copyright: String,
		now_cmd_license: License,
	) -> Context {
		Context {
			raw_args,
			args,
			common_flags,
			routes,
			local_flags,
			exe_path,
			common_flags_values,
			local_flags_values,
			parsing_args,
			error_info_list,
			now_cmd_authors,
			now_cmd_version,
			now_cmd_copyright,
			now_cmd_license,
		}
	}

	/// Set args
	pub fn args(mut self, args: VecDeque<String>) -> Self {
		self.args = args;
		self
	}

	/// Get exe_path as &str
	pub fn current(&self) -> &str {
		&self.exe_path
	}

	/// Change exe_path's value
	pub fn change_current(mut self, path: String) {
		self.exe_path = path;
	}

	/// Find long form of local flag matches name_or_alias
	/// ロングフォームがname_or_aliasと一致するローカルフラグを検索してその結果を返す
	#[inline]
	pub fn find_local_long_flag(&self, name_or_alias: &str) -> LongFound<&Flag> {
		self.local_flags.find_long_flag(name_or_alias)
	}

	/// Find short form of local flag matches name_or_alias
	/// ショートフォームがname_or_aliasと一致するローカルフラグを検索してその結果を返す
	#[inline]
	pub fn find_local_short_flag(&self, short_alias: &char) -> Option<&Flag> {
		self.local_flags.find_short_flag(short_alias)
	}

	/// Find long form of common flag matches name_or_alias
	/// ロングフォームがname_or_aliasと一致するコモンフラグを検索してその結果を返す
	#[inline]
	pub fn find_common_long_flag(&self, name_or_alias: &str) -> LongFound<&Flag> {
		self.common_flags.find_long_flag(name_or_alias)
	}

	/// Find short form of common flag matches name_or_alias
	/// ショートフォームがname_or_aliasと一致するコモンフラグを検索してその結果を返す
	#[inline]
	pub fn find_common_short_flag(&self, short_alias: &char) -> Option<&Flag> {
		self.common_flags.find_short_flag(short_alias)
	}

	/// Add(Push back) middle_arg to this context's parsing_args
	pub fn push_back_to_parsing_args(&mut self, middle_arg: MiddleArg) {
		match self.parsing_args {
			None => {
				self.parsing_args = Some({
					let mut inner = VecDeque::new();
					inner.push_back(middle_arg);
					inner
				})
			}
			Some(ref mut vd) => (*vd).push_back(middle_arg),
		}
	}

	/// Shift(Push front) middle_arg to this context's parsing_args
	pub fn push_front_to_parsing_args(&mut self, middle_arg: MiddleArg) {
		match self.parsing_args {
			None => {
				self.parsing_args = Some({
					let mut inner = VecDeque::new();
					inner.push_front(middle_arg);
					inner
				})
			}
			Some(ref mut vd) => (*vd).push_back(middle_arg),
		}
	}

	/// Takes flag value from context. Different from get, returns flag_value instance own (not reference) that has context.
	/// contextからフラグ値を取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はデフォルト値のコピー)そのものを返す
	pub fn take_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
		match self.take_local_flag_value_of(flag_name) {
			None => self.take_common_flag_value_of(flag_name),
			val => val,
		}
	}

	/// Takes inputted flag value from context. Different from get, returns flag_value 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> {
		match self.take_inputted_local_flag_value_of(flag_name) {
			None => self.take_inputted_common_flag_value_of(flag_name),
			val => val,
		}
	}

	/// Takes flag value from context. Different from get, returns flag_value instance own (not reference) that has context.
	/// contextからローカルフラグの値を取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はデフォルト値のコピー)そのものを返す
	pub fn take_local_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
		match self.take_inputted_common_flag_value_of(flag_name) {
			None => match self.local_flags.find(flag_name) {
				None => None,
				Some(f) => Some(f.default_value.clone()),
			},
			val => val,
		}
	}

	/// Takes inputted flag value from context. Different from get, returns flag_value instance own (not reference) that has context.
	/// contextからコモンフラグの値を取得する。Getとは違い、参照ではなくcontextに格納されているもの(格納されていない場合はデフォルト値のコピー)そのものを返す
	pub fn take_common_flag_value_of(&mut self, flag_name: &str) -> Option<FlagValue> {
		match self.take_inputted_common_flag_value_of(flag_name) {
			None => match self.common_flags.find(flag_name) {
				None => None,
				Some(f) => Some(f.default_value.clone()),
			},
			val => val,
		}
	}

	/// Takes inputted local flag value from context. Different from get, returns flag_value 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> {
		match self.local_flags_values {
			Vector(None) => None,
			Vector(Some(ref mut local)) => {
				match local.iter().position(|(name, _)| name == flag_name) {
					Some(index) => {
						let (_, val) = local.remove(index);
						Some(val)
					}
					None => None,
				}
			}
		}
	}

	/// Takes inputted local flag value from context. Different from get, returns flag_value 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> {
		match self.common_flags_values {
			Vector(None) => None,
			Vector(Some(ref mut common)) => {
				match common.iter().position(|(name, _)| name == flag_name) {
					Some(index) => {
						let (_, val) = common.remove(index);
						Some(val)
					}
					None => None,
				}
			}
		}
	}

	/// 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> {
		match self.get_local_flag_value_of(flag_name) {
			None => self.get_common_flag_value_of(flag_name),
			flag_val => flag_val,
		}
	}

	/// 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> {
		match self.get_inputted_local_flag_value_of(flag_name) {
			None => self.get_inputted_common_flag_value_of(flag_name),
			flag_val => flag_val,
		}
	}

	/// 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_common_flag_value_of(&self, flag_name: &str) -> Option<FlagValue> {
		match self.get_inputted_common_flag_value_of(flag_name) {
			None => match self.common_flags.find(flag_name) {
				Some(f) => Some(f.default_value.clone()),
				None => None,
			},
			Some(FlagValue::None) => match self.common_flags.find(flag_name) {
				Some(f) => Some(f.derive_flag_value_if_no_value()),
				None => None,
			},
			val => val,
		}
	}

	/// 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> {
		match self.get_inputted_local_flag_value_of(flag_name) {
			None => match self.local_flags.find(flag_name) {
				Some(f) => Some(f.default_value.clone()),
				None => None,
			},
			Some(FlagValue::None) => match self.local_flags.find(flag_name) {
				Some(f) => Some(f.derive_flag_value_if_no_value()),
				None => None,
			},
			val => val,
		}
	}

	/// 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> {
		match &self.local_flags_values {
			Vector(None) => None,
			Vector(Some(local)) => match local.iter().find(|(name, _)| name == flag_name) {
				None => None,
				Some((_, flag_val)) => Some(flag_val.to_owned()),
			},
		}
	}

	/// 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> {
		match &self.common_flags_values {
			Vector(None) => None,
			Vector(Some(common)) => match common.iter().find(|(name, _)| name == flag_name) {
				None => None,
				Some((_, flag_val)) => Some(flag_val.to_owned()),
			},
		}
	}

	/// Returns flag has specified name is true flag.
	pub fn is_flag_true(&self, name: &str) -> bool {
		Some(FlagValue::Bool(true)) == self.get_flag_value_of(name)
	}
}

impl<'a> From<Vec<String>> for Context {
	fn from(raw_args: Vec<String>) -> Context {
		let args = VecDeque::from(raw_args.clone());
		let exe_path = match raw_args.get(0) {
			Some(str) => String::from(str),
			None => String::new(),
		};
		Context {
			raw_args,
			args,
			common_flags: Vector::default(),
			local_flags: Vector::default(),
			routes: Vector::default(),
			exe_path,
			common_flags_values: Vector::default(),
			local_flags_values: Vector::default(),
			parsing_args: None,
			error_info_list: Vector::default(),
			now_cmd_authors: String::default(),
			now_cmd_version: String::default(),
			now_cmd_license: License::default(),
			now_cmd_copyright: String::default(),
		}
	}
}