1use combu::{
2 Command, Context, Flag, FlagValue, action_result, alias, checks, commands, copyright,
3 crate_authors, crate_description, crate_name, crate_version, done, flags, license, output_help,
4 vector::flag::FlagSearch,
5};
6
7use crate::pwgen;
8
9pub fn new() -> Command {
10 Command::with_all_field(
11 crate_name!().into(),
12 Some(act),
13 crate_authors!().into(),
14 copyright!(from_crate, 2022),
15 license!("MIT License",file_path=>"../LICENSE"),
16 Some(crate_description!().into()),
17 "rara [OPTIONS]".into(),
18 flags![
19 [
20 [length]=>[>int?20,="password length option. default: 20",-l,--len]
21 ],
22 [
23 [number]=>[>int?7,="password number option. default: 7",-n,--num]
24 ],
25 [
26 [include]=>[>String,="chooses chars indicate type password include. Types are alphabet(a),number(n),symbol(s) and default(d). You can specify multiple chars(ex: an). default=ans",-i,?"d"]
27 ],
28 [
29 [exclude]=>[
30 >String?"",
31 ="Password will generate without chars that is specidied by this flag",-e
32 ]
33 ],
34 [
35 [custom]=>[
36 >String?"",
37 ="Password will generate with only chars that is specidied by this flag. this option is inputted, include option is disabled. default: disable",-c,-m,--cstm
38 ]
39 ]
40 ],
41 flags!(help, version, license),
42 alias!(),
43 crate_version!().into(),
44 commands!(),
45 )
46}
47
48fn act(cmd: Command, ctx: Context) -> action_result!() {
49 checks!(cmd, ctx, [error, help, version, license]);
50 parse_ctx_and_run(cmd, ctx)
51}
52
53pub fn parse_ctx_and_run(cmd: Command, ctx: Context) -> action_result!() {
54 let l = {
55 let lf = cmd.l_flags.find("length").unwrap();
56 match ctx
57 .get_flag_value_of(&lf.name, &cmd)
58 .unwrap()
59 .get_int_unwrap()
60 {
61 x if x > 0 => x,
62 _ => lf.default_value.get_int_unwrap(),
63 }
64 } as usize;
65 let n = {
66 let nf = cmd.l_flags.find("number").unwrap();
67 match ctx
68 .get_flag_value_of(&nf.name, &cmd)
69 .unwrap()
70 .get_int_unwrap()
71 {
72 x if x > 0 => x,
73 _ => nf.default_value.get_int_unwrap(),
74 }
75 } as usize;
76 let include_str = match ctx
77 .get_flag_value_of("custom", &cmd)
78 .unwrap()
79 .get_string_value()
80 {
81 x if x.is_empty() => {
82 let include = ctx
83 .get_flag_value_of("include", &cmd)
84 .unwrap()
85 .get_string_value();
86 if include.contains('d') {
87 String::from(pwgen::str_list::get_alphabets())
88 + pwgen::str_list::get_numbers()
89 + pwgen::str_list::get_symbols()
90 } else {
91 let mut str = String::new();
92 if include.contains('a') {
93 str += pwgen::str_list::get_alphabets();
94 }
95 if include.contains('n') {
96 str += pwgen::str_list::get_numbers();
97 }
98 if include.contains('s') {
99 str += pwgen::str_list::get_symbols();
100 }
101 str
102 }
103 }
104 x => x,
105 };
106
107 let include_chars: Vec<char> = match ctx.get_inputted_local_flag_value_of("exclude") {
108 None | Some(FlagValue::None) => include_str.chars().collect(),
109 Some(FlagValue::String(val)) if val.is_empty() => include_str.chars().collect(),
110 Some(ex) => {
111 let ex = ex.get_string_value();
112 include_str.chars().filter(|c| !ex.contains(*c)).collect()
113 }
114 };
115
116 if include_chars.is_empty() {
117 println!("No char can use in password!\r\n");
118 output_help!(&cmd, &ctx);
119 return done!();
120 }
121
122 let password_list = pwgen::pwgen(l, n, &include_chars);
123
124 println!("---generated passwords begin---");
125 for password in password_list {
126 println!("{password}");
127 }
128 println!("---generated passwords end---");
129
130 done!()
131}