1use std::collections::HashMap;
7
8pub fn parse_options(argv: &[String]) -> Vec<String> {
10 let mut options: Vec<String> = Vec::new();
11 for arg in argv {
12 if arg.starts_with('-') {
13 if arg == "-" {
17 continue;
18 }
19 if is_double_hyphen_option(&arg[..]) {
24 break;
25 }
26 if is_definition_option(&arg[..]) {
29 let option_definition_vec = get_definition_parts(&arg[..]);
30 let option = &option_definition_vec[0];
31 options.push(option.to_string());
32 } else {
33 options.push(arg.clone());
34 }
35 }
36 }
37
38 options
39}
40
41pub fn parse_definitions(argv: &[String]) -> HashMap<String, String> {
43 let mut definitions: HashMap<String, String> = HashMap::new();
44 for arg in argv {
45 if arg.starts_with('-') {
46 if is_double_hyphen_option(&arg[..]) {
50 break;
51 }
52 if is_definition_option(&arg[..]) {
55 let option_definition_vec = get_definition_parts(&arg[..]);
56 let option = &option_definition_vec[0];
57 let definition = &option_definition_vec[1];
58 definitions.insert(option.to_string(), definition.to_string());
59 }
60 }
61 }
62
63 definitions
64}
65
66pub fn parse_first_arg(arg_list: &[String]) -> Option<String> {
69 match arg_list.get(1) {
70 Some(x) => Some(x.clone()),
71 None => None,
72 }
73}
74
75pub fn parse_last_arg(arg_list: &[String]) -> Option<String> {
78 if arg_list.len() > 1 {
79 match arg_list.get(arg_list.len() - 1) {
80 Some(x) => Some(x.clone()),
81 None => None,
82 }
83 } else {
84 None }
86}
87
88pub fn parse_double_hyphen_args(arg_list: &[String]) -> Option<Vec<String>> {
91 for (index, value) in arg_list.iter().enumerate() {
92 if is_double_hyphen_option(&value[..]) {
93 let sub_vec = arg_list[(index + 1)..arg_list.len()].to_vec();
94 if !sub_vec.is_empty() {
95 return Some(sub_vec);
96 } else {
97 return None;
98 }
99 }
100 }
101
102 None
103}
104
105pub fn parse_mops(arg_list: &[String]) -> Option<Vec<String>> {
111 let mut return_vec: Vec<String> = Vec::new();
112
113 for arg in arg_list {
115 if !arg.starts_with("--") {
116 let t = &arg[..];
118 for x in t.chars() {
119 if x != '-' {
121 let option_string = format!("-{}", x); return_vec.push(option_string);
124 }
125 }
126 }
127 }
128
129 if return_vec.is_empty() {
131 None
132 } else {
133 Some(return_vec)
134 }
135}
136
137pub fn is_definition_option(needle: &str) -> bool {
143 needle.contains('=')
144}
145
146pub fn is_double_hyphen_option(needle: &str) -> bool {
151 needle == "--"
152}
153
154pub fn is_mops_option(needle: &str) -> bool {
156 needle.starts_with('-') && !needle.starts_with("--") && needle.len() > 2
158}
159
160pub fn get_definition_parts(needle: &str) -> Vec<String> {
166 let opt_def: Vec<_> = needle.split('=').collect();
167 vec![String::from(opt_def[0]), String::from(opt_def[1])]
168}
169
170#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[test]
176 fn function_parse_options() {
177 let test_vec = vec![
178 String::from("tester"),
179 String::from("subcommand"),
180 String::from("-o"),
181 String::from("spacedefinition"),
182 String::from("--longoption"),
183 String::from("-"), String::from("--defoption=equaldefinition"),
185 String::from("--"),
186 String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
189 ];
190
191 let expected_vec = vec![
192 String::from("-o"),
193 String::from("--longoption"),
194 String::from("--defoption"),
195 ];
196
197 assert!(parse_options(&test_vec) == expected_vec);
198 }
199
200 #[test]
201 fn function_parse_options_no_options() {
202 let test_vec = vec![
203 String::from("tester"),
204 String::from("subcommand"),
205 String::from("-"), String::from("spacedefinition"),
207 String::from("--"),
208 String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
211 ];
212
213 let expected_vec: Vec<String> = vec![];
214
215 assert!(parse_options(&test_vec) == expected_vec);
216 }
217
218 #[test]
219 fn function_parse_definitions_single_def() {
220 let test_vec = vec![
221 String::from("tester"),
222 String::from("subcommand"),
223 String::from("-o"),
224 String::from("spacedefinition"),
225 String::from("--longoption"),
226 String::from("--defoption=equaldefinition"),
227 String::from("--"),
228 String::from("--output=filepath"), String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
232 ];
233
234 let mut expected_hm = HashMap::new();
235 expected_hm.insert("--defoption".to_string(), "equaldefinition".to_string());
236
237 assert_eq!(parse_definitions(&test_vec), expected_hm);
238 }
239
240 #[test]
241 fn function_parse_definitions_multi_def() {
242 let test_vec = vec![
243 String::from("tester"),
244 String::from("subcommand"),
245 String::from("-o"),
246 String::from("spacedefinition"),
247 String::from("--longoption"),
248 String::from("--defoption=equaldefinition"),
249 String::from("--another=anotherdef"),
250 String::from("--"),
251 String::from("--output=filepath"), String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
255 ];
256
257 let mut expected_hm = HashMap::new();
258 expected_hm.insert("--defoption".to_string(), "equaldefinition".to_string());
259 expected_hm.insert("--another".to_string(), "anotherdef".to_string());
260
261 assert_eq!(parse_definitions(&test_vec), expected_hm);
262 }
263
264 #[test]
265 fn function_parse_first_arg() {
266 let test_vec = vec![
267 String::from("test"),
268 String::from("subcmd"),
269 String::from("arg"),
270 ];
271 assert_eq!(parse_first_arg(&test_vec), Some(String::from("subcmd")));
272 }
273
274 #[test]
275 fn function_parse_first_arg_executable_only() {
276 let test_vec = vec![String::from("test")];
277 assert_eq!(parse_first_arg(&test_vec), None);
278 }
279
280 #[test]
281 fn function_parse_last_arg() {
282 let test_vec = vec![
283 String::from("test"),
284 String::from("subcmd"),
285 String::from("arg"),
286 ];
287 assert_eq!(parse_last_arg(&test_vec), Some(String::from("arg")));
288 }
289
290 #[test]
291 fn function_parse_last_arg_executable_only() {
292 let test_vec = vec![String::from("test")];
293 assert_eq!(parse_last_arg(&test_vec), None);
294 }
295
296 #[test]
297 fn function_parse_double_hyphen_args() {
298 let test_vec = vec![
299 String::from("test"),
300 String::from("-o"),
301 String::from("path"),
302 String::from("--"),
303 String::from("--this"),
304 String::from("--that"),
305 ];
306 let expected_vec = vec![String::from("--this"), String::from("--that")];
307 assert_eq!(parse_double_hyphen_args(&test_vec), Some(expected_vec));
308 }
309
310 #[test]
311 fn function_parse_double_hyphen_args_no_post_args() {
312 let test_vec = vec![
313 String::from("test"),
314 String::from("-o"),
315 String::from("path"),
316 String::from("--"),
317 ];
318 assert_eq!(parse_double_hyphen_args(&test_vec), None);
319 }
320
321 #[test]
322 fn function_parse_double_hyphen_args_no_double_hyphen() {
323 let test_vec = vec![
324 String::from("test"),
325 String::from("-o"),
326 String::from("path"),
327 ];
328 assert_eq!(parse_double_hyphen_args(&test_vec), None);
329 }
330
331 #[test]
332 fn function_parse_mops() {
333 let test_vec = vec![
334 String::from("--lng"),
335 String::from("-hij"),
336 String::from("-o"),
337 ];
338
339 let expected_vec = vec![
341 String::from("-h"),
342 String::from("-i"),
343 String::from("-j"),
344 String::from("-o"),
345 ];
346
347 assert_eq!(parse_mops(&test_vec), Some(expected_vec));
348 }
349
350 #[test]
351 fn function_parse_mops_without_mops() {
352 let test_vec = vec![
353 String::from("--lng"),
354 String::from("--hij"),
355 String::from("--output"),
356 ];
357
358 assert_eq!(parse_mops(&test_vec), None);
359 }
360
361 #[test]
362 fn function_is_definition_option_true() {
363 let true_defintion = "--option=definition";
364 assert_eq!(is_definition_option(true_defintion), true);
365 }
366
367 #[test]
368 fn function_is_definition_option_false() {
369 let false_definition = "--option";
370 assert_eq!(is_definition_option(false_definition), false);
371 }
372
373 #[test]
374 fn function_get_definition_parts() {
375 let definition_string = "--option=definition";
376 let expected: Vec<String> = vec![String::from("--option"), String::from("definition")];
377 assert!(get_definition_parts(definition_string) == expected);
378 }
379
380 #[test]
381 fn function_is_double_hyphen_option_true() {
382 let true_definition = "--";
383 assert_eq!(is_double_hyphen_option(true_definition), true);
384 }
385
386 #[test]
387 fn function_is_double_hyphen_option_false() {
388 let false_definition_1 = "--help";
389 let false_definition_2 = "-s";
390 let false_definition_3 = "subcmd";
391 assert_eq!(is_double_hyphen_option(false_definition_1), false);
392 assert_eq!(is_double_hyphen_option(false_definition_2), false);
393 assert_eq!(is_double_hyphen_option(false_definition_3), false);
394 }
395
396 #[test]
397 fn function_is_mops_option() {
398 let true_definition = "-mpn";
399 let false_definition_1 = "-o";
400 let false_definition_2 = "--output";
401 let false_definition_3 = "command";
402 let false_definition_4 = "--";
403 let false_definition_5 = "-";
404
405 assert_eq!(is_mops_option(true_definition), true);
406 assert_eq!(is_mops_option(false_definition_1), false);
407 assert_eq!(is_mops_option(false_definition_2), false);
408 assert_eq!(is_mops_option(false_definition_3), false);
409 assert_eq!(is_mops_option(false_definition_4), false);
410 assert_eq!(is_mops_option(false_definition_5), false);
411 }
412}