multi/
multi.rs

1use combu::{command::presets, done, ActionError, ActionResult, Command, Context, Flag, FlagValue};
2/*
3multi command example.
4We can run as follows:
5```bash
6cargo run --example multi -- a 1 2 3 4 5
715
8cargo run --example multi -- s 1 2 3 4 5
9-13
10```
11 */
12fn main() {
13	let _ = root_command().run_from_args(std::env::args().collect());
14}
15
16fn root_command() -> Command {
17	Command::with_name("multi")
18		.description("root command sample: arg printer")
19		.usage(presets::usage("multi"))
20		.common_flag(Flag::new_bool("help").short_alias('h'))
21		.common_flag(Flag::new_bool("reverse").short_alias('r'))
22		.local_flag(
23			Flag::new_bool("by-char")
24				.short_alias('c')
25				.description("process at char units"),
26		)
27		.action(print_args)
28		.sub_command(add_command())
29		.sub_command(sub_command())
30}
31fn call_help(c: &Context, cur_cmd: &Command) -> Result<ActionResult, ActionError> {
32	println!("{}", presets::func::help(cur_cmd, c));
33	done!()
34}
35fn print_args(current_command: Command, context: Context) -> Result<ActionResult, ActionError> {
36	if called_help(&context, &current_command) {
37		return call_help(&context, &current_command);
38	}
39	let r: bool =
40		context.get_flag_value_of("reverse", &current_command) == Some(FlagValue::Bool(true));
41	let c: bool =
42		context.get_flag_value_of("by-char", &current_command) == Some(FlagValue::Bool(true));
43	let str = {
44		let str = if r && !c {
45			context
46				.args
47				.iter()
48				.rev()
49				.fold(String::new(), |c, arg| c + arg)
50		} else {
51			context.args.iter().fold(String::new(), |c, arg| c + arg)
52		};
53		if c {
54			str.chars().rev().collect::<String>()
55		} else {
56			str
57		}
58	};
59
60	println!("{}", str);
61
62	Ok(ActionResult::Done)
63}
64
65fn called_help(c: &Context, cc: &Command) -> bool {
66	Some(FlagValue::Bool(true)) == c.get_flag_value_of("help", cc)
67}
68
69fn add_command() -> Command {
70	Command::new()
71		.name("add")
72		.alias("a")
73		.action(add_action)
74		.local_flag(Flag::new_bool("detail").short_alias('d'))
75}
76
77fn add_action(cmd: Command, c: Context) -> Result<ActionResult, ActionError> {
78	if called_help(&c, &cmd) {
79		return call_help(&c, &cmd);
80	}
81	let f = |(str, sum), num: f64| (format!("{} {} +", str, num), sum + num);
82	let (mut str, sum): (String, f64) =
83		if c.get_flag_value_of("reverse", &cmd) == Some(FlagValue::Bool(true)) {
84			c.args
85				.iter()
86				.rev()
87				.filter_map(|arg| arg.parse().ok())
88				.fold((String::new(), 0.0), f)
89		} else {
90			c.args
91				.iter()
92				.filter_map(|arg| arg.parse().ok())
93				.fold((String::new(), 0.0), f)
94		};
95	str.pop();
96	str.pop();
97
98	if c.get_flag_value_of("detail", &cmd).unwrap().is_bool_true() {
99		println!("{} = {}", str, sum);
100	} else {
101		println!("{}", sum);
102	}
103	Ok(ActionResult::Done)
104}
105
106fn sub_command() -> Command {
107	Command::new()
108		.name("sub")
109		.alias("s")
110		.action(sub_action)
111		.local_flag(Flag::new_bool("sort").short_alias('s'))
112}
113
114fn sub_action(cmd: Command, c: Context) -> Result<ActionResult, ActionError> {
115	if called_help(&c, &cmd) {
116		return call_help(&c, &cmd);
117	}
118	let f = |(str, sum), (index, num): (usize, f64)| {
119		(
120			format!("{} {} -", str, num),
121			if index < 1 { num } else { sum - num },
122		)
123	};
124	let filter_map_f = |arg: &String| arg.parse().ok();
125	let (mut str, result): (String, f64) =
126		if c.get_flag_value_of("reverse", &cmd) == Some(FlagValue::Bool(true)) {
127			c.args
128				.iter()
129				.rev()
130				.filter_map(filter_map_f)
131				.enumerate()
132				.fold((String::new(), 0.0), f)
133		} else if c.get_flag_value_of("sort", &cmd).unwrap().is_bool_true() {
134			let mut fvec = c.args.iter().filter_map(filter_map_f).collect::<Vec<f64>>();
135			fvec.sort_by(|a, b| a.partial_cmp(b).unwrap());
136			fvec
137				.iter_mut()
138				.enumerate()
139				.fold((String::new(), 0.0), |s, (index, fl)| f(s, (index, *fl)))
140		} else {
141			c.args
142				.iter()
143				.filter_map(filter_map_f)
144				.enumerate()
145				.fold((String::new(), 0.0), f)
146		};
147	str.pop();
148	str.pop();
149
150	println!("{} = {}", str, result);
151
152	Ok(ActionResult::Done)
153}