use std::collections::HashMap;
pub fn parse_options(argv: &[String]) -> Vec<String> {
let mut options: Vec<String> = Vec::new();
for arg in argv {
if arg.starts_with('-') {
if arg == "-" {
continue;
}
if is_double_hyphen_option(&arg[..]) {
break;
}
if is_definition_option(&arg[..]) {
let option_definition_vec = get_definition_parts(&arg[..]);
let option = &option_definition_vec[0];
options.push(option.to_string());
} else {
options.push(arg.clone());
}
}
}
options
}
pub fn parse_definitions(argv: &[String]) -> HashMap<String, String> {
let mut definitions: HashMap<String, String> = HashMap::new();
for arg in argv {
if arg.starts_with('-') {
if is_double_hyphen_option(&arg[..]) {
break;
}
if is_definition_option(&arg[..]) {
let option_definition_vec = get_definition_parts(&arg[..]);
let option = &option_definition_vec[0];
let definition = &option_definition_vec[1];
definitions.insert(option.to_string(), definition.to_string());
}
}
}
definitions
}
pub fn parse_first_arg(arg_list: &[String]) -> Option<String> {
match arg_list.get(1) {
Some(x) => Some(x.clone()),
None => None,
}
}
pub fn parse_last_arg(arg_list: &[String]) -> Option<String> {
if arg_list.len() > 1 {
match arg_list.get(arg_list.len() - 1) {
Some(x) => Some(x.clone()),
None => None,
}
} else {
None }
}
pub fn parse_double_hyphen_args(arg_list: &[String]) -> Option<Vec<String>> {
for (index, value) in arg_list.iter().enumerate() {
if is_double_hyphen_option(&value[..]) {
let sub_vec = arg_list[(index + 1)..arg_list.len()].to_vec();
if !sub_vec.is_empty() {
return Some(sub_vec);
} else {
return None;
}
}
}
None
}
pub fn parse_mops(arg_list: &[String]) -> Option<Vec<String>> {
let mut return_vec: Vec<String> = Vec::new();
for arg in arg_list {
if !arg.starts_with("--") {
let t = &arg[..];
for x in t.chars() {
if x != '-' {
let option_string = format!("-{}", x); return_vec.push(option_string);
}
}
}
}
if return_vec.is_empty() {
None
} else {
Some(return_vec)
}
}
pub fn is_definition_option(needle: &str) -> bool {
needle.contains('=')
}
pub fn is_double_hyphen_option(needle: &str) -> bool {
needle == "--"
}
pub fn is_mops_option(needle: &str) -> bool {
needle.starts_with('-') && !needle.starts_with("--") && needle.len() > 2
}
pub fn get_definition_parts(needle: &str) -> Vec<String> {
let opt_def: Vec<_> = needle.split('=').collect();
vec![String::from(opt_def[0]), String::from(opt_def[1])]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn function_parse_options() {
let test_vec = vec![
String::from("tester"),
String::from("subcommand"),
String::from("-o"),
String::from("spacedefinition"),
String::from("--longoption"),
String::from("-"), String::from("--defoption=equaldefinition"),
String::from("--"),
String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
];
let expected_vec = vec![
String::from("-o"),
String::from("--longoption"),
String::from("--defoption"),
];
assert!(parse_options(&test_vec) == expected_vec);
}
#[test]
fn function_parse_options_no_options() {
let test_vec = vec![
String::from("tester"),
String::from("subcommand"),
String::from("-"), String::from("spacedefinition"),
String::from("--"),
String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
];
let expected_vec: Vec<String> = vec![];
assert!(parse_options(&test_vec) == expected_vec);
}
#[test]
fn function_parse_definitions_single_def() {
let test_vec = vec![
String::from("tester"),
String::from("subcommand"),
String::from("-o"),
String::from("spacedefinition"),
String::from("--longoption"),
String::from("--defoption=equaldefinition"),
String::from("--"),
String::from("--output=filepath"), String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
];
let mut expected_hm = HashMap::new();
expected_hm.insert("--defoption".to_string(), "equaldefinition".to_string());
assert_eq!(parse_definitions(&test_vec), expected_hm);
}
#[test]
fn function_parse_definitions_multi_def() {
let test_vec = vec![
String::from("tester"),
String::from("subcommand"),
String::from("-o"),
String::from("spacedefinition"),
String::from("--longoption"),
String::from("--defoption=equaldefinition"),
String::from("--another=anotherdef"),
String::from("--"),
String::from("--output=filepath"), String::from("--afterdoublehyphen"), String::from("-x"), String::from("lastpos"),
];
let mut expected_hm = HashMap::new();
expected_hm.insert("--defoption".to_string(), "equaldefinition".to_string());
expected_hm.insert("--another".to_string(), "anotherdef".to_string());
assert_eq!(parse_definitions(&test_vec), expected_hm);
}
#[test]
fn function_parse_first_arg() {
let test_vec = vec![
String::from("test"),
String::from("subcmd"),
String::from("arg"),
];
assert_eq!(parse_first_arg(&test_vec), Some(String::from("subcmd")));
}
#[test]
fn function_parse_first_arg_executable_only() {
let test_vec = vec![String::from("test")];
assert_eq!(parse_first_arg(&test_vec), None);
}
#[test]
fn function_parse_last_arg() {
let test_vec = vec![
String::from("test"),
String::from("subcmd"),
String::from("arg"),
];
assert_eq!(parse_last_arg(&test_vec), Some(String::from("arg")));
}
#[test]
fn function_parse_last_arg_executable_only() {
let test_vec = vec![String::from("test")];
assert_eq!(parse_last_arg(&test_vec), None);
}
#[test]
fn function_parse_double_hyphen_args() {
let test_vec = vec![
String::from("test"),
String::from("-o"),
String::from("path"),
String::from("--"),
String::from("--this"),
String::from("--that"),
];
let expected_vec = vec![String::from("--this"), String::from("--that")];
assert_eq!(parse_double_hyphen_args(&test_vec), Some(expected_vec));
}
#[test]
fn function_parse_double_hyphen_args_no_post_args() {
let test_vec = vec![
String::from("test"),
String::from("-o"),
String::from("path"),
String::from("--"),
];
assert_eq!(parse_double_hyphen_args(&test_vec), None);
}
#[test]
fn function_parse_double_hyphen_args_no_double_hyphen() {
let test_vec = vec![
String::from("test"),
String::from("-o"),
String::from("path"),
];
assert_eq!(parse_double_hyphen_args(&test_vec), None);
}
#[test]
fn function_parse_mops() {
let test_vec = vec![
String::from("--lng"),
String::from("-hij"),
String::from("-o"),
];
let expected_vec = vec![
String::from("-h"),
String::from("-i"),
String::from("-j"),
String::from("-o"),
];
assert_eq!(parse_mops(&test_vec), Some(expected_vec));
}
#[test]
fn function_parse_mops_without_mops() {
let test_vec = vec![
String::from("--lng"),
String::from("--hij"),
String::from("--output"),
];
assert_eq!(parse_mops(&test_vec), None);
}
#[test]
fn function_is_definition_option_true() {
let true_defintion = "--option=definition";
assert_eq!(is_definition_option(true_defintion), true);
}
#[test]
fn function_is_definition_option_false() {
let false_definition = "--option";
assert_eq!(is_definition_option(false_definition), false);
}
#[test]
fn function_get_definition_parts() {
let definition_string = "--option=definition";
let expected: Vec<String> = vec![String::from("--option"), String::from("definition")];
assert!(get_definition_parts(definition_string) == expected);
}
#[test]
fn function_is_double_hyphen_option_true() {
let true_definition = "--";
assert_eq!(is_double_hyphen_option(true_definition), true);
}
#[test]
fn function_is_double_hyphen_option_false() {
let false_definition_1 = "--help";
let false_definition_2 = "-s";
let false_definition_3 = "subcmd";
assert_eq!(is_double_hyphen_option(false_definition_1), false);
assert_eq!(is_double_hyphen_option(false_definition_2), false);
assert_eq!(is_double_hyphen_option(false_definition_3), false);
}
#[test]
fn function_is_mops_option() {
let true_definition = "-mpn";
let false_definition_1 = "-o";
let false_definition_2 = "--output";
let false_definition_3 = "command";
let false_definition_4 = "--";
let false_definition_5 = "-";
assert_eq!(is_mops_option(true_definition), true);
assert_eq!(is_mops_option(false_definition_1), false);
assert_eq!(is_mops_option(false_definition_2), false);
assert_eq!(is_mops_option(false_definition_3), false);
assert_eq!(is_mops_option(false_definition_4), false);
assert_eq!(is_mops_option(false_definition_5), false);
}
}