combu/
command.rs

1use crate::{
2	Action, Context, Flag, FlagValue, Parser, Vector,
3	action::{ActionError, ActionErrorKind::NoActionRegistered, ActionResult},
4	done,
5	parser::MiddleArg,
6};
7
8use core::mem::swap;
9use std::{collections::VecDeque, fmt::Debug};
10
11///The struct for command information store and command execution
12///This can be root and edge
13///コマンドの情報格納&実行用構造体です。root(根)にもedge(葉)にもなりえます。
14#[derive(Clone, Default, Debug)]
15pub struct Command {
16	///Command name
17	pub name: String,
18	///Command action
19	pub action: Option<Action>,
20	///Command authors
21	pub authors: String,
22	///Command copyright
23	pub copyright: String,
24	/// License of command
25	pub license: License,
26	/// Command description
27	pub description: Option<String>,
28	///Command usage
29	pub usage: String,
30	///local flags of command
31	pub l_flags: Vector<Flag>,
32	///common flags of command
33	pub c_flags: Vector<Flag>,
34	///alias for command
35	pub alias: Vector<String>,
36	///Command version
37	pub version: String,
38	///container of sub-command
39	pub sub: Vector<Command>,
40}
41
42/// Helper inner macro
43macro_rules! run_result{
44	()=>{
45		Result<ActionResult,ActionError>
46	}
47}
48/// Helper inner macro
49macro_rules! no_registered_error {
50	($command:expr,$context:expr) => {
51		Err(ActionError::without_related_error(
52			"no action is registered.".into(),
53			NoActionRegistered,
54			$command,
55			$context,
56		))
57	};
58}
59/// Helper inner macro
60macro_rules! check_sub {
61	($sub:expr, $self:expr) => {
62		check_sub_field!($sub, $self, authors);
63		check_sub_field!($sub, $self, version);
64		check_sub_field!($sub, $self, copyright);
65		check_sub_field!($sub, $self, license: License);
66	};
67}
68/// Helper inner macro
69macro_rules! check_sub_field {
70	($sub: expr, $self:expr, $field: ident) => {
71		if $sub.$field.is_empty() {
72			swap(&mut $sub.$field, &mut $self.$field)
73		}
74	};
75	($sub:expr, $self:expr,$field:ident :Option,) => {
76		if $sub.$field.is_none() {
77			swap(&mut $sub.$field, &mut $self.$field)
78		}
79	};
80	($sub:expr, $self:expr,$field:ident :License) => {
81		if $sub.$field.is_none() {
82			swap(&mut $sub.$field, &mut $self.$field)
83		}
84	};
85}
86
87/// LicenseFunc shows type alias for license function
88pub type LicenseFunc = fn(command: &Command, context: &Context) -> String;
89
90#[derive(Clone)]
91/// License shows license information
92#[derive(Default)]
93pub struct License(pub Option<(String, LicenseFunc)>);
94
95impl Debug for License {
96	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97		if let License(Some(val)) = self {
98			write!(f, "Some({},Func for Output)", val.0)
99		} else {
100			write!(f, "None")
101		}
102	}
103}
104
105impl License {
106	/// Creates new License information.
107	pub fn new(inner: Option<(String, LicenseFunc)>) -> Self {
108		License(inner)
109	}
110	/// Returns true if self has some license information.
111	pub fn is_some(&self) -> bool {
112		matches!(*self, License(Some(_)))
113	}
114	/// Returns true if self has no license information.
115	pub fn is_none(&self) -> bool {
116		matches!(*self, License(None))
117	}
118	/// Takes inner license information of self and returns.
119	pub fn take(&mut self) -> Self {
120		core::mem::take(self)
121	}
122	/// Returns (short) expression of license. If no license information(self is License(None)), returns None.
123	pub fn expr(&self) -> Option<String> {
124		match self {
125			License(Some((expr, _))) => Some(expr.into()),
126			License(None) => None,
127		}
128	}
129	/// Returns (short) expression of license. If no license information(self is License(None)), this function may panic.
130	pub fn expr_unwrap(&self) -> String {
131		match self {
132			License(Some((expr, _))) => expr.clone(),
133			License(None) => panic!("called `License::expr_unwrap()` on a `None` value"),
134		}
135	}
136	/// Returns (long) expression - detail of license.
137	pub fn output(&self, cmd: &Command, ctx: &Context) -> Option<String> {
138		match self {
139			License(Some((_, outputter))) => Some(outputter(cmd, ctx)),
140			License(None) => None,
141		}
142	}
143	/// Returns (long) expression - detail of license. If self is License(None), this function may panic.
144	pub fn output_unwrap(&self, cmd: &Command, ctx: &Context) -> String {
145		match self {
146			License(Some((_, outputter))) => outputter(cmd, ctx),
147			_ => panic!("called `License::expr_unwrap()` on a `None`value"),
148		}
149	}
150	/// Returns function which outputs (long) expression (or detail of license) with wrapping Option.
151	pub fn output_fn(&self) -> Option<LicenseFunc> {
152		match self {
153			License(Some((_, outputter))) => Some(*outputter),
154			License(None) => None,
155		}
156	}
157	/// Returns function of (long) expression (or detail of license). If self is License(None), this will panic.
158	pub fn output_fn_unwrap(&self) -> LicenseFunc {
159		match self {
160			License(Some((_, outputter))) => *outputter,
161			_ => panic!("called `License::output_fn_wrap` on a `None` value"),
162		}
163	}
164	/// Returns unwrap inner
165	pub fn unwrap(self) -> (String, LicenseFunc) {
166		let License(inner) = self;
167		inner.unwrap()
168	}
169}
170
171/// Helper inner macro for context generation
172macro_rules! gen_context_for_self_action {
173	($raw_args:expr) => {{
174		let mut args = VecDeque::from($raw_args.clone());
175		let exe_path = args.pop_front().unwrap();
176		gen_context_for_self_action!($raw_args, args, exe_path)
177	}};
178	($raw_args:expr,$args:expr,$exe_path:expr) => {
179		Context::new($raw_args, $args, Vector(None), Vector(None), $exe_path)
180	};
181	($raw_args:expr,$args:expr,$exe_path:expr, $inter_mediate_args:expr) => {
182		Context::with_all_field(
183			$raw_args,
184			$args,
185			Vector(None),
186			$exe_path,
187			Vector(None),
188			Vector::default(),
189			Vector::default(),
190			Some($inter_mediate_args),
191			Vector(None),
192		)
193	};
194}
195
196/// Helper inner macro that is about context generation for sub command run
197macro_rules! gen_context_for_sub_run {
198	($self:expr,$raw_args:expr,$args:expr,$exe_path:expr) => {
199		gen_context_for_sub_run!(inner, $self, $raw_args, $args, $exe_path, None)
200	};
201	($self:expr,$raw_args:expr,$args:expr,$exe_path:expr, $inter_mediate_args: expr) => {
202		gen_context_for_sub_run!(
203			inner,
204			$self,
205			$raw_args,
206			$args,
207			$exe_path,
208			Some($inter_mediate_args)
209		)
210	};
211	(inner,$self:expr, $raw_args:expr,$args:expr,$exe_path:expr,$inter_mediate_args:expr) => {
212		Context::with_all_field(
213			$raw_args,
214			$args,
215			Vector::with_first_elem($self.c_flags.take()),
216			$exe_path,
217			$self.derive_route_init_vector(),
218			Vector::default(),
219			Vector::default(),
220			$inter_mediate_args,
221			Vector::default(),
222		)
223	};
224}
225
226impl Command {
227	/// Creare new instance of Command
228	pub fn new() -> Command {
229		Command::default()
230	}
231
232	/// Create new instance of Command with name,authors,version
233	pub fn with_base<T: Into<String>>(
234		name: T,
235		authors: T,
236		version: T,
237		description: T,
238		action: Option<Action>,
239	) -> Command {
240		Command::with_all_field(
241			name.into(),
242			action,
243			authors.into(),
244			String::default(),
245			License(None),
246			Some(description.into()),
247			String::default(),
248			Vector::default(),
249			Vector::default(),
250			Vector::default(),
251			version.into(),
252			Vector::default(),
253		)
254	}
255
256	/// Create new instance of Command with name
257	pub fn with_name<T: Into<String>>(name: T) -> Command {
258		Command {
259			name: name.into(),
260			action: None,
261			authors: String::default(),
262			copyright: String::default(),
263			license: License::default(),
264			description: None,
265			usage: String::default(),
266			l_flags: Vector::default(),
267			c_flags: Vector::default(),
268			alias: Vector::default(),
269			version: String::default(),
270			sub: Vector::default(),
271		}
272	}
273
274	/// Create new instance of Command with more options
275	#[allow(clippy::too_many_arguments)]
276	pub fn with_all_field(
277		name: String,
278		action: Option<Action>,
279		authors: String,
280		copyright: String,
281		license: License,
282		description: Option<String>,
283		usage: String,
284		local_flags: Vector<Flag>,
285		common_flags: Vector<Flag>,
286		alias: Vector<String>,
287		version: String,
288		sub: Vector<Command>,
289	) -> Command {
290		Command {
291			name,
292			action,
293			authors,
294			copyright,
295			license,
296			description,
297			usage,
298			l_flags: local_flags,
299			c_flags: common_flags,
300			alias,
301			version,
302			sub,
303		}
304	}
305
306	/// Run command with collecting args automatically
307	pub fn run_with_auto_arg_collect(self) -> run_result!() {
308		match self.sub {
309			Vector(None) => self.single_run(std::env::args().collect::<Vec<String>>()),
310			_ => self.run(std::env::args().collect::<Vec<String>>()),
311		}
312	}
313
314	/// Run command as single(do not have sub) command
315	/// ルートからサブコマンドがないシンプルな状態の時
316	/// アクションが登録されていなければサブコマンドがあるかを調査する
317	pub fn single_run(mut self, raw_args: Vec<String>) -> run_result!() {
318		match self.action.take() {
319			Some(action) => {
320				if raw_args.len() < 2 {
321					action(self, gen_context_for_self_action!(raw_args))
322				} else {
323					let mut context = gen_context_for_self_action!(raw_args);
324					//println!("single_run_context: {:?}", context);
325					context =
326						Parser::default().parse_args_until_end(&self.l_flags, &self.c_flags, context);
327					action(self, context)
328				}
329			}
330			None => match self.sub {
331				Vector(None) => {
332					let c = gen_context_for_self_action!(raw_args);
333					no_registered_error!(self, c)
334				}
335				_ => self.run(raw_args),
336			},
337		}
338	}
339
340	/// Set Command's name
341	pub fn name<T: Into<String>>(mut self, name: T) -> Command {
342		self.name = name.into();
343		self
344	}
345
346	/// Set command's usage
347	pub fn usage<T: Into<String>>(mut self, usage: T) -> Self {
348		self.usage = usage.into();
349		self
350	}
351
352	/// Set command's action
353	pub fn action(mut self, action: Action) -> Self {
354		self.action = Some(action);
355		self
356	}
357
358	/// Set command's authors
359	pub fn authors<T: Into<String>>(mut self, authors: T) -> Self {
360		self.authors = authors.into();
361		self
362	}
363
364	/// Set command's copyright
365	pub fn copyright<T: Into<String>>(mut self, copyright: T) -> Self {
366		self.copyright = copyright.into();
367		self
368	}
369
370	/// Add a local flag to command
371	pub fn local_flag(mut self, flag: Flag) -> Self {
372		self.l_flags.push(flag);
373		self
374	}
375
376	/// Add a local flags to command
377	pub fn local_flags(mut self, flags: Vec<Flag>) -> Self {
378		self.l_flags.append_vec(flags);
379		self
380	}
381
382	/// Add a common flag to command
383	pub fn common_flag(mut self, flag: Flag) -> Self {
384		self.c_flags.push(flag);
385		self
386	}
387
388	/// Add a common flag to command
389	pub fn command_flags(mut self, flags: Vec<Flag>) -> Self {
390		self.c_flags.append_vec(flags);
391		self
392	}
393
394	/// Set command's description
395	pub fn description<T: Into<String>>(mut self, description: T) -> Self {
396		self.description = Some(description.into());
397		self
398	}
399
400	/// Set command's version
401	pub fn version<T: Into<String>>(mut self, version: T) -> Self {
402		self.version = version.into();
403		self
404	}
405
406	/// Add command's sub command
407	pub fn sub_command(mut self, sub_command: Command) -> Self {
408		self.sub.push(sub_command);
409		self
410	}
411
412	/// Add sub commands
413	pub fn sub_commands(mut self, sub_commands: Vec<Command>) -> Self {
414		self.sub.append_vec(sub_commands);
415		self
416	}
417
418	/// Sets license
419	pub fn license(mut self, license: License) -> Self {
420		self.license = license;
421		self
422	}
423
424	/// Add command's alias
425	pub fn alias<T: Into<String>>(mut self, a: T) -> Self {
426		self.alias.push(a.into());
427		self
428	}
429
430	/// Returns true if name_or_alias matches command's name or one of alias at least
431	/// name_or_aliasがコマンド名かエイリアスのうち少なくとも一つにマッチした場合trueを返す
432	pub fn is(&self, name_or_alias: &str) -> bool {
433		if name_or_alias == self.name {
434			true
435		} else {
436			match self.alias.inner() {
437				None => false,
438				Some(inner) => inner.iter().any(|a| a == name_or_alias),
439			}
440		}
441	}
442
443	/// Take sub command matches name_or_alias.
444	/// name_or_aliasに一致するサブコマンドがある場合、保持しているVectorからswap_removeで取り出して返す
445	pub fn take_sub(&mut self, name_or_alias: &str) -> Option<Command> {
446		match self.sub {
447			Vector(None) => None,
448			Vector(Some(ref mut inner)) => inner
449				.iter()
450				.position(|c| c.is(name_or_alias))
451				.map(|index| inner.swap_remove(index)),
452		}
453	}
454
455	/// Gets sub command mutable reference matches name_or_alias.
456	pub fn get_mut_sub(&mut self, name_or_alias: &str) -> Option<&mut Command> {
457		match self.sub {
458			Vector(None) => None,
459			Vector(Some(ref mut inner)) => match inner.iter().position(|c| c.is(name_or_alias)) {
460				None => None,
461				Some(index) => Some(inner.get_mut(index).unwrap()),
462			},
463		}
464	}
465
466	/// Returns true if this command has sub command(s).
467	pub fn has_sub(&self) -> bool {
468		self.sub.has_inner_vec()
469	}
470
471	/// Returns init Vector for Context's route
472	pub fn derive_route_init_vector(&self) -> Vector<String> {
473		if self.name.is_empty() {
474			Vector(None)
475		} else {
476			Vector(Some(vec![self.name.clone()]))
477		}
478	}
479}
480
481impl From<String> for Command {
482	fn from(name: String) -> Self {
483		Command {
484			name,
485			action: None,
486			authors: String::default(),
487			copyright: String::default(),
488			license: License::default(),
489			description: None,
490			usage: String::default(),
491			l_flags: Vector::default(),
492			c_flags: Vector::default(),
493			alias: Vector::default(),
494			version: String::default(),
495			sub: Vector::default(),
496		}
497	}
498}
499
500/// Trait for implementation Run function.
501pub trait Run<T> {
502	/// run function
503	fn run(self, args: T) -> run_result!();
504}
505
506impl Run<Vec<String>> for Command {
507	fn run(self, args: Vec<String>) -> run_result!() {
508		self.run_from_args(args)
509	}
510}
511
512impl Run<Context> for Command {
513	fn run(self, c: Context) -> run_result!() {
514		self.run_with_context(c)
515	}
516}
517
518impl Command {
519	/// Run commands with raw_args
520	pub fn run_from_args(mut self, raw_args: Vec<String>) -> run_result!() {
521		if self.sub.is_none() {
522			return self.single_run(raw_args);
523		}
524		let mut args = VecDeque::from(raw_args.clone());
525		let exe_path = args.pop_front().unwrap();
526		let head = args.pop_front();
527		if head.is_none() {
528			//引数がない場合
529			let c = gen_context_for_self_action!(raw_args, args, exe_path);
530			match self.action {
531				Some(action) => action(self, c),
532				None => no_registered_error!(self, c),
533			}
534		} else {
535			//get before first non-flag arg with parsing flags
536			let p = Parser::default();
537			match head {
538				Some(long_flag) if p.long_flag(&long_flag) => {
539					//long flag
540					let last = p.long_middle(long_flag);
541					self.assign_run(args, VecDeque::new(), p, raw_args, exe_path, last)
542				}
543				Some(short_flag) if p.flag(&short_flag) => {
544					//short flag
545					let last = p.short_middle(short_flag);
546					self.assign_run(args, VecDeque::new(), p, raw_args, exe_path, last)
547				}
548				Some(arg) => {
549					match self.take_sub(&arg) {
550						None => {
551							// ルートコマンド実行のとき
552							args.push_front(arg);
553							let mut c = gen_context_for_self_action!(raw_args, args, exe_path);
554							match self.action {
555								None => no_registered_error!(self, c),
556								Some(action) => {
557									c = p.parse_args_until_end(&self.l_flags, &self.c_flags, c);
558									action(self, c)
559								}
560							}
561						}
562						Some(sub) => {
563							// サブコマンドがヒットしたとき
564							let c = gen_context_for_sub_run!(self, raw_args, args, exe_path);
565							let r = sub.run(c);
566							// サブコマンドの結果をハンドリング
567							self.handle_sub_result(r)
568						}
569					}
570				}
571				_ => {
572					//Because None has already excluded, this area must be unreachable.
573					panic!("unexpected error");
574				}
575			}
576		}
577	}
578
579	/// Run command with context
580	pub fn run_with_context(mut self, mut context: Context) -> run_result!() {
581		if self.sub.is_none() {
582			// サブコマンドがない場合
583			let p = Parser::default();
584			let (mut context, non_flag_args) =
585				p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, context, true);
586			if let Some(mut non_flag_args) = non_flag_args {
587				non_flag_args.append(&mut context.args);
588				context.args = non_flag_args;
589			}
590			context = p.parse_args_until_end(&self.l_flags, &self.c_flags, context);
591			match self.action {
592				Some(action) => action(self, context),
593				None => no_registered_error!(self, context),
594			}
595		} else {
596			//サブコマンドと一致するかを捜査
597			let p = Parser::default();
598			match context.args.pop_front() {
599				Some(long_flag) if p.long_flag(&long_flag) => {
600					let last = p.long_middle(long_flag);
601					self.assign_context(context, p, VecDeque::new(), last)
602				}
603				Some(short_flag) if p.flag(&short_flag) => {
604					let last = p.short_middle(short_flag);
605					self.assign_context(context, p, VecDeque::new(), last)
606				}
607				Some(arg) => {
608					//println!("arg sub-sub: {}", &arg);
609					match self.take_sub(&arg) {
610						Some(mut sub) => {
611							context.common_flags.push(self.c_flags.take());
612							check_sub!(sub, self);
613							context.routes.push(self.name.clone());
614							let r = sub.run(context);
615							self.handle_sub_result(r)
616						}
617						None => match self.action {
618							None => no_registered_error!(self, context),
619							Some(action) => {
620								let c = match p.parse_inter_mediate_args(
621									&self.l_flags,
622									&self.c_flags,
623									context,
624									true,
625								) {
626									(mut context, None) => {
627										context =
628											p.parse_args_until_end(&self.l_flags, &self.c_flags, context);
629										context.args.push_front(arg);
630										context
631									}
632									(mut context, Some(mut non_flag_args)) => {
633										context =
634											p.parse_args_until_end(&self.l_flags, &self.c_flags, context);
635										context.args.push_front(arg);
636										non_flag_args.append(&mut context.args);
637										context.args = non_flag_args;
638										context
639									}
640								};
641								action(self, c)
642							}
643						},
644					}
645				}
646				None => {
647					//サブコマンド等の処理の必要がないのでこのまま叩き込む
648					match self.action {
649						Some(action) => {
650							let (mut context, non_flag_args) =
651								p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, context, true);
652							if let Some(mut non_flag_args) = non_flag_args {
653								non_flag_args.append(&mut context.args);
654								context.args = non_flag_args;
655							}
656							action(self, context)
657						}
658						None => {
659							let (mut context, non_flag_args) =
660								p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, context, true);
661							if let Some(mut non_flag_args) = non_flag_args {
662								non_flag_args.append(&mut context.args);
663								context.args = non_flag_args;
664							}
665							no_registered_error!(self, context)
666						}
667					}
668				}
669			}
670		}
671	}
672
673	/// Assign context to sub command or self own action.
674	/// コンテキストのargsを見てもサブコマンド行きかコマンドでそのまま処理すればいいか分からなかった時の処理用
675	pub fn assign_context(
676		mut self,
677		mut c: Context,
678		p: Parser,
679		mut inter_mediate_args: VecDeque<MiddleArg>,
680		last: MiddleArg,
681	) -> run_result!() {
682		let (next_non_flag, args, _inter_mediate_args, last) =
683			p.middle_parse(c.args, inter_mediate_args, last);
684		inter_mediate_args = _inter_mediate_args;
685		//println!("next_non_flag: {:?}", next_non_flag);
686		match next_non_flag {
687			Some(arg) => match self.take_sub(&arg) {
688				Some(mut sub) => {
689					// サブコマンド実行だった時
690					c.common_flags.push(self.c_flags.take());
691					c.args = args;
692					inter_mediate_args.push_back(last);
693					if let Some(mut parsing_args) = c.parsing_args {
694						parsing_args.append(&mut inter_mediate_args);
695						c.parsing_args = Some(parsing_args);
696					} else {
697						c.parsing_args = Some(inter_mediate_args);
698					}
699					check_sub!(sub, self);
700					c.routes.push(self.name.clone());
701					let r = sub.run(c);
702					self.handle_sub_result(r)
703				}
704				None => match &last {
705					MiddleArg::LongFlag(_, FlagValue::None)
706					| MiddleArg::ShortFlag(_, FlagValue::None) => {
707						// 値が設定されていないフラグが前の引数の時はそのフラグの値として扱い、次の引数をハンドリング
708						inter_mediate_args.push_back(last);
709						inter_mediate_args.push_back(MiddleArg::Normal(arg));
710						c.args = args;
711						match c.args.pop_front() {
712							Some(long_flag) if p.long_flag(&long_flag) => {
713								let last = p.long_middle(long_flag);
714								self.assign_context(c, p, inter_mediate_args, last)
715							}
716							Some(short_flag) if p.flag(&short_flag) => {
717								let last = p.short_middle(short_flag);
718								self.assign_context(c, p, inter_mediate_args, last)
719							}
720							Some(arg) => match self.take_sub(&arg) {
721								Some(mut sub) => {
722									c.common_flags.push(self.c_flags.take());
723									if let Some(mut parsing_args) = c.parsing_args {
724										parsing_args.append(&mut inter_mediate_args);
725										c.parsing_args = Some(parsing_args);
726									} else {
727										c.parsing_args = Some(inter_mediate_args);
728									}
729									c.routes.push(self.name.clone());
730									check_sub!(sub, self);
731									let r = sub.run(c);
732									self.handle_sub_result(r)
733								}
734								None => {
735									if let Some(mut parsing_args) = c.parsing_args {
736										parsing_args.append(&mut inter_mediate_args);
737										c.parsing_args = Some(parsing_args);
738									} else {
739										c.parsing_args = Some(inter_mediate_args);
740									}
741									let (mut c, non_flag_args) =
742										p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, c, false);
743									c = p.parse_args_until_end(&self.l_flags, &self.c_flags, c);
744									c.args.push_front(arg);
745									if let Some(mut non_flag_args) = non_flag_args {
746										non_flag_args.append(&mut c.args);
747										c.args = non_flag_args;
748									}
749									match self.action {
750										Some(action) => action(self, c),
751										None => no_registered_error!(self, c),
752									}
753								}
754							},
755							None => {
756								if let Some(mut parsing_args) = c.parsing_args {
757									parsing_args.append(&mut inter_mediate_args);
758									c.parsing_args = Some(parsing_args);
759								} else {
760									c.parsing_args = Some(inter_mediate_args);
761								}
762								let (mut c, args) =
763									p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, c, false);
764
765								if let Some(mut args) = args {
766									args.append(&mut c.args);
767									c.args = args;
768								}
769								match self.action {
770									Some(action) => action(self, c),
771									None => no_registered_error!(self, c),
772								}
773							}
774						}
775					}
776					_ => {
777						inter_mediate_args.push_back(last);
778						c.args = args;
779						if let Some(mut parsing_args) = c.parsing_args {
780							parsing_args.append(&mut inter_mediate_args);
781							c.parsing_args = Some(parsing_args);
782						}
783						let (mut c, non_flag_args) =
784							p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, c, false);
785						c = p.parse_args_until_end(&self.l_flags, &self.c_flags, c);
786						c.args.push_front(arg);
787						if let Some(mut non_flag_args) = non_flag_args {
788							non_flag_args.append(&mut c.args);
789							c.args = non_flag_args;
790						}
791						match self.action {
792							Some(action) => action(self, c),
793							None => no_registered_error!(self, c),
794						}
795					}
796				},
797			},
798			None => {
799				inter_mediate_args.push_back(last);
800				c.args = args;
801				if let Some(mut parsing_args) = c.parsing_args {
802					parsing_args.append(&mut inter_mediate_args);
803					c.parsing_args = Some(parsing_args);
804				} else {
805					c.parsing_args = Some(inter_mediate_args);
806				}
807				let (mut c, non_flag_args) =
808					p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, c, false);
809				//println!("after_parse_ima:{:?}", c);
810				if let Some(non_flag_args) = non_flag_args {
811					//non_flag_args.append(&mut c.args);
812					c.args = non_flag_args;
813				}
814				match self.action {
815					Some(action) => action(self, c),
816					None => no_registered_error!(self, c),
817				}
818			}
819		}
820	}
821
822	/// Assign subcomannd's run or command's own action with no context
823	/// コンテキストが生成されていないときに、run_from_args内で第一引数からサブコマンドかそうでないか分からなかった時に再帰処理を行って割り当てを行う関数
824	pub fn assign_run(
825		mut self,
826		mut args: VecDeque<String>,
827		mut inter_mediate_args: VecDeque<MiddleArg>,
828		p: Parser,
829		raw_args: Vec<String>,
830		exe_path: String,
831		last: MiddleArg,
832	) -> run_result!() {
833		let (next_non_flag, _args, _inter_mediate_args, last) =
834			p.middle_parse(args, inter_mediate_args, last);
835		inter_mediate_args = _inter_mediate_args;
836		args = _args;
837		match next_non_flag {
838			Some(arg) => {
839				match self.take_sub(&arg) {
840					Some(sub) => {
841						inter_mediate_args.push_back(last);
842						let c =
843							gen_context_for_sub_run!(self, raw_args, args, exe_path, inter_mediate_args);
844
845						sub.run(c)
846					}
847					None => {
848						//一致するサブコマンドがなかった場合
849						match &last {
850							MiddleArg::LongFlag(_, FlagValue::None)
851							| MiddleArg::ShortFlag(_, FlagValue::None) => {
852								//フラグの値になりうる場合
853								inter_mediate_args.push_back(last);
854								inter_mediate_args.push_back(MiddleArg::Normal(arg));
855								match args.pop_front() {
856									Some(long_flag) if p.long_flag(&long_flag) => {
857										let last = p.long_middle(long_flag);
858										self.assign_run(args, inter_mediate_args, p, raw_args, exe_path, last)
859									}
860									Some(short_flag) if p.flag(&short_flag) => {
861										let last = p.short_middle(short_flag);
862										self.assign_run(args, inter_mediate_args, p, raw_args, exe_path, last)
863									}
864									Some(arg) => match self.take_sub(&arg) {
865										Some(sub) => {
866											let c = gen_context_for_sub_run!(
867												self,
868												raw_args,
869												args,
870												exe_path,
871												inter_mediate_args
872											);
873
874											sub.run(c)
875										}
876										None => {
877											//サブコマンドはないのでそのままselfでaction
878											let c = gen_context_for_self_action!(
879												raw_args,
880												args,
881												exe_path,
882												inter_mediate_args
883											);
884											let (mut c, non_flag_args) = p.parse_inter_mediate_args(
885												&self.l_flags,
886												&self.c_flags,
887												c,
888												false,
889											);
890											c = p.parse_args_until_end(&self.l_flags, &self.c_flags, c);
891											c.args.push_front(arg);
892											if let Some(mut non_flag_args) = non_flag_args {
893												non_flag_args.append(&mut c.args);
894												c.args = non_flag_args;
895											};
896											match self.action {
897												Some(action) => action(self, c),
898												None => no_registered_error!(self, c),
899											}
900										}
901									},
902									None => {
903										//残りのargはなし、そのままaction
904										let c = gen_context_for_self_action!(
905											raw_args,
906											args,
907											exe_path,
908											inter_mediate_args
909										);
910										let (mut c, non_flag_args) =
911											p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, c, false);
912										if let Some(mut non_flag_args) = non_flag_args {
913											non_flag_args.append(&mut c.args);
914											c.args = non_flag_args;
915										}
916										match self.action {
917											Some(action) => action(self, c),
918											None => no_registered_error!(self, c),
919										}
920									}
921								}
922							}
923							_ => {
924								//argがフラグの可能性がない
925								inter_mediate_args.push_back(last);
926								//inter_mediate_args.push_back(MiddleArg::Normal(arg));
927
928								let c = gen_context_for_self_action!(
929									raw_args,
930									args,
931									exe_path,
932									inter_mediate_args
933								);
934								let (mut c, non_flag_args) =
935									p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, c, false);
936								c = p.parse_args_until_end(&self.l_flags, &self.c_flags, c);
937								c.args.push_front(arg);
938								if let Some(mut non_flag_args) = non_flag_args {
939									non_flag_args.append(&mut c.args);
940									c.args = non_flag_args;
941								}
942								match self.action {
943									Some(action) => action(self, c),
944									_ => no_registered_error!(self, c),
945								}
946							}
947						}
948					}
949				}
950			}
951			None => {
952				//argがなかった場合
953				//self.actionに放り込む
954				inter_mediate_args.push_back(last);
955				let context =
956					gen_context_for_self_action!(raw_args, args, exe_path, inter_mediate_args);
957				let (mut c, non_flag_args) =
958					p.parse_inter_mediate_args(&self.l_flags, &self.c_flags, context, false);
959				if let Some(mut non_flag_args) = non_flag_args {
960					non_flag_args.append(&mut c.args);
961					c.args = non_flag_args;
962				}
963
964				match self.action {
965					Some(action) => action(self, c),
966					None => no_registered_error!(self, c),
967				}
968			}
969		}
970	}
971
972	/// Handle sub action's result (Result<ActionResult, ActionError>).
973	///Implemented: at ParentActionRequest and Err
974	/// アクションの結果であるResult<ActionResult, ActionError>をハンドルする関数。現在はParentActionRequestのハンドリング、もしくはエラー表示のみ
975	pub fn handle_sub_result(mut self, mut req: Result<ActionResult, ActionError>) -> run_result!() {
976		match req {
977			done!() => {
978				// Doneなら何もしないでreqを上にあげる
979				req
980			}
981			Ok(ActionResult::ParentActionRequest(mut cmd, mut ctx)) => {
982				// サブコマンドからリクエストが飛んでいた時はselfを与えてリクエストされたアクションを実行
983				ctx.routes.pop(); //ルートをさかのぼる
984				self.c_flags = ctx.common_flags.remove_last(); //コモンフラグを戻す
985				check_sub!(self, cmd); // authors, version, copyright, licenseを戻す
986				let action = cmd.action.unwrap(); // リクエストアクションはsub.actionに格納されているものとする
987				self.sub.push(cmd); //サブコマンドを親コマンドの末尾に戻す
988				action(self, ctx)
989			}
990			Err(ref mut err) => {
991				if !err.printed {
992					println!("error: {err}");
993				}
994				err.printed = true;
995				req
996			}
997			_ => req,
998		}
999	}
1000}
1001#[cfg(test)]
1002mod tests {
1003	use crate::license;
1004
1005	use super::super::parser::ParseError;
1006	use super::super::{Flag, FlagType};
1007	use super::*;
1008
1009	fn cnv_arg(mut v: Vec<&str>) -> Vec<String> {
1010		v.iter_mut().map(|s| s.to_owned()).collect()
1011	}
1012
1013	#[test]
1014	fn test_single_run() {
1015		let mut arg = vec![
1016			"exe_path".to_string(),
1017			"test".to_string(),
1018			"test".to_string(),
1019		];
1020		let root = base_root().action(|_, c| {
1021			println!("test_action: {c:?}");
1022			let raw_args = vec![
1023				"exe_path".to_string(),
1024				"test".to_string(),
1025				"test".to_string(),
1026			];
1027			let expect_args = {
1028				let mut vd = VecDeque::from(raw_args.clone());
1029				vd.pop_front();
1030				vd
1031			};
1032			assert_eq!(c.raw_args, raw_args);
1033			assert_eq!(c.args, expect_args);
1034			assert_eq!(c.exe_path, String::from("exe_path"));
1035			assert_eq!(c.routes, Vector(None));
1036			done!()
1037		});
1038
1039		let _ = root.single_run(arg.clone());
1040
1041		arg.push("--common=C_after".into());
1042		arg.push("--local=L_after".into());
1043		arg.insert(1, "--common=C_before".into());
1044		arg.insert(1, "--local=L_before".into());
1045		let root = Command::with_name("root")
1046			.action(|cmd, c| {
1047				println!("test_action: {c:?}");
1048				let raw_args: Vec<String> = vec![
1049					"exe_path".to_string(),
1050					"--local=L_before".to_string(),
1051					"--common=C_before".to_string(),
1052					"test".to_string(),
1053					"test".to_string(),
1054					"--common=C_after".to_string(),
1055					"--local=L_after".to_string(),
1056				];
1057				let expect_args = VecDeque::from(vec!["test".to_string(), "test".to_string()]);
1058				assert_eq!(c.raw_args, raw_args);
1059				assert_eq!(c.args, expect_args);
1060				assert_eq!(c.exe_path, String::from("exe_path"));
1061				assert_eq!(c.routes, Vector(None));
1062				let l_flag_values = Vector::from(vec![
1063					(
1064						"local".to_string(),
1065						FlagValue::String("L_before".to_owned()),
1066					),
1067					("local".to_string(), FlagValue::String("L_after".into())),
1068				]);
1069				assert_eq!(c.local_flags_values, l_flag_values);
1070				let c_flag_values = Vector::from(vec![
1071					(
1072						"common".to_string(),
1073						FlagValue::String("C_before".to_owned()),
1074					),
1075					("common".to_string(), FlagValue::String("C_after".into())),
1076				]);
1077				assert_eq!(c.common_flags_values, c_flag_values);
1078				assert_eq!(cmd.version, "root_version".to_owned());
1079				assert_eq!(cmd.copyright, "root_copyright".to_owned());
1080				assert_eq!(cmd.license.unwrap().0, String::from("root_license"));
1081				done!()
1082			})
1083			.common_flag(Flag::new("common", FlagType::String, "sample common flag"))
1084			.local_flag(Flag::new("local", FlagType::String, "sample local flag"))
1085			.version("root_version")
1086			.copyright("root_copyright")
1087			.license(license!(
1088				"root_license".into(),
1089				content=>"root_license_content".into()
1090			));
1091
1092		let _ = root.single_run(arg);
1093	}
1094
1095	#[test]
1096	fn run_root() {
1097		let arg = vec![
1098			"exe_path".to_string(),
1099			"test".to_string(),
1100			"test".to_string(),
1101			"--local".to_string(),
1102			"test".to_string(),
1103		];
1104		let root = Command::new()
1105			.action(|mut cmd, c| {
1106				println!("test_action: {c:?}");
1107				let raw_args = vec![
1108					"exe_path".to_string(),
1109					"test".to_string(),
1110					"test".to_string(),
1111					"--local".to_string(),
1112					"test".to_string(),
1113				];
1114				let expect_args = VecDeque::from(vec!["test".to_string(), "test".to_string()]);
1115				assert_eq!(c.raw_args, raw_args);
1116				assert_eq!(c.args, expect_args);
1117				assert_eq!(c.exe_path, String::from("exe_path"));
1118				assert_eq!(
1119					c.get_local_flag_value_of("local", &cmd),
1120					Some(FlagValue::String("test".into()))
1121				);
1122				assert_eq!(
1123					c.get_flag_value_of("local", &cmd),
1124					Some(FlagValue::String("test".into()))
1125				);
1126				assert_eq!(
1127					c.get_flag_value_of("common", &cmd),
1128					Some(FlagValue::String(String::default()))
1129				);
1130				assert_eq!(c.routes, Vector(None));
1131				assert_eq!(cmd.version, "root_version".to_owned());
1132				assert_eq!(cmd.copyright, "root_copyright".to_owned());
1133				let License(inner) = cmd.license.take();
1134				let inner = inner.unwrap();
1135				assert_eq!(inner.0, String::from("root_license"));
1136				assert_eq!(inner.1(&cmd, &c), String::from("root_license_content"));
1137				done!()
1138			})
1139			.common_flag(Flag::new("common", FlagType::String, "sample common flag"))
1140			.local_flag(Flag::new("local", FlagType::String, "sample local flag"))
1141			.sub_command(Command::with_name("sub").action(|_, _| {
1142				println!("sub");
1143				done!()
1144			}))
1145			.version("root_version")
1146			.copyright("root_copyright")
1147			.license(license!(
1148				expr=>"root_license".into(),
1149				content=>"root_license_content".into()
1150			));
1151		let _ = root.run(arg);
1152	}
1153
1154	fn base_root() -> Command {
1155		Command::new()
1156			.local_flag(Flag::new_string("local").short_alias('l'))
1157			.local_flag(Flag::new_bool("lafter").short_alias('a'))
1158			.common_flag(Flag::new_bool("common").short_alias('c'))
1159			.common_flag(Flag::new_string("cstr").short_alias('s'))
1160			.common_flag(Flag::new_bool("cafter"))
1161			.version("root_version")
1162			.copyright("root_copyright")
1163			.license(license!(
1164				"root_license".into(),
1165				content=>"root_license_content".into(),
1166			))
1167			.authors("root_authors")
1168	}
1169
1170	macro_rules! assert_attrs {
1171		($prefix:expr, $context:expr,$command:expr) => {
1172			let prefix = String::from($prefix);
1173			assert_eq!($command.authors, prefix.clone() + "authors");
1174			assert_eq!($command.version, prefix.clone() + "version");
1175			assert_eq!($command.copyright, prefix.clone() + "copyright");
1176			assert_eq!(
1177				(
1178					$command.license.expr_unwrap(),
1179					$command.license.output_unwrap(&$command, &$context)
1180				),
1181				(prefix.clone() + "license", prefix + "license_content")
1182			);
1183		};
1184	}
1185	#[test]
1186	fn run_root_with_flag_before_normal_arg() {
1187		let mut arg = cnv_arg(vec!["exe_path", "--local=test"]);
1188		let root = base_root().sub_command(Command::with_name("sub").action(|c, _| {
1189			panic!("not root, in sub: {c:?}");
1190		}));
1191		arg.push("test".into());
1192		let _ = root
1193			.clone()
1194			.action(|cmd, c| {
1195				println!("c: {c:?}");
1196				assert_eq!(
1197					cnv_arg(vec!["exe_path", "--local=test", "test"]),
1198					c.raw_args
1199				);
1200				assert_eq!(
1201					c.get_flag_value_of("local", &cmd).unwrap(),
1202					FlagValue::String("test".into())
1203				);
1204				assert_eq!(c.routes, Vector(None));
1205				assert_attrs!("root_", c, cmd);
1206				done!()
1207			})
1208			.run(arg.clone());
1209		arg[2] = "--common".into();
1210		let _ = root
1211			.clone()
1212			.action(|cur_cmd, c| {
1213				println!("c: {c:?}");
1214				assert_eq!(
1215					cnv_arg(vec!["exe_path", "--local=test", "--common"]),
1216					c.raw_args
1217				);
1218				assert_eq!(
1219					c.get_flag_value_of("local", &cur_cmd).unwrap(),
1220					FlagValue::String("test".into())
1221				);
1222				assert_eq!(
1223					c.get_flag_value_of("common", &cur_cmd).unwrap(),
1224					FlagValue::Bool(true)
1225				);
1226				assert_eq!(c.routes, Vector(None));
1227				assert_attrs!("root_", c, cur_cmd);
1228				done!()
1229			})
1230			.run(arg.clone());
1231
1232		arg.push("test".into());
1233		let _ = root
1234			.clone()
1235			.action(|cc, c| {
1236				println!("{c:?}");
1237				assert_eq!(
1238					cnv_arg(vec!["exe_path", "--local=test", "--common", "test"]),
1239					c.raw_args
1240				);
1241				assert_eq!(VecDeque::from(vec!["test".to_string()]), c.args);
1242				assert_eq!(
1243					c.get_flag_value_of("local", &cc).unwrap(),
1244					FlagValue::String("test".into())
1245				);
1246				assert_eq!(
1247					c.get_flag_value_of("common", &cc).unwrap(),
1248					FlagValue::Bool(true)
1249				);
1250				assert_eq!(c.routes, Vector(None));
1251				assert_attrs!("root_", c, cc);
1252				done!()
1253			})
1254			.run(arg.clone());
1255
1256		println!("arg after flags");
1257		arg.push("arg".into());
1258		arg.push("ex_arg".into());
1259		arg.push("--lafter".into());
1260		arg.push("--cafter".into());
1261		let _ = root
1262			.clone()
1263			.action(|cur, c| {
1264				println!("{c:?}");
1265				assert_eq!(
1266					cnv_arg(vec![
1267						"exe_path",
1268						"--local=test",
1269						"--common",
1270						"test",
1271						"arg",
1272						"ex_arg",
1273						"--lafter",
1274						"--cafter"
1275					]),
1276					c.raw_args
1277				);
1278				assert_eq!(
1279					VecDeque::from(cnv_arg(vec!["test", "arg", "ex_arg"])),
1280					c.args
1281				);
1282				assert_eq!(
1283					c.get_flag_value_of("local", &cur).unwrap(),
1284					FlagValue::String("test".into())
1285				);
1286				assert_eq!(
1287					c.get_flag_value_of("common", &cur).unwrap(),
1288					FlagValue::Bool(true)
1289				);
1290				assert_eq!(
1291					c.get_flag_value_of("cafter", &cur).unwrap(),
1292					FlagValue::Bool(true)
1293				);
1294				assert_eq!(
1295					c.get_flag_value_of("lafter", &cur).unwrap(),
1296					FlagValue::Bool(true)
1297				);
1298				assert_eq!(c.routes, Vector(None));
1299				assert_attrs!("root_", c, cur);
1300				done!()
1301			})
1302			.run(arg.clone());
1303
1304		arg.remove(5);
1305		arg.remove(4);
1306		arg.insert(5, "arg".into());
1307
1308		let _ = root
1309			.clone()
1310			.action(|cur_cmd, c| {
1311				println!("{c:?}");
1312				assert_eq!(
1313					c.raw_args,
1314					cnv_arg(vec![
1315						"exe_path",
1316						"--local=test",
1317						"--common",
1318						"test",
1319						"--lafter",
1320						"arg",
1321						"--cafter"
1322					])
1323				);
1324				assert_eq!(VecDeque::from(cnv_arg(vec!["test", "arg"])), c.args);
1325				assert_eq!(
1326					c.get_flag_value_of("local", &cur_cmd).unwrap(),
1327					FlagValue::String("test".into())
1328				);
1329				assert_eq!(
1330					c.get_flag_value_of("common", &cur_cmd).unwrap(),
1331					FlagValue::Bool(true)
1332				);
1333				assert_eq!(
1334					c.get_flag_value_of("cafter", &cur_cmd).unwrap(),
1335					FlagValue::Bool(true)
1336				);
1337				assert_eq!(
1338					c.get_flag_value_of("lafter", &cur_cmd).unwrap(),
1339					FlagValue::Bool(true)
1340				);
1341				assert_eq!(c.routes, Vector(None));
1342				assert_attrs!("root_", c, cur_cmd);
1343				done!()
1344			})
1345			.run(arg.clone());
1346
1347		arg.push("ex_arg".into());
1348		let _ = root
1349			.clone()
1350			.action(|cmd, c| {
1351				println!("{c:?}");
1352				assert_eq!(
1353					c.raw_args,
1354					cnv_arg(vec![
1355						"exe_path",
1356						"--local=test",
1357						"--common",
1358						"test",
1359						"--lafter",
1360						"arg",
1361						"--cafter",
1362						"ex_arg"
1363					])
1364				);
1365				assert_eq!(
1366					VecDeque::from(cnv_arg(vec!["test", "arg", "ex_arg"])),
1367					c.args
1368				);
1369				assert_eq!(
1370					c.get_flag_value_of("local", &cmd).unwrap(),
1371					FlagValue::String("test".into())
1372				);
1373				assert_eq!(
1374					c.get_flag_value_of("common", &cmd).unwrap(),
1375					FlagValue::Bool(true)
1376				);
1377				assert_eq!(
1378					c.get_flag_value_of("cafter", &cmd).unwrap(),
1379					FlagValue::Bool(true)
1380				);
1381				assert_eq!(
1382					c.get_flag_value_of("lafter", &cmd).unwrap(),
1383					FlagValue::Bool(true)
1384				);
1385				assert_eq!(c.routes, Vector(None));
1386				assert_attrs!("root_", c, cmd);
1387				done!()
1388			})
1389			.run(arg.clone());
1390		arg[4] = "-a".into();
1391		let _ = root
1392			.clone()
1393			.action(|cmd, c| {
1394				println!("{c:?}");
1395				assert_eq!(
1396					c.raw_args,
1397					cnv_arg(vec![
1398						"exe_path",
1399						"--local=test",
1400						"--common",
1401						"test",
1402						"-a",
1403						"arg",
1404						"--cafter",
1405						"ex_arg"
1406					])
1407				);
1408				assert_eq!(
1409					VecDeque::from(cnv_arg(vec!["test", "arg", "ex_arg"])),
1410					c.args
1411				);
1412				assert_eq!(
1413					c.get_flag_value_of("local", &cmd).unwrap(),
1414					FlagValue::String("test".into())
1415				);
1416				assert_eq!(
1417					c.get_flag_value_of("common", &cmd).unwrap(),
1418					FlagValue::Bool(true)
1419				);
1420				assert_eq!(
1421					c.get_flag_value_of("cafter", &cmd).unwrap(),
1422					FlagValue::Bool(true)
1423				);
1424				assert_eq!(
1425					c.get_flag_value_of("lafter", &cmd).unwrap(),
1426					FlagValue::Bool(true)
1427				);
1428				assert_eq!(c.routes, Vector(None));
1429				assert_attrs!("root_", c, cmd);
1430				done!()
1431			})
1432			.run(arg.clone());
1433	}
1434
1435	#[test]
1436	fn run_node() {
1437		let mut arg = cnv_arg(vec![
1438			"exe_path", "sub", "test", "--common", "test", "--cstr", "strt", "-b", "--local",
1439		]);
1440		let root = base_root().action(|c, _| {
1441			println!("test_action: {c:?}");
1442			panic!("not sub");
1443		});
1444		let sub = Command::with_name("sub")
1445			.local_flag(Flag::new_bool("bool").short_alias('b'))
1446			.local_flag(Flag::new_string("string").short_alias('s'))
1447			.common_flag(Flag::new_bool("cl"))
1448			.sub_command(Command::with_name("leaf").action(|c, _| {
1449				println!("Context: {c:?}");
1450				panic!("in leaf")
1451			}))
1452			.authors("sub_authors")
1453			.version("sub_version")
1454			.copyright("sub_copyright")
1455			.license(license!(
1456				"sub_license".into(),
1457				content=>"sub_license_content".into(),
1458			));
1459		let _ = root
1460			.clone()
1461			.sub_command(sub.clone().action(|cmd, c| {
1462				println!("{c:?}");
1463				let raw_args = cnv_arg(vec![
1464					"exe_path", "sub", "test", "--common", "test", "--cstr", "strt", "-b", "--local",
1465				]);
1466				let expect_args = VecDeque::from(vec!["test".to_string(), "test".to_string()]);
1467				assert_eq!(c.exe_path, String::from("exe_path"));
1468				assert_eq!(c.raw_args, raw_args);
1469				assert_eq!(c.args, expect_args);
1470				assert_eq!(
1471					c.get_flag_value_of("common", &cmd),
1472					Some(FlagValue::Bool(true))
1473				);
1474				assert_eq!(
1475					c.get_flag_value_of("bool", &cmd).unwrap(),
1476					FlagValue::Bool(true)
1477				);
1478				assert_eq!(c.get_flag_value_of("commons", &cmd), None);
1479				assert_eq!(c.get_flag_value_of("local", &cmd), None);
1480				assert_eq!(c.routes, Vector(None));
1481				assert_attrs!("sub_", c, cmd);
1482				done!()
1483			}))
1484			.run(arg.clone());
1485
1486		println!("サブコマンド前フラグのテスト");
1487		arg = cnv_arg(vec!["exe_path", "--cstr=test", "-b", "sub"]);
1488		let _ = root
1489			.clone()
1490			.name("root")
1491			.sub_command(sub.clone().action(|cmd, c| {
1492				println!("c: {c:?}");
1493				assert_eq!(
1494					c.raw_args,
1495					cnv_arg(vec!["exe_path", "--cstr=test", "-b", "sub"])
1496				);
1497				assert_eq!(
1498					c.get_flag_value_of("cstr", &cmd).unwrap(),
1499					FlagValue::String("test".into())
1500				);
1501				assert_eq!(
1502					c.get_flag_value_of("bool", &cmd).unwrap(),
1503					FlagValue::Bool(true)
1504				);
1505				assert_eq!(c.routes, Vector(Some(vec!["root".to_string()])));
1506				assert_attrs!("sub_", c, cmd);
1507				done!()
1508			}))
1509			.run(arg.clone());
1510
1511		println!("サブコマンド探しをする場合");
1512		arg[1] = "--cstr".into();
1513		arg.insert(2, "test".into());
1514
1515		let _ = root
1516			.clone()
1517			.sub_command(sub.clone().action(|cmd, c| {
1518				println!("c:{c:?}");
1519				assert_eq!(
1520					c.raw_args,
1521					cnv_arg(vec!["exe_path", "--cstr", "test", "-b", "sub"])
1522				);
1523				assert_eq!(
1524					c.get_flag_value_of("cstr", &cmd).unwrap(),
1525					FlagValue::String("test".into())
1526				);
1527				assert_eq!(
1528					c.get_flag_value_of("bool", &cmd).unwrap(),
1529					FlagValue::Bool(true)
1530				);
1531				assert_eq!(c.routes, Vector(None));
1532				assert_attrs!("sub_", c, cmd);
1533				done!()
1534			}))
1535			.run(arg.clone());
1536
1537		arg.remove(2);
1538		arg[1] = "--cstr=test".into();
1539		arg.push("test_arg".into());
1540		arg.push("--cafter".into());
1541		arg.push("test_arg2".into());
1542		arg.push("--string".into());
1543		arg.push("testStr".into());
1544		let _ = root
1545			.clone()
1546			.sub_command(sub.clone().action(|cmd, c| {
1547				println!("{c:?}");
1548				assert_eq!(
1549					c.raw_args,
1550					cnv_arg(vec![
1551						"exe_path",
1552						"--cstr=test",
1553						"-b",
1554						"sub",
1555						"test_arg",
1556						"--cafter",
1557						"test_arg2",
1558						"--string",
1559						"testStr"
1560					])
1561				);
1562				assert_eq!(c.args, cnv_arg(vec!["test_arg", "test_arg2"]));
1563				assert_eq!(
1564					c.get_flag_value_of("cstr", &cmd).unwrap(),
1565					FlagValue::String("test".into())
1566				);
1567				assert_eq!(
1568					c.get_flag_value_of("bool", &cmd).unwrap(),
1569					FlagValue::Bool(true)
1570				);
1571				assert_eq!(
1572					c.get_flag_value_of("cafter", &cmd).unwrap(),
1573					FlagValue::Bool(true)
1574				);
1575				assert_eq!(c.get_local_flag_value_of("cafter", &cmd), None);
1576				assert_eq!(
1577					c.get_flag_value_of("string", &cmd).unwrap(),
1578					FlagValue::String("testStr".into())
1579				);
1580				assert_eq!(c.routes, Vector(None));
1581				assert_attrs!("sub_", c, cmd);
1582				done!()
1583			}))
1584			.run(arg.clone());
1585
1586		println!("\r\n\r\nサブサブコマンドが存在する場合の判別系\r\n");
1587		arg.remove(4);
1588		let _ = root
1589			.clone()
1590			.sub_command(sub.clone().action(|cmd, c| {
1591				println!("result_c: {c:?}");
1592				assert_eq!(
1593					c.raw_args,
1594					cnv_arg(vec![
1595						"exe_path",
1596						"--cstr=test",
1597						"-b",
1598						"sub",
1599						"--cafter",
1600						"test_arg2",
1601						"--string",
1602						"testStr"
1603					])
1604				);
1605				assert_eq!(c.args, vec!["test_arg2".to_string()]);
1606				assert_eq!(
1607					c.get_common_flag_value_of("cstr", &cmd).unwrap(),
1608					FlagValue::String("test".into())
1609				);
1610				assert_eq!(
1611					c.get_local_flag_value_of("string", &cmd).unwrap(),
1612					FlagValue::String("testStr".into())
1613				);
1614				assert_eq!(
1615					c.get_inputted_common_flag_value_of("cafter").unwrap(),
1616					FlagValue::None
1617				);
1618				assert_eq!(c.routes, Vector(None));
1619				assert_attrs!("sub_", c, cmd);
1620				done!()
1621			}))
1622			.run(arg.clone());
1623		println!("\r\n\r\nサブサブコマンドが存在する場合の判別系その2\r\n");
1624		arg.push("ex_arg".into());
1625		arg[5] = "test_arg".to_owned();
1626
1627		let _ = root
1628			.clone()
1629			.sub_command(sub.clone().action(|cmd, c| {
1630				println!("C: {c:?}");
1631				assert_eq!(
1632					c.raw_args,
1633					cnv_arg(vec![
1634						"exe_path",
1635						"--cstr=test",
1636						"-b",
1637						"sub",
1638						"--cafter",
1639						"test_arg",
1640						"--string",
1641						"testStr",
1642						"ex_arg"
1643					])
1644				);
1645				assert_eq!(c.args, cnv_arg(vec!["test_arg", "ex_arg"]));
1646				assert_eq!(c.routes, Vector(None));
1647				assert_attrs!("sub_", c, cmd);
1648				done!()
1649			}))
1650			.run(arg.clone());
1651		arg[6] = "--string=testStr".into();
1652		arg[8] = "test_arg2".into();
1653		arg.remove(7);
1654		arg.push("test_arg3".into());
1655		arg.push("--common".into());
1656		arg.push("test_arg4".into());
1657
1658		let _ = root
1659			.clone()
1660			.sub_command(sub.clone().action(|cmd, c| {
1661				println!("C: {c:?}");
1662				assert_eq!(
1663					c.raw_args,
1664					cnv_arg(vec![
1665						"exe_path",
1666						"--cstr=test",
1667						"-b",
1668						"sub",
1669						"--cafter",
1670						"test_arg",
1671						"--string=testStr",
1672						"test_arg2",
1673						"test_arg3",
1674						"--common",
1675						"test_arg4"
1676					])
1677				);
1678				assert_eq!(
1679					c.args,
1680					vec![
1681						"test_arg".to_owned(),
1682						"test_arg2".to_owned(),
1683						"test_arg3".to_owned(),
1684						"test_arg4".to_owned()
1685					]
1686				);
1687				assert_eq!(
1688					c.get_common_flag_value_of("cstr", &cmd).unwrap(),
1689					FlagValue::String("test".into())
1690				);
1691				assert_eq!(
1692					c.get_local_flag_value_of("bool", &cmd).unwrap(),
1693					FlagValue::Bool(true)
1694				);
1695				assert_eq!(
1696					c.get_common_flag_value_of("cafter", &cmd).unwrap(),
1697					FlagValue::Bool(true)
1698				);
1699				assert_eq!(
1700					c.get_flag_value_of("string", &cmd).unwrap(),
1701					FlagValue::String("testStr".into())
1702				);
1703				assert_eq!(c.routes, Vector(None));
1704				assert_attrs!("sub_", c, cmd);
1705				done!()
1706			}))
1707			.run(arg.clone());
1708
1709		arg.pop();
1710		arg.remove(8);
1711		arg.remove(7);
1712		arg.remove(5);
1713
1714		let _ = root
1715			.clone()
1716			.sub_command(sub.clone().action(|cmd, c| {
1717				println!("c: {c:?}");
1718				assert_eq!(
1719					c.raw_args,
1720					cnv_arg(vec![
1721						"exe_path",
1722						"--cstr=test",
1723						"-b",
1724						"sub",
1725						"--cafter",
1726						"--string=testStr",
1727						"--common"
1728					])
1729				);
1730				assert_eq!(c.args.len(), 0);
1731				assert_eq!(
1732					c.get_flag_value_of("cstr", &cmd).unwrap(),
1733					FlagValue::String("test".into())
1734				);
1735				assert_eq!(
1736					c.get_flag_value_of("bool", &cmd).unwrap(),
1737					FlagValue::Bool(true)
1738				);
1739				assert_eq!(
1740					c.get_flag_value_of("cafter", &cmd).unwrap(),
1741					FlagValue::Bool(true)
1742				);
1743				assert_eq!(
1744					c.get_flag_value_of("string", &cmd).unwrap(),
1745					FlagValue::String("testStr".into())
1746				);
1747				assert_eq!(
1748					c.get_flag_value_of("common", &cmd).unwrap(),
1749					FlagValue::Bool(true)
1750				);
1751				assert_eq!(c.routes, Vector(None));
1752				assert_attrs!("sub_", c, cmd);
1753				done!()
1754			}))
1755			.run(arg.clone());
1756	}
1757
1758	#[test]
1759	fn run_leaf() {
1760		let arg = vec![
1761			"exe_path".to_string(),
1762			"sub".to_string(),
1763			"leaf".to_string(),
1764			"--common".to_string(),
1765			"test".to_string(),
1766			"-c".to_string(),
1767			"--local".to_string(),
1768		];
1769		let root = Command::new()
1770			.action(|c, _| {
1771				println!("test_action: {c:?}");
1772				panic!("not sub");
1773			})
1774			.common_flag(Flag::new("common", FlagType::String, "sample common flag"))
1775			.common_flag(Flag::new_string("cshort").short_alias('c'))
1776			.local_flag(Flag::new("local", FlagType::default(), "sample local flag"))
1777			.sub_command(
1778				Command::with_name("sub")
1779					.action(|c, _| {
1780						panic!("sub: {c:?}");
1781					})
1782					.version("sub_version")
1783					.copyright("sub_copyright")
1784					.license(license!(
1785						"sub_license".into(),
1786						content=>"root_license_content".into(),
1787					))
1788					.authors("sub_authors")
1789					.sub_command(
1790						Command::with_name("leaf")
1791							.action(|cmd, c| {
1792								println!("{c:?}");
1793								let raw_args = vec![
1794									"exe_path".to_string(),
1795									"sub".to_string(),
1796									"leaf".to_string(),
1797									//"test".to_string(),
1798									"--common".to_string(),
1799									"test".to_string(),
1800									"-c".to_string(),
1801									"--local".to_string(),
1802								];
1803								//let expect_args = VecDeque::from(vec!["test".to_string()]);
1804								let expect_args = VecDeque::new();
1805								assert_eq!(c.exe_path, String::from("exe_path"));
1806								assert_eq!(c.raw_args, raw_args);
1807								assert_eq!(c.args, expect_args);
1808								assert_eq!(
1809									c.get_flag_value_of("common", &cmd),
1810									Some(FlagValue::String("test".into()))
1811								);
1812								assert_eq!(
1813									c.get_inputted_flag_value_of("cshort").unwrap(),
1814									FlagValue::None
1815								);
1816								assert_eq!(
1817									c.get_flag_value_of("cshort", &cmd).unwrap(),
1818									FlagValue::String("".into())
1819								);
1820								assert_eq!(
1821									c.get_flag_value_of("local", &cmd).unwrap(),
1822									FlagValue::Bool(true)
1823								);
1824								assert_eq!(c.get_common_flag_value_of("local", &cmd), None);
1825								assert_eq!(c.routes, Vector(Some(vec!["sub".to_string()])));
1826								assert_attrs!("leaf_", c, cmd);
1827								done!()
1828							})
1829							.local_flag(Flag::new_bool("local").short_alias('l'))
1830							.version("leaf_version")
1831							.copyright("leaf_copyright")
1832							.license(license!(
1833								"leaf_license".into(),
1834								content=>"leaf_license_content".into(),
1835							))
1836							.authors("leaf_authors"),
1837					),
1838			);
1839		let _ = root.run(arg.clone());
1840	}
1841
1842	#[test]
1843	fn run_leaf_with_flag_before_normal_flag() {
1844		let root = base_root().action(|c, _| {
1845			panic!("root action: {c:?} - not leaf");
1846		});
1847		let sub = Command::with_name("sub")
1848			.local_flag(Flag::new_bool("sub_local"))
1849			.local_flag(Flag::new_string("sub_lstr"))
1850			.common_flag(Flag::new_bool("sub_common"))
1851			.local_flag(Flag::new_string("sub_cstr"))
1852			.action(|c, _| {
1853				panic!("sub action: {c:?} - not leaf");
1854			});
1855		let leaf = Command::with_name("leaf")
1856			.common_flag(Flag::new_bool("cbool").short_alias('o'))
1857			.common_flag(Flag::new_string("cs"))
1858			.local_flag(Flag::new_bool("lbool").short_alias('b'))
1859			.local_flag(Flag::new_string("lsafter").short_alias('a'))
1860			.local_flag(Flag::new_string("lsbefore").short_alias('s'))
1861			.authors("leaf_authors")
1862			.copyright("leaf_copyright")
1863			.version("leaf_version")
1864			.license(license!(
1865				"leaf_license".to_owned(),
1866				content=>"leaf_license_content".to_owned(),
1867			));
1868
1869		let run_leaf: fn(Command, Command, Command, Action, Vec<String>) -> () =
1870			|root, sub, leaf, action, args| {
1871				let _ = root
1872					.sub_command(sub.sub_command(leaf.action(action)))
1873					.run(args);
1874			};
1875
1876		let mut args = cnv_arg(vec!["exe_path", "--lbool", "sub", "--lsbefore", "leaf"]);
1877
1878		run_leaf(
1879			root.clone().name("root"),
1880			sub.clone(),
1881			leaf.clone(),
1882			|cmd, c| {
1883				println!("{c:?}");
1884				assert_eq!(
1885					c.raw_args,
1886					cnv_arg(vec!["exe_path", "--lbool", "sub", "--lsbefore", "leaf"])
1887				);
1888				assert_eq!(c.args, VecDeque::new());
1889				assert_eq!(
1890					c.get_flag_value_of("lbool", &cmd).unwrap(),
1891					FlagValue::Bool(true)
1892				);
1893				assert_eq!(
1894					c.get_flag_value_of("lsbefore", &cmd).unwrap(),
1895					FlagValue::String("".into())
1896				);
1897				assert_eq!(
1898					c.routes,
1899					Vector(Some(vec!["root".to_string(), "sub".to_owned(),]))
1900				);
1901				assert_attrs!("leaf_", c, cmd);
1902				done!()
1903			},
1904			args.clone(),
1905		);
1906
1907		args.push("arg".into());
1908
1909		run_leaf(
1910			root.clone(),
1911			sub.clone(),
1912			leaf.clone(),
1913			|cmd, c| {
1914				println!("{c:?}");
1915				assert_eq!(
1916					c.raw_args,
1917					cnv_arg(vec![
1918						"exe_path",
1919						"--lbool",
1920						"sub",
1921						"--lsbefore",
1922						"leaf",
1923						"arg"
1924					])
1925				);
1926				assert_eq!(c.args, VecDeque::from(vec![String::from("arg")]));
1927				assert_eq!(
1928					c.get_flag_value_of("lbool", &cmd).unwrap(),
1929					FlagValue::Bool(true)
1930				);
1931				assert_eq!(
1932					c.get_flag_value_of("lsbefore", &cmd).unwrap(),
1933					FlagValue::String("".into())
1934				);
1935				assert_eq!(c.routes, Vector(Some(vec!["sub".to_owned()])));
1936				assert_attrs!("leaf_", c, cmd);
1937				done!()
1938			},
1939			args.clone(),
1940		);
1941		args.push("-o".into());
1942		run_leaf(
1943			root.clone(),
1944			sub.clone(),
1945			leaf.clone(),
1946			|cmd, c| {
1947				println!("{c:?}");
1948				assert_eq!(
1949					c.raw_args,
1950					cnv_arg(vec![
1951						"exe_path",
1952						"--lbool",
1953						"sub",
1954						"--lsbefore",
1955						"leaf",
1956						"arg",
1957						"-o"
1958					])
1959				);
1960				assert_eq!(
1961					c.get_flag_value_of("lbool", &cmd).unwrap(),
1962					FlagValue::Bool(true)
1963				);
1964				assert_eq!(c.args, VecDeque::from(vec!["arg".to_string()]));
1965				assert_eq!(
1966					c.get_flag_value_of("lsbefore", &cmd).unwrap(),
1967					FlagValue::String("".into())
1968				);
1969				assert_eq!(
1970					c.get_flag_value_of("cbool", &cmd).unwrap(),
1971					FlagValue::Bool(true)
1972				);
1973				assert_eq!(c.routes, Vector(Some(vec!["sub".to_owned()])));
1974				assert_attrs!("leaf_", c, cmd);
1975				done!()
1976			},
1977			args.clone(),
1978		);
1979		args.pop();
1980		args.insert(4, "before_arg".into());
1981
1982		run_leaf(
1983			root.clone(),
1984			sub.clone(),
1985			leaf.clone(),
1986			|cmd, c| {
1987				println!("{c:?}");
1988				assert_eq!(
1989					c.raw_args,
1990					cnv_arg(vec![
1991						"exe_path",
1992						"--lbool",
1993						"sub",
1994						"--lsbefore",
1995						"before_arg",
1996						"leaf",
1997						"arg"
1998					])
1999				);
2000				assert_eq!(c.args, VecDeque::from(vec!["arg".to_string()]));
2001				assert_eq!(c.args, VecDeque::from(vec![String::from("arg")]));
2002				assert_eq!(
2003					c.get_flag_value_of("lbool", &cmd).unwrap(),
2004					FlagValue::Bool(true)
2005				);
2006				assert_eq!(
2007					c.get_flag_value_of("lsbefore", &cmd).unwrap(),
2008					FlagValue::String("before_arg".into())
2009				);
2010				assert_eq!(c.routes, Vector(Some(vec!["sub".to_owned()])));
2011				assert_attrs!("leaf_", c, cmd);
2012				done!()
2013			},
2014			args.clone(),
2015		);
2016	}
2017
2018	#[test]
2019	fn test_flag_type() {
2020		let arg = vec![
2021			"exe_path".to_string(),
2022			"sub".to_string(),
2023			"leaf".to_string(),
2024			"test".to_string(),
2025			"--common".to_string(),
2026			"test".to_string(),
2027			"-c".to_string(),
2028			"--local".to_string(),
2029			"-y".to_string(),
2030			"-i".to_string(),
2031			"111".to_string(),
2032			"--float".to_string(),
2033			"10.0".to_string(),
2034		];
2035
2036		let leaf = Command::with_name("leaf")
2037			.action(|cmd, c| {
2038				println!("sub_action: {c:?}");
2039				let raw_args = vec![
2040					"exe_path".to_string(),
2041					"sub".to_string(),
2042					"leaf".to_string(),
2043					"test".to_string(),
2044					"--common".to_string(),
2045					"test".to_string(),
2046					"-c".to_string(),
2047					"--local".to_string(),
2048					"-y".to_string(),
2049					"-i".to_string(),
2050					"111".to_string(),
2051					"--float".to_string(),
2052					"10.0".to_string(),
2053				];
2054				let expect_args = VecDeque::from(vec!["test".to_string(), "test".to_owned()]);
2055				assert_eq!(c.exe_path, String::from("exe_path"));
2056				assert_eq!(c.raw_args, raw_args);
2057				assert_eq!(c.args, expect_args);
2058				assert_eq!(
2059					c.get_flag_value_of("common", &cmd),
2060					Some(FlagValue::Bool(true))
2061				);
2062				assert_eq!(
2063					c.get_inputted_flag_value_of("commons"),
2064					Some(FlagValue::None)
2065				);
2066				assert_eq!(
2067					c.get_flag_value_of("commons", &cmd),
2068					Some(FlagValue::String("".into()))
2069				);
2070				assert_eq!(c.get_flag_value_of("local", &cmd), None);
2071				assert_eq!(c.get_inputted_common_flag_value_of("yes"), None);
2072				assert_eq!(
2073					c.get_local_flag_value_of("yes", &cmd),
2074					Some(FlagValue::Bool(true))
2075				);
2076				assert_eq!(
2077					c.get_flag_value_of("yes", &cmd),
2078					Some(FlagValue::Bool(true))
2079				);
2080				let expect_error_args = {
2081					let mut vd = VecDeque::new();
2082					vd.push_back(MiddleArg::LongFlag("local".into(), FlagValue::None));
2083					vd
2084				};
2085				assert_eq!(c.get_flag_value_of("int", &cmd), Some(FlagValue::Int(111)));
2086				assert_eq!(
2087					c.get_flag_value_of("float", &cmd),
2088					Some(FlagValue::Float(10.into()))
2089				);
2090
2091				assert_eq!(
2092					c.error_info_list,
2093					Vector::from(vec![(
2094						MiddleArg::LongFlag("local".into(), FlagValue::None),
2095						ParseError::NoExistLong,
2096						ParseError::NoExistLong
2097					)])
2098				);
2099				assert_attrs!("sub_", c, cmd);
2100				assert_eq!(c.parsing_args.unwrap(), expect_error_args);
2101				done!()
2102			})
2103			.local_flag(Flag::new_bool("yes").short_alias('y'))
2104			.local_flag(Flag::new_int("int").short_alias('i'))
2105			.local_flag(Flag::new_float("float").short_alias('f'))
2106			.authors("sub_authors")
2107			.version("sub_version")
2108			.copyright("sub_copyright")
2109			.license(license!(
2110				"sub_license".into(),
2111				content=>"sub_license_content".into(),
2112			));
2113		let root = Command::new()
2114			.action(|c, _| {
2115				println!("test_action: {c:?}");
2116				panic!("not sub");
2117			})
2118			.common_flag(Flag::new(
2119				"common",
2120				FlagType::default(),
2121				"sample common flag",
2122			))
2123			.common_flag(Flag::new_string("commons").short_alias('c'))
2124			.common_flag(Flag::new_string("yes").short_alias('y'))
2125			.local_flag(Flag::new("local", FlagType::default(), "sample local flag"))
2126			.sub_command(
2127				Command::with_name("sub")
2128					.action(|c, _| {
2129						println!("sub: {c:?}");
2130						panic!("not leaf");
2131					})
2132					.sub_command(leaf),
2133			);
2134		let _ = root.run(arg.clone());
2135	}
2136}
2137
2138/// Presets of Command
2139pub mod presets {
2140
2141	use crate::Vector;
2142	use crate::default_usage;
2143
2144	use super::{Action, Command, License};
2145
2146	/// Create usage preset
2147	pub fn usage<T: Into<String>>(name: T) -> String {
2148		default_usage!(name as var)
2149	}
2150
2151	/// Create root command with base
2152	pub fn root_with_base<T: Into<String>>(
2153		name: T,
2154		authors: T,
2155		version: T,
2156		description: T,
2157		action: Option<Action>,
2158	) -> Command {
2159		let name = name.into();
2160		let usage = default_usage!(nameString=>name.clone());
2161		Command::with_all_field(
2162			name,
2163			action,
2164			authors.into(),
2165			String::default(),
2166			License(None),
2167			Some(description.into()),
2168			usage,
2169			Vector::default(),
2170			Vector::default(),
2171			Vector::default(),
2172			version.into(),
2173			Vector::default(),
2174		)
2175	}
2176
2177	/// Create version command preset
2178	pub fn preset_version() -> Command {
2179		Command::with_all_field(
2180			String::from("version"),
2181			Some(func::version_print),
2182			String::default(),
2183			String::default(),
2184			License::default(),
2185			Some(String::from("show version")),
2186			String::default(),
2187			Vector::default(),
2188			Vector::default(),
2189			Vector::default(),
2190			String::default(),
2191			Vector::default(),
2192		)
2193	}
2194
2195	/// function presets for command construction.
2196	pub mod func {
2197		use crate::{FlagType, action_result};
2198
2199		use super::super::{Command, Context, Flag, Vector};
2200		use std::cmp::max;
2201
2202		/// Preset of version command action
2203		pub fn version_print(cmd: Command, ctx: Context) -> action_result!() {
2204			crate::check_help!(cmd, ctx, help_tablize_with_alias_dedup);
2205			println!("{}", cmd.version);
2206			crate::done!()
2207		}
2208
2209		/// macro for help action
2210		macro_rules! _add_help_with_flag_dudup {
2211			($help:ident,$iter:expr,$nl_list:ident,$s_list:ident,$suffix:ident,$name_and_alias_min_width:ident,$sp:ident,$indent:ident) => {
2212				for f in $iter {
2213					let mut all_dup = true;
2214					let first_help_width = $help.len();
2215					if let Vector(Some(short_alias)) = &f.short_alias {
2216						for s in short_alias.iter() {
2217							if !$s_list.contains(&s) {
2218								if (!all_dup) {
2219									$help.push(',');
2220								}
2221								all_dup = false;
2222								$help.push_str("-");
2223								$help.push(*s);
2224								$s_list.push(s);
2225							}
2226						}
2227					} else {
2228						$help.push_str(&$indent);
2229					}
2230					if !$nl_list.contains(&&f.name) {
2231						$help.push_str(if all_dup { " --" } else { ", --" });
2232						all_dup = false;
2233						$help.push_str(&f.name);
2234						$nl_list.push(&f.name);
2235					}
2236					if let Vector(Some(long_alias)) = &f.long_alias {
2237						for long in long_alias.iter() {
2238							if !$nl_list.contains(&long) {
2239								$nl_list.push(long);
2240								if all_dup {
2241									$help.push_str(" --");
2242									all_dup = false;
2243								} else {
2244									$help.push_str(", --");
2245								}
2246								$help.push_str(long);
2247							}
2248						}
2249					}
2250					if all_dup {
2251						$help.truncate(first_help_width);
2252					} else {
2253						let name_and_alias_width = $help.len() - first_help_width;
2254						if name_and_alias_width < $name_and_alias_min_width {
2255							$help.push_str(
2256								$sp.repeat($name_and_alias_min_width - name_and_alias_width)
2257									.as_str(),
2258							);
2259						}
2260						$help.push('\t');
2261						$help.push_str(&f.description);
2262						$help.push_str(&$suffix);
2263						$help.push('\n');
2264					}
2265				}
2266			};
2267		}
2268
2269		/// Add help for this flag to append_to. name_and_alias_min_width means min width of name and alias' field.
2270		/// Flagに対するヘルプをappend_toに追加する。nameとalias表示部分のずれをある程度吸収できるようにその部分の最小幅をname_and_alias_min_widthで指定する
2271		fn flag_help_simple(
2272			flag: &Flag,
2273			append_to: String,
2274			name_and_alias_min_width: usize,
2275		) -> String {
2276			let mut help = append_to;
2277			let first_help_width = help.len();
2278
2279			if let Vector(Some(short_alias)) = &flag.short_alias {
2280				help = short_alias
2281					.iter()
2282					.fold(help, |help, s| format!("{help}-{s},"));
2283			} else {
2284				help += "   ";
2285			}
2286			help = help + " --" + &flag.name;
2287			if let Vector(Some(long_alias)) = &flag.long_alias {
2288				help = long_alias.iter().fold(help, |help, l| {
2289					//ロングフラグ出力
2290					format!("{help}, --{l}")
2291				})
2292			};
2293			help = add_type_suffix(help, &flag.flag_type);
2294			let name_and_alias_width = help.len() - first_help_width;
2295
2296			if name_and_alias_width < name_and_alias_min_width {
2297				help += &" ".repeat(name_and_alias_min_width - name_and_alias_width);
2298			}
2299
2300			help + "\t" + &flag.description + "\n"
2301		}
2302		/// Preset of help function(compact version)
2303		pub fn help_with_alias_dedup(cmd: &Command, ctx: &Context) -> String {
2304			let mut help = String::new();
2305			let indent_size: usize = 3;
2306			let sp = String::from(" ");
2307			let indent = sp.repeat(indent_size);
2308			if let Some(description) = &cmd.description {
2309				help.push_str(description);
2310				help.push_str("\n\n");
2311			}
2312			help += &format!("Usage:\n{}{}\n", &indent, cmd.usage);
2313			let name_and_alias_min_width = 12;
2314			let routes = ctx.routes.clone();
2315			let mut routes: Vec<String> = if routes.len() < ctx.depth() {
2316				let mut routes: Vec<String> = routes.into();
2317				routes.insert(
2318					0,
2319					std::path::Path::new(ctx.exe_path())
2320						.file_stem()
2321						.unwrap_or(std::ffi::OsStr::new("root"))
2322						.to_str()
2323						.unwrap_or("root")
2324						.to_owned(),
2325				);
2326				routes
2327			} else {
2328				routes.into()
2329			};
2330			if cmd.l_flags.has_at_least_one()
2331				|| cmd.c_flags.has_at_least_one()
2332				|| ctx.common_flags.has_at_least_one()
2333			{
2334				help.push_str("\nFlags: \n");
2335
2336				let mut nl_list = Vec::<&String>::new();
2337				let mut s_list = Vec::<&char>::new();
2338
2339				if let Vector(Some(l_flags)) = &cmd.l_flags {
2340					let mut i = l_flags.iter().rev();
2341					if let Some(f) = i.next() {
2342						// ローカルフラグ出力
2343						help = flag_help_simple(f, help, name_and_alias_min_width);
2344						nl_list.push(&f.name);
2345						if let Vector(Some(la)) = &f.long_alias {
2346							let mut la = la.iter().collect();
2347							nl_list.append(&mut la);
2348						};
2349						if let Vector(Some(sa)) = &f.short_alias {
2350							let mut sa = sa.iter().collect();
2351							s_list.append(&mut sa)
2352						}
2353						let emp_str = String::new();
2354						_add_help_with_flag_dudup!(
2355							help,
2356							i,
2357							nl_list,
2358							s_list,
2359							emp_str,
2360							name_and_alias_min_width,
2361							sp,
2362							indent
2363						)
2364					}
2365				}
2366
2367				// コモンフラグ出力
2368				// まず現在のコマンドのコモンフラグ出力
2369				if let Vector(Some(c_flags)) = &cmd.c_flags {
2370					let suffix = if !cmd.sub.is_empty() {
2371						format!(
2372							"[also available in sub command{} under here]",
2373							(if cmd.sub.len() < 2 { "" } else { "s" })
2374						)
2375					} else {
2376						String::new()
2377					};
2378					_add_help_with_flag_dudup!(
2379						help,
2380						c_flags.iter().rev(),
2381						nl_list,
2382						s_list,
2383						suffix,
2384						name_and_alias_min_width,
2385						sp,
2386						indent
2387					);
2388				}
2389
2390				// コモンフラグ出力(contextに取り込まれているフラグ)
2391				if let Vector(Some(cfs)) = &ctx.common_flags {
2392					for (c_index, c_flags) in cfs.iter().enumerate().rev() {
2393						if let Vector(Some(c_flags)) = c_flags {
2394							let suffix = match routes.get(c_index) {
2395								Some(cmd_name) => sp.clone() + "(inherited from " + cmd_name + ")",
2396								None => String::new(),
2397							};
2398
2399							_add_help_with_flag_dudup!(
2400								help,
2401								c_flags.iter().rev(),
2402								nl_list,
2403								s_list,
2404								suffix,
2405								name_and_alias_min_width,
2406								sp,
2407								indent
2408							);
2409						}
2410					}
2411				}
2412			}
2413
2414			// サブコマンド出力
2415			if let Vector(Some(sub)) = &cmd.sub {
2416				let mut iter = sub.iter();
2417				if let Some(sub_command) = iter.next() {
2418					help.push_str("Sub Command");
2419					if sub.len() > 1 {
2420						help.push('s');
2421					}
2422					help.push_str(": \n");
2423					// 最初のフラグ情報追加
2424					help = help + &indent + &sub_command.name;
2425					let mut na_list = vec![&sub_command.name];
2426					let mut name_and_alias_width = sub_command.name.len();
2427					if let Vector(Some(alias)) = &sub_command.alias {
2428						let mut a = alias.iter().collect();
2429						na_list.append(&mut a);
2430						for a in alias {
2431							help = help + ", " + a;
2432							name_and_alias_width += a.len() + 2;
2433						}
2434					}
2435					if name_and_alias_width < name_and_alias_min_width {
2436						help = help + &sp.repeat(name_and_alias_min_width - name_and_alias_width);
2437					}
2438					if let Some(description) = &sub_command.description {
2439						help = help + "\t" + description
2440					}
2441					help += "\n";
2442
2443					for sub_cmd in iter {
2444						let mut all_dup = true;
2445						let help_first_width = help.len();
2446						if !na_list.contains(&&sub_cmd.name) {
2447							na_list.push(&sub_cmd.name);
2448							help = help + &indent + &sub_cmd.name;
2449							all_dup = false;
2450						}
2451						if let Vector(Some(alias)) = &sub_cmd.alias {
2452							for a in alias {
2453								if !na_list.contains(&a) {
2454									na_list.push(a);
2455									if all_dup {
2456										help = help + &indent + a;
2457									} else {
2458										help = help + ", " + a;
2459									}
2460									all_dup = false;
2461								}
2462							}
2463						}
2464						if !all_dup {
2465							let name_and_alias_width = help_first_width - help.len();
2466							if name_and_alias_width < name_and_alias_min_width {
2467								help += &sp.repeat(name_and_alias_min_width - name_and_alias_width);
2468							}
2469							if let Some(description) = &sub_cmd.description {
2470								help = help + "\t" + description;
2471							}
2472							help += "\n"
2473						}
2474					}
2475				}
2476				if routes.len() < 2 && !cmd.name.is_empty() {
2477					routes[0] = cmd.name.clone();
2478				}
2479				let exe_suffix = std::env::consts::EXE_SUFFIX;
2480				if !exe_suffix.is_empty() {
2481					routes[0].push('[');
2482					routes[0].push_str(exe_suffix);
2483					routes[0].push(']')
2484				}
2485				help = help + &routes.join(" ") + "<subcommand> --help for more information.";
2486				help += "\n";
2487			}
2488			help
2489		}
2490
2491		/// Add type suffix for flag help
2492		pub fn add_type_suffix(to: String, ft: &FlagType) -> String {
2493			match &ft {
2494				FlagType::Bool => to,
2495				FlagType::String => to + " <string>",
2496				FlagType::Int => to + " <int>",
2497				FlagType::Float => to + " <float>",
2498			}
2499		}
2500
2501		/// Preset of help function
2502		pub fn help(cmd: &Command, ctx: &Context) -> String {
2503			let mut help = String::new();
2504			let indent_size: usize = 3;
2505			let sp = String::from(" ");
2506			let indent: String = sp.repeat(indent_size);
2507			if let Some(description) = &cmd.description {
2508				help.push_str(description);
2509				help.push_str("\n\n");
2510			}
2511			help += &format!("Usage:\n{}{}\n\n", &indent, cmd.usage);
2512
2513			//フラグ処理
2514			let l_flags: &Vector<Flag> = &cmd.l_flags;
2515			let ctx_c_flags: &Vector<Vector<Flag>> = &ctx.common_flags;
2516
2517			help.push_str("Flags(If exist flags have same alias and specified by user, inputted value will be interpreted as the former flag's value): \n");
2518			let head: String;
2519			let cl_label;
2520			let name_and_alias_field_min_width: usize = 7;
2521			if (ctx_c_flags.sum_of_length() + cmd.c_flags.len()) > 0 && cmd.l_flags.has_at_least_one()
2522			{
2523				//コモンフラグとローカルフラグ両方が設定されている場合
2524				head = indent.repeat(2);
2525				cl_label = true;
2526			} else {
2527				//設定されていない場合、ローカルフラグもしくはコモンフラグだけなのでラベルはいらない
2528				head = indent.clone();
2529				cl_label = false;
2530			}
2531
2532			if let Vector(Some(l_flags)) = l_flags {
2533				if cl_label {
2534					help.push_str(&indent);
2535					help.push_str("[Local]: \n");
2536				}
2537				help = l_flags.iter().rfold(help, |help, l_flag| {
2538					flag_help_simple(l_flag, help + &head, name_and_alias_field_min_width + 10)
2539				});
2540			}
2541			let depth = ctx.depth();
2542			let mut common_head = true;
2543			if let Vector(Some(c_flags)) = &cmd.c_flags {
2544				if cl_label {
2545					help = help
2546						+ &indent + "[Common"
2547						+ &format!(
2548							"(common flags are available in this command and sub command{} under this command)]: \n",
2549							(if cmd.sub.len() < 2 { "" } else { "s" })
2550						);
2551				}
2552
2553				for cf in c_flags {
2554					help = flag_help_simple(cf, help + &head, name_and_alias_field_min_width)
2555				}
2556
2557				common_head = false;
2558			}
2559			if let Vector(Some(c_flags)) = ctx_c_flags {
2560				let route_without_root = depth > ctx.routes.len();
2561				if cl_label && common_head {
2562					help = help + &indent + "Common ";
2563				}
2564				help = c_flags
2565					.iter()
2566					.enumerate()
2567					.rfold(help, |help, (index, c_flags)| -> String {
2568						//コモンフラグ書き出し
2569						if let Vector(Some(c_flags)) = c_flags {
2570							let mut help = help;
2571							if cl_label {
2572								let mut from_owned: String;
2573								let from = if route_without_root {
2574									if index < 1 {
2575										let cur_path = std::path::Path::new(ctx.exe_path());
2576										from_owned = cur_path
2577											.file_stem()
2578											.unwrap_or(std::ffi::OsStr::new("root"))
2579											.to_str()
2580											.unwrap_or("root")
2581											.to_owned();
2582										match cur_path.extension() {
2583											None => {}
2584											Some(val) => {
2585												from_owned += &format!("[.{}]", val.to_str().unwrap_or("exe"))
2586											}
2587										}
2588
2589										&from_owned
2590									} else {
2591										ctx.routes.get(index - 1).unwrap()
2592									}
2593								} else {
2594									ctx.routes.get(index).unwrap()
2595								};
2596								if common_head {
2597									help += &format!("[inherited from {from}]: \n")
2598								} else {
2599									common_head = false;
2600									help += &format!("{}[inherited from {}]: \n", &indent, from)
2601								}
2602							}
2603
2604							help = c_flags.iter().rfold(help, |help, c_flag| -> String {
2605								flag_help_simple(c_flag, help + &head, name_and_alias_field_min_width)
2606							});
2607							help
2608						} else {
2609							help
2610						}
2611					});
2612				help += "\n";
2613			}
2614
2615			if let Vector(Some(sub_commands)) = &cmd.sub {
2616				help += &format!(
2617					"Sub Command{}: \n",
2618					if sub_commands.len() < 2 { "" } else { "s" }
2619				);
2620				help = sub_commands.iter().fold(help, |help, sub_command| {
2621					//サブコマンドの説明出力
2622					let mut help = help + &indent + &sub_command.name;
2623					let mut name_and_alias_width = sub_command.name.len();
2624					if let Vector(Some(alias)) = &sub_command.alias {
2625						let (h_str, w) = alias
2626							.iter()
2627							.fold((help, name_and_alias_width), |(help, w), alias| {
2628								(help + ", " + alias, w + 2 + alias.len())
2629							});
2630						help = h_str;
2631						name_and_alias_width = w;
2632					}
2633					if name_and_alias_width < name_and_alias_field_min_width {
2634						help += &sp.repeat(name_and_alias_field_min_width - name_and_alias_width);
2635					}
2636
2637					help = if let Some(description) = &sub_command.description {
2638						help + "\t" + description
2639					} else {
2640						help
2641					};
2642					help + "\n"
2643				});
2644				let loc_owned: String;
2645				let location: &str = {
2646					if cmd.name.is_empty() {
2647						let path = std::path::Path::new(ctx.exe_path());
2648						let mut l: String = path
2649							.file_stem()
2650							.unwrap_or(std::ffi::OsStr::new("root"))
2651							.to_str()
2652							.unwrap_or("root")
2653							.to_owned();
2654						match path.extension() {
2655							None => {}
2656							Some(ext) => {
2657								l = l + "[." + ext.to_str().unwrap_or("exe") + "]";
2658							}
2659						}
2660						loc_owned = l;
2661						&loc_owned
2662					} else {
2663						//セルフネームがある
2664						if depth < 1 {
2665							//コモンフラグが1コマンド分しかない→現在はルートコマンド
2666							&cmd.name
2667						} else {
2668							loc_owned = if let Vector(Some(routes)) = &ctx.routes {
2669								routes.iter().rfold(
2670									{
2671										if depth > routes.len() {
2672											let path = std::path::Path::new(ctx.exe_path());
2673											let mut l = path
2674												.file_stem()
2675												.unwrap_or(std::ffi::OsStr::new("root"))
2676												.to_str()
2677												.unwrap_or("root")
2678												.to_owned();
2679											match path.extension() {
2680												None => {}
2681												Some(val) => {
2682													l = l + "[." + val.to_str().unwrap_or("exe") + "]";
2683												}
2684											}
2685											l
2686										} else {
2687											String::new()
2688										}
2689									},
2690									|str, route| {
2691										//現在どのコマンドに対応しているか
2692										str + &sp + route
2693									},
2694								)
2695							} else {
2696								panic!("Routes of context should be not none under sub command.")
2697							};
2698							&loc_owned
2699						}
2700					}
2701				};
2702				help = help + "\n" + &format!("{location} <subcommand> --help for more information.");
2703				help += "\n";
2704			}
2705
2706			help
2707		}
2708
2709		/// Preset of flag help function (tablize)
2710		pub fn flag_help_tablize(
2711			append_to: String,
2712			f: &Flag,
2713			sp: &str,
2714			s_max_num: usize, //最大ショートエイリアス数
2715			nl_width: usize,
2716			pre_d_space: &str,
2717		) -> String {
2718			let mut help = append_to;
2719			// short_alias出力
2720			help = help + &sp.repeat((s_max_num - f.short_alias.len()) * 4);
2721			if let Vector(Some(short_alias)) = &f.short_alias {
2722				for s in short_alias {
2723					help.push('-');
2724					help.push(*s);
2725					help.push_str(", ");
2726				}
2727			}
2728			let prev_help_len = help.len();
2729			help.push_str("--");
2730			help.push_str(&f.name);
2731			if let Vector(Some(long_alias)) = &f.long_alias {
2732				for l in long_alias {
2733					help.push_str(", --");
2734					help.push_str(l);
2735				}
2736			}
2737			help = add_type_suffix(help, &f.flag_type);
2738			let _nl_width = help.len() - prev_help_len;
2739			if _nl_width < nl_width {
2740				help.push_str(&sp.repeat(nl_width - _nl_width));
2741			}
2742			help.push_str(pre_d_space);
2743			help.push_str(&f.description);
2744			help.push('\n');
2745
2746			help
2747		}
2748
2749		/// Preset of help function (tablize)
2750		pub fn help_tablize(cmd: &Command, ctx: &Context) -> String {
2751			let mut help = String::new();
2752			let indent_size: usize = 3;
2753			let sp = String::from(" ");
2754			let indent: String = sp.repeat(indent_size);
2755			if let Some(description) = &cmd.description {
2756				help.push_str(description);
2757				help.push_str("\n\n");
2758			}
2759			help = help + "Usage:\n" + &indent + &cmd.usage + "\n\n";
2760
2761			if cmd.l_flags.len() + cmd.c_flags.len() + ctx.common_flags.sum_of_length() > 0 {
2762				// フラグが存在するとき
2763				help.push_str("Flags(If exist flags have same alias and specified by user, inputted value will be interpreted as the former flag's value): \n");
2764
2765				let nl_width = |flag: &Flag| match &flag.long_alias {
2766					Vector(None) => flag.name.len() + flag_type_suffix_len(&flag.flag_type),
2767					Vector(Some(long_aliases)) => {
2768						long_aliases.iter().fold(
2769							flag.name.len() + flag_type_suffix_len(&flag.flag_type),
2770							|width, long_alias| width + long_alias.len(),
2771						) + long_aliases.len() * 4
2772					}
2773				};
2774
2775				let max_calc =
2776					|flags: &Vector<Flag>, s_width_max: &mut usize, nl_width_max: &mut usize| {
2777						if let Vector(Some(flags)) = flags {
2778							for f in flags {
2779								*s_width_max = max(*s_width_max, f.short_alias.len());
2780								*nl_width_max = max(*nl_width_max, nl_width(f));
2781							}
2782						}
2783					};
2784				// フラグ出力
2785				let l_flags = &cmd.l_flags;
2786				let c_flags = &cmd.c_flags;
2787				let ctx_c_flags = &ctx.common_flags;
2788				// short_aliasの幅とlong_aliasの幅計算
2789				// short_aliasとlong_aliasを調べてmax_widthを出す
2790				let mut s_width_max: usize = 1; //文字幅が決まっているので文字数を記録
2791				let mut nl_width_max: usize = 8;
2792				max_calc(l_flags, &mut s_width_max, &mut nl_width_max);
2793				max_calc(c_flags, &mut s_width_max, &mut nl_width_max);
2794				if let Vector(Some(ctx_c_flags)) = ctx_c_flags {
2795					for ccf in ctx_c_flags {
2796						max_calc(ccf, &mut s_width_max, &mut nl_width_max);
2797					}
2798				}
2799
2800				let head: String;
2801				let cl_label: bool;
2802				if cmd.l_flags.has_at_least_one() {
2803					// ローカルがある場合、区別用のラベル表示する
2804					head = indent.repeat(2);
2805					cl_label = true;
2806				} else {
2807					head = indent.clone();
2808					cl_label = false;
2809				}
2810
2811				let gap = sp.repeat(2);
2812				if let Vector(Some(l_flags)) = l_flags {
2813					if cl_label {
2814						help.push_str(&indent);
2815						help.push_str("[Local]: \n");
2816					}
2817					for l in l_flags.iter().rev() {
2818						help.push_str(&head);
2819						help = flag_help_tablize(help, l, &sp, s_width_max, nl_width_max, &gap);
2820					}
2821				}
2822
2823				if let Vector(Some(c_flags)) = c_flags {
2824					if cl_label {
2825						help.push_str(&indent);
2826						help.push_str("[Common (available in this command and sub command");
2827						if cmd.sub.len() > 1 {
2828							help.push('s');
2829						}
2830						help.push_str(" under this command)]: \n");
2831					}
2832					for c in c_flags.iter().rev() {
2833						help.push_str(&head);
2834						help = flag_help_tablize(help, c, &sp, s_width_max, nl_width_max, &gap)
2835					}
2836				}
2837
2838				if let Vector(Some(ctx_c_flags)) = ctx_c_flags {
2839					let route_without_root = ctx.depth() > ctx.routes.len();
2840					for (index, cc_flags) in ctx_c_flags.iter().enumerate().rev() {
2841						if let Vector(Some(cc_flags)) = cc_flags {
2842							help.push_str("[Common, inherited from ");
2843							if route_without_root {
2844								if index < 1 {
2845									help.push_str(&root_str(ctx.exe_path()))
2846								} else {
2847									match ctx.routes.get(index - 1) {
2848										Some(val) => help.push_str(val),
2849										None => help.push_str("unknown"),
2850									}
2851								}
2852							} else {
2853								match ctx.routes.get(index) {
2854									Some(val) => help.push_str(val),
2855									None => help.push_str("unknown"),
2856								}
2857							}
2858							help.push_str("]: \n");
2859							for c in cc_flags {
2860								help.push_str(&head);
2861								help = flag_help_tablize(help, c, &sp, s_width_max, nl_width_max, &gap);
2862							}
2863						}
2864					}
2865				}
2866			}
2867
2868			if let Vector(Some(sub_commands)) = &cmd.sub {
2869				help += "Sub Command";
2870				if sub_commands.len() > 1 {
2871					help.push('s');
2872				}
2873				help += ": \n";
2874				let mut na_max_width: usize = 10;
2875				for sc in sub_commands {
2876					match &sc.alias {
2877						Vector(None) => na_max_width = max(na_max_width, sc.name.len()),
2878						Vector(Some(alias)) => {
2879							na_max_width = max(
2880								na_max_width,
2881								alias
2882									.iter()
2883									.fold(sc.name.len() + 2 * alias.len(), |sum, a| sum + a.len()),
2884							);
2885						}
2886					}
2887				}
2888
2889				na_max_width += 3;
2890
2891				for sc in sub_commands {
2892					let help_pref_len = help.len();
2893					help = help + &sc.name;
2894					if let Vector(Some(alias)) = &sc.alias {
2895						help = alias.iter().fold(help, |help, a| help + ", " + a)
2896					}
2897					let sp_num = na_max_width - help.len() + help_pref_len;
2898					help = help + &sp.repeat(sp_num);
2899					if let Some(description) = &sc.description {
2900						help.push_str(description);
2901					}
2902					help.push('\n');
2903				}
2904
2905				help.push_str("\nSee '");
2906				if ctx.depth() > 0 {
2907					if ctx.depth() > ctx.routes.len() {
2908						help.push_str(&root_str(ctx.exe_path()));
2909						help.push_str(&sp);
2910					}
2911					if let Vector(Some(routes)) = &ctx.routes {
2912						for route in routes {
2913							help.push_str(route);
2914							help.push_str(&sp);
2915						}
2916					}
2917					help.push_str(&cmd.name);
2918					help.push_str(" <subcommand> --help' for more information");
2919				} else {
2920					let root = if cmd.name.is_empty() {
2921						root_str(ctx.exe_path())
2922					} else {
2923						cmd.name.clone()
2924					};
2925
2926					help.push_str(&root);
2927					help.push_str("<subcommand> --help' for more information.")
2928				}
2929			}
2930
2931			help
2932		}
2933
2934		/// helper macro for flag tablize
2935		macro_rules! _flag_tablize_dedup {
2936			($iter:expr,$nl_col_width:ident,$s_col_width:ident,$nl_list:ident,$s_list:ident,$s_columns:ident,$nl_columns:ident) => {
2937				for f in $iter {
2938					let mut alias_exist = false;
2939					if let Vector(Some(sa)) = &f.short_alias {
2940						let mut dedup_s = Vec::<&char>::new();
2941						for s in sa.iter() {
2942							if !$s_list.contains(&s) {
2943								dedup_s.push(s);
2944								$s_list.push(s);
2945								alias_exist = true;
2946							}
2947						}
2948						$s_col_width = max(dedup_s.len(), $s_col_width);
2949						$s_columns.push_back(dedup_s);
2950					} else {
2951						$s_columns.push_back(vec![]);
2952					}
2953					let mut dedup_nl = Vec::<&String>::new();
2954					let mut nl_width;
2955					if !$nl_list.contains(&&f.name) {
2956						$nl_list.push(&f.name);
2957						dedup_nl.push(&f.name);
2958						nl_width = f.name.len();
2959						alias_exist = true;
2960					} else {
2961						nl_width = 0;
2962					}
2963					if let Vector(Some(long_alias)) = &f.long_alias {
2964						for la in long_alias {
2965							if !$nl_list.contains(&la) {
2966								$nl_list.push(la);
2967								dedup_nl.push(la);
2968								nl_width += la.len();
2969								alias_exist = true;
2970							}
2971						}
2972					}
2973					if alias_exist {
2974						match dedup_nl.len() {
2975							1 => {
2976								nl_width += flag_type_suffix_len(&f.flag_type);
2977							}
2978							x if x > 1 => {
2979								nl_width += match &f.flag_type {
2980									FlagType::Bool => x * 4,
2981									FlagType::String => x * 4 + 9,
2982									FlagType::Int => x * 4 + 6,
2983									FlagType::Float => x * 4 + 8,
2984								};
2985							}
2986							_ => {}
2987						}
2988					}
2989					$nl_columns.push_back(dedup_nl);
2990					$nl_col_width = max(nl_width, $nl_col_width);
2991				}
2992			};
2993		}
2994
2995		/// Add short alias to append_to.
2996		/// It is formatted as "-<s>"
2997		/// example: "-a, -b"
2998		fn add_short_flags_str(append_to: &mut String, s_list: Vec<&char>) {
2999			append_to.push('-');
3000			let mut si = s_list.into_iter();
3001			append_to.push(*si.next().unwrap());
3002			for s in si {
3003				append_to.push_str(", -");
3004				append_to.push(*s);
3005			}
3006		}
3007
3008		/// Return flag type suffix length
3009		fn flag_type_suffix_len(ft: &FlagType) -> usize {
3010			match &ft {
3011				FlagType::Bool => 2,
3012				FlagType::String => 11, // 2 + " <string>"
3013				FlagType::Int => 8,     // 2 + " <int>"
3014				FlagType::Float => 10,  // 2 + " <float>"
3015			}
3016		}
3017
3018		/// Add long alias (following prev) to append to.
3019		/// example: "--a, --b"
3020		fn add_long_flags_str_to_prev_flags(
3021			append_to: &mut String,
3022			nl_iter: std::vec::IntoIter<&String>,
3023		) {
3024			for nl in nl_iter {
3025				append_to.push_str(", --");
3026				append_to.push_str(nl);
3027			}
3028		}
3029
3030		/// Add long alias (main,or formal) to append_to.
3031		fn add_long_flags_str(append_to: &mut String, mut nl_iter: std::vec::IntoIter<&String>) {
3032			append_to.push_str("--");
3033			append_to.push_str(nl_iter.next().unwrap());
3034			add_long_flags_str_to_prev_flags(append_to, nl_iter);
3035		}
3036
3037		/// Add all flags' help string to append_to.
3038		///
3039		/// # Parameters
3040		///
3041		/// - append_to: The string to which the help string is appended.
3042		/// - flags: A vector of Flag whose help string is added.
3043		/// - s_columns: A VecDeque of vectors of short aliases.
3044		/// - nl_columns: A VecDeque of vectors of long aliases.
3045		/// - s_col_width: The width of the short alias column.
3046		/// - nl_col_width: The width of the long alias column.
3047		/// - gap_width: The width of the gap between the two columns.
3048		/// - suffix: The suffix appended to the end of each line.
3049		/// - prefix: The prefix appended to the beginning of each line.
3050		/// - sp: The string to repeat for filling the gap.
3051		fn add_flags_help_str(
3052			mut append_to: String,
3053			flags: &[Flag],
3054			s_columns: &mut std::collections::VecDeque<Vec<&char>>,
3055			nl_columns: &mut std::collections::VecDeque<Vec<&String>>,
3056			s_col_width: usize,
3057			nl_col_width: usize,
3058			gap_width: usize,
3059			suffix: &str,
3060			prefix: &str,
3061			sp: &str,
3062		) -> String {
3063			for f in flags.iter().rev() {
3064				append_to.push_str(prefix);
3065				let s_list = s_columns.pop_front().unwrap();
3066				let nl_list = nl_columns.pop_front().unwrap();
3067				if s_list.is_empty() {
3068					if !nl_list.is_empty() {
3069						append_to.push_str(&sp.repeat(s_col_width));
3070						let prev_help_len = append_to.len();
3071						add_long_flags_str(&mut append_to, nl_list.into_iter());
3072						append_to = add_type_suffix(append_to, &f.flag_type);
3073						let nl_len = append_to.len() - prev_help_len;
3074						append_to = append_to
3075							+ &sp.repeat(nl_col_width + gap_width - nl_len)
3076							+ &f.description
3077							+ suffix;
3078					}
3079				} else {
3080					append_to = append_to + &sp.repeat(s_col_width - (s_list.len() * 4));
3081					add_short_flags_str(&mut append_to, s_list);
3082					if nl_list.is_empty() {
3083						append_to = add_type_suffix(append_to, &f.flag_type)
3084							+ &sp.repeat(4 + nl_col_width)
3085							+ &f.description
3086							+ suffix;
3087					} else {
3088						let prev_help_len = append_to.len();
3089						add_long_flags_str_to_prev_flags(&mut append_to, nl_list.into_iter());
3090						append_to = add_type_suffix(append_to, &f.flag_type);
3091						let nl_len = append_to.len() - prev_help_len - 2;
3092						append_to = append_to
3093							+ &sp.repeat(nl_col_width + gap_width - nl_len)
3094							+ &f.description
3095							+ suffix;
3096					}
3097				}
3098			}
3099			append_to
3100		}
3101
3102		/// Preset of help function (tablize) with deleted duplication
3103		pub fn help_tablize_with_alias_dedup(cmd: &Command, ctx: &Context) -> String {
3104			let mut help = String::new();
3105			let indent_size = 3;
3106			let sp = String::from(" ");
3107			let indent: String = sp.repeat(indent_size);
3108			if let Some(description) = &cmd.description {
3109				help.push_str(description);
3110				help.push_str("\n\n");
3111			}
3112			help = help + "Usage:\n" + &indent + &cmd.usage + "\n";
3113
3114			let flag_num = cmd.l_flags.len() + cmd.c_flags.len() + ctx.common_flags.sum_of_length();
3115			if flag_num > 0 {
3116				let mut nl_col_width = 5;
3117				let mut s_col_width = 1;
3118				help.push_str("\nFlags: \n");
3119
3120				let mut nl_list = Vec::<&String>::new();
3121				let mut s_list = Vec::<&char>::new();
3122				let mut s_columns = std::collections::VecDeque::<Vec<&char>>::with_capacity(flag_num);
3123				let mut nl_columns =
3124					std::collections::VecDeque::<Vec<&String>>::with_capacity(flag_num);
3125				if let Vector(Some(l_flags)) = &cmd.l_flags {
3126					let mut l = l_flags.iter().rev();
3127					if let Some(f) = l.next() {
3128						nl_list.push(&f.name);
3129						let mut nl_width = f.name.len() + 2;
3130						if let Vector(Some(la)) = &f.long_alias {
3131							let mut la: Vec<&String> = la.iter().collect();
3132							nl_width += 4 * la.len();
3133							for l in la.iter() {
3134								nl_width += l.len();
3135							}
3136							nl_list.append(&mut la);
3137						}
3138						nl_width += flag_type_suffix_len(&f.flag_type);
3139						nl_col_width = max(nl_width, nl_col_width);
3140						nl_columns.push_back(nl_list.clone());
3141						if let Vector(Some(sa)) = &f.short_alias {
3142							let mut sa: Vec<&char> = sa.iter().collect();
3143							s_col_width = max(sa.len(), s_col_width);
3144							s_list.append(&mut sa);
3145						}
3146						s_columns.push_back(s_list.clone());
3147						_flag_tablize_dedup!(
3148							l,
3149							nl_col_width,
3150							s_col_width,
3151							nl_list,
3152							s_list,
3153							s_columns,
3154							nl_columns
3155						);
3156					}
3157				}
3158				if let Vector(Some(c_flags)) = &cmd.c_flags {
3159					_flag_tablize_dedup!(
3160						c_flags.iter().rev(),
3161						nl_col_width,
3162						s_col_width,
3163						nl_list,
3164						s_list,
3165						s_columns,
3166						nl_columns
3167					);
3168				}
3169				if let Vector(Some(cfs)) = &ctx.common_flags {
3170					for c_flags in cfs.iter().rev() {
3171						if let Vector(Some(c_flags)) = c_flags {
3172							_flag_tablize_dedup!(
3173								c_flags.iter().rev(),
3174								nl_col_width,
3175								s_col_width,
3176								nl_list,
3177								s_list,
3178								s_columns,
3179								nl_columns
3180							)
3181						}
3182					}
3183				}
3184				drop(s_list);
3185				drop(nl_list);
3186				// help出力
3187				s_col_width *= 4;
3188				let gap_width = 3;
3189				if let Vector(Some(l_flags)) = &cmd.l_flags {
3190					let suffix = "\n";
3191					help = add_flags_help_str(
3192						help,
3193						l_flags,
3194						&mut s_columns,
3195						&mut nl_columns,
3196						s_col_width,
3197						nl_col_width,
3198						gap_width,
3199						suffix,
3200						&indent,
3201						&sp,
3202					)
3203				}
3204
3205				if let Vector(Some(c_flags)) = &cmd.c_flags {
3206					let suffix = match &cmd.sub {
3207						Vector(Some(subs)) if subs.len() > 1 => {
3208							" [common: also available in sub commands under here]\n"
3209						}
3210						Vector(Some(subs)) if !subs.is_empty() => {
3211							" [common: also available in sub command under here]\n"
3212						}
3213						_ => "\n",
3214					};
3215					help = add_flags_help_str(
3216						help,
3217						c_flags,
3218						&mut s_columns,
3219						&mut nl_columns,
3220						s_col_width,
3221						nl_col_width,
3222						gap_width,
3223						suffix,
3224						&indent,
3225						&sp,
3226					)
3227				}
3228
3229				if let Vector(Some(c_flags_list)) = &ctx.common_flags {
3230					let route_without_root = ctx.depth() > ctx.routes.len();
3231					for (index, c_flags) in c_flags_list.iter().enumerate().rev() {
3232						if let Vector(Some(c_flags)) = c_flags {
3233							let mut suffix = sp.clone() + "[common: inherited from ";
3234							if route_without_root {
3235								if index < 1 {
3236									suffix.push_str(&root_str(ctx.exe_path()))
3237								} else {
3238									match ctx.routes.get(index - 1) {
3239										Some(val) => suffix.push_str(val),
3240										None => suffix.push_str("unknown"),
3241									}
3242								}
3243							} else {
3244								match ctx.routes.get(index) {
3245									Some(val) => suffix.push_str(val),
3246									None => suffix.push_str("unknown"),
3247								}
3248							}
3249							suffix.push_str("]\n");
3250
3251							help = add_flags_help_str(
3252								help,
3253								c_flags,
3254								&mut s_columns,
3255								&mut nl_columns,
3256								s_col_width,
3257								nl_col_width,
3258								gap_width,
3259								&suffix,
3260								&indent,
3261								&sp,
3262							);
3263						}
3264					}
3265				}
3266			}
3267
3268			if let Vector(Some(sub_commands)) = &cmd.sub {
3269				help += "\nSub Command";
3270				if sub_commands.len() > 1 {
3271					help.push('s');
3272				}
3273				help += ": \n";
3274
3275				// サブコマンド名の列挙最大長算出
3276				let mut na_max_width: usize = 12;
3277				for sc in sub_commands {
3278					match &sc.alias {
3279						Vector(None) => na_max_width = max(na_max_width, sc.name.len()),
3280						Vector(Some(alias)) => {
3281							na_max_width = max(
3282								na_max_width,
3283								alias
3284									.iter()
3285									.fold(sc.name.len() + 2 * alias.len(), |sum, a| sum + a.len()),
3286							);
3287						}
3288					}
3289				}
3290				na_max_width += 3;
3291
3292				for sc in sub_commands {
3293					let help_pref_len = help.len();
3294					help = help + &indent + &sc.name;
3295					if let Vector(Some(alias)) = &sc.alias {
3296						for a in alias {
3297							help = help + a;
3298						}
3299					}
3300					let sp_num = na_max_width + help_pref_len - help.len();
3301					help = help + &sp.repeat(sp_num);
3302					if let Some(description) = &sc.description {
3303						help.push_str(description);
3304					}
3305					help.push('\n');
3306				}
3307
3308				help.push_str("\nSee '");
3309				if ctx.depth() > 0 {
3310					if ctx.depth() > ctx.routes.len() {
3311						help.push_str(&root_str(ctx.exe_path()));
3312						help.push_str(&sp);
3313					}
3314					if let Vector(Some(routes)) = &ctx.routes {
3315						for route in routes {
3316							help.push_str(route);
3317							help.push_str(&sp);
3318						}
3319					}
3320					help.push_str(&cmd.name);
3321				} else {
3322					let root = if cmd.name.is_empty() {
3323						root_str(ctx.exe_path())
3324					} else {
3325						cmd.name.clone()
3326					};
3327					help.push_str(&root);
3328				}
3329				help.push_str(" <subcommand> --help' for more information");
3330			}
3331
3332			help
3333		}
3334
3335		/// Get root path as string for help
3336		pub fn root_str(exe_path: &str) -> String {
3337			let exe_path = std::path::Path::new(exe_path);
3338			let mut root_string = exe_path
3339				.file_stem()
3340				.unwrap_or(std::ffi::OsStr::new("root"))
3341				.to_str()
3342				.unwrap_or("root")
3343				.to_owned();
3344			if let Some(val) = exe_path.extension() {
3345				match val.to_str() {
3346					Some(val) => root_string = root_string + "[." + val + "]",
3347					None => match std::env::consts::EXE_SUFFIX {
3348						"" => {}
3349						val => root_string = root_string + "[" + val + "]",
3350					},
3351				}
3352			}
3353
3354			root_string
3355		}
3356
3357		#[cfg(test)]
3358		mod test {
3359			use super::super::Command;
3360			use super::help_tablize_with_alias_dedup;
3361			use crate::{
3362				Context, Flag, action_result, checks, copyright, crate_authors, crate_license,
3363				crate_version, done, flags, license, preset_help_command, vector,
3364			};
3365
3366			#[test]
3367			fn presets_help_func_test() {
3368				let act = |cmd: Command, ctx: Context| -> action_result!() {
3369					checks!(cmd, ctx, [error, help, version, license]);
3370					println!("check passed!");
3371					done!()
3372				};
3373				let raw_args = vec!["help".to_owned(), "--help".to_owned()];
3374				let _r = Command::with_all_field(
3375					"root".to_owned(),
3376					Some(act),
3377					crate_authors!().to_owned(),
3378					copyright!(2022, suquiya),
3379					license!(crate_license!().to_owned(),file_path=>"../LICENSE"),
3380					Some(crate_authors!().to_owned()),
3381					"root [subcommand] [options]".to_owned(),
3382					flags!(),
3383					flags!(help, license, authors, copyright, version),
3384					vector![],
3385					crate_version!().to_owned(),
3386					vector![preset_help_command!(help_tablize_with_alias_dedup)],
3387				)
3388				.run_from_args(raw_args);
3389			}
3390		}
3391	}
3392}