1use std::cell::RefCell;
3use std::rc::Rc;
4use std::boxed::Box;
5
6pub struct Arguments {
7 args: Vec<Arg>,
8 operations: Vec<Operation>,
9 flags: Option<Vec<Flag>>,
10 }
12#[derive(Clone)]
13pub struct Operation {
14 arg: String,
15 func: Rc<RefCell<Box<dyn Fn(&[Arg], &Arguments) -> ()>>>,
16}
17impl Operation {
19 pub fn new<F>(arg: String, func: F) -> Self
20 where F: Fn(&[Arg], &Arguments),
21 F: 'static
22 {
23 Self {
24 arg,
25 func: Rc::new(RefCell::new(Box::new(func))),
26 }
27 }
28 pub fn select(name: &str, ops: &[Operation]) -> Option<Self> {
29 for op in ops.iter() {
30 if name == op.arg {
31 return Some(op.clone());
32 }
33 }
34 None
35 }
36}
37#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct Flag {
39 flag: String,
40 values: Vec<Arg>,
41}
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub enum ArgType {
44 OPTION,
45 VALUE,
46 FLAG,
47}
48#[derive(Debug, Clone, PartialEq, Eq)]
50pub struct Arg {
51 name: String,
52 kind: ArgType,
53}
54
55impl Arg {
56 pub fn new(name: String, kind: ArgType) -> Self {
57 Self { name, kind }
58 }
59 pub fn get_name(&self) -> String {
60 self.name.clone()
61 }
62}
63impl Flag {
65 pub fn new(flag: String, values: Vec<Arg>) -> Self {
66 Self { flag, values }
67 }
68 pub fn get_name(&self) -> String {
69 self.flag.clone()
70 }
71 pub fn extend_from_slice(&mut self, slice: &[Arg]){
72 self.values.extend_from_slice(slice);
73 }
74 pub fn get_values(&self) -> &[Arg]{
75 self.values.as_slice()
76 }
77 pub fn get_value_vec(&self) -> Vec<Arg>{
78 self.values.clone()
79 }
80}
81impl Arguments {
85 pub fn new() -> Self {
87 let mut args: Vec<String> = std::env::args().skip(1).collect();
88 if args.len() == 0 {
89 return Self {args: Vec::new(), operations: Vec::new(), flags: None}
90 }
91 let mut arglist = Vec::new();
92 let mut flags = Vec::new();
93 let option: String = args.remove(0);
94 let reop = option.clone();
95 arglist.push(Arg::new(option, ArgType::OPTION));
96 flags.push(Flag::new(reop, Vec::new()));
97 for arg in args.iter() {
98 if arg.find("--").is_some() {
99 arglist.push(Arg::new(arg.clone(), ArgType::FLAG));
100 flags.push(Flag::new(arg.clone(), Vec::new()));
101 } else {
102 arglist.push(Arg::new(arg.clone(), ArgType::VALUE));
103 }
104 }
105 Self {
106 args: arglist,
107 operations: Vec::new(),
108 flags: Some(flags),
109 }
110 }
111 pub fn invoke_callback<F>(&mut self, flag: &str, func: F)
113 where F: Fn(&[Arg], &Arguments),
114 F: 'static
115 {
116 self.operations.push(Operation::new(flag.to_string(), func));
117 }
118 pub fn parse(&mut self) {
120 let mut flags_index: Vec<usize> = Vec::new();
124 flags_index.push(0);
125 for (index, a) in self.args.iter().enumerate() {
126 if a.name.find("--").is_some() && index != 0 {
127 flags_index.push(index);
128 }
129 }
130 let slice_args = self.args.as_slice();
131 for (ind, flag_index) in flags_index.iter().enumerate() {
132 let flag = &slice_args[*flag_index];
133 let start: usize = *flag_index + 1;
134 let end: usize = match flags_index.get(ind + 1) {
135 Some(index) => *index,
136 None => slice_args.len(),
137 };
138 let f = self.get_flag_index(&flag.name).expect("flag parsing error");
139 let slice = self.flags.as_mut().unwrap().as_mut_slice();
140 slice[f].extend_from_slice(&slice_args[start..end]);
141
142 }
143 for flag in self.flags.as_ref().unwrap().iter(){
144 if let Some(op) = Operation::select(&flag.get_name(), &self.operations){
145 let fun = op.func.borrow();
146 fun(flag.get_values(), &self);
147 }
148 }
149 }
150 pub fn get_flag(&self, flag_name: &str) -> Option<Flag> {
152 match &self.flags {
153 Some(fs) => {
154 for flag in fs.iter() {
155 if flag.get_name() == flag_name {
156 return Some(flag.clone());
157 } }
158 None
159 }
160 None => None,
161 }
162 }
163 pub fn get_flag_index(&self, flag_name: &str) -> Option<usize>{
164 match &self.flags {
165 Some(fs) => {
166 for (index, flag) in fs.iter().enumerate() {
167 if flag.get_name() == flag_name {
168 return Some(index);
169 }
170 }
171 None
172 }
173 None => None,
174 }
175 }
176 pub fn get_arg(&self, flag_name: &str) -> Option<Arg> {
178 for arg in self.args.iter() {
179 if arg.get_name() == flag_name {
180 return Some(arg.clone());
181 }
182 }
183 None
184 }
185 pub fn has_arg(&self, flag_name: &str) -> bool {
187 self.get_arg(flag_name).is_some()
188 }
189 pub fn get_flags(&self) -> Vec<Arg> {
190 self.args.clone()
191 }
192}