use crate::cmd::get_os_args;
use std::collections::HashMap;
use std::fmt::Display;
pub struct Args {
pub command: String,
pub sub_command: String,
pub option: Vec<String>,
pub data: HashMap<String, Vec<String>>,
pub raw: Vec<String>,
}
impl Args {
pub fn get_data(&self, key: &str) -> Option<&Vec<String>> {
if let Some(value) = self.get_value(vec![key]) {
return Some(value);
}
None
}
pub fn get_value(&self, keys: Vec<&str>) -> Option<&Vec<String>> {
if self.data.is_empty() {
return None;
}
for key in keys {
if self.data.contains_key(key) {
return self.data.get(key);
}
}
None
}
pub fn get_value_string(&self, keys: Vec<&str>) -> String {
let mut value = String::new();
if let Some(v) = self.get_value(keys) {
value = String::from(v.join(" ").trim());
}
value
}
pub fn get_value_string_option(&self, keys: Vec<&str>) -> Option<String> {
if let Some(v) = self.get_value(keys) {
let value = String::from(v.join(" ").trim());
return Some(value);
}
None
}
pub fn get_value_i32(&self, keys: Vec<&str>) -> i32 {
if let Some(v) = self.get_value_string_option(keys) {
return v.parse::<i32>().unwrap();
}
0
}
pub fn get_value_bool(&self, keys: Vec<&str>) -> bool {
return if let Some(v) = self.get_value_string_option(keys) {
v.parse::<bool>().unwrap()
} else {
true
};
}
pub fn contain_opts(&self, keys: Vec<&str>) -> bool {
for key in keys {
if self.option.contains(&String::from(key)) {
return true;
}
}
false
}
pub fn from_args(args: &Vec<String>) -> Args {
let mut command = String::new(); let mut sub_command = String::new(); let mut option = Vec::new();
let mut data: HashMap<String, Vec<String>> = HashMap::new();
let mut count = 0;
let mut last_opt = String::new(); let mut last_value: Vec<String> = Vec::new();
for arg in args {
let mut long_opt: i32 = -1;
let mut shot_opt: i32 = -1;
if let Some(vi) = arg.find("--") {
long_opt = vi as i32;
};
if let Some(vi) = arg.find("-") {
shot_opt = vi as i32;
};
let is_not_opt = shot_opt != 0;
if count == 0 && is_not_opt {
command = String::from(arg);
} else if count == 1 && sub_command.len() == 0 && is_not_opt {
sub_command = String::from(arg);
} else {
if long_opt == 0 {
let (_, opt) = arg.split_at(2);
if !last_value.is_empty() && !last_opt.is_empty() {
if !data.contains_key(last_opt.as_str()) {
data.insert(last_opt.clone(), last_value);
}
last_value = Vec::new();
}
last_opt = String::from(opt);
option.push(String::from(&last_opt));
} else if shot_opt == 0 {
let (_, opt) = arg.split_at(1);
if !last_value.is_empty() && !last_opt.is_empty() {
if !data.contains_key(last_opt.as_str()) {
data.insert(last_opt.clone(), last_value);
}
last_value = Vec::new();
}
for by in opt.chars() {
last_opt = String::from(by);
option.push(String::from(&last_opt));
}
} else {
last_value.push(String::from(arg));
}
}
count += 1;
}
if !last_value.is_empty() && !last_opt.is_empty() {
if !data.contains_key(last_opt.as_str()) {
data.insert(last_opt.clone(), last_value);
}
}
Args {
command,
sub_command,
option,
data,
raw: args.to_vec(),
}
}
pub fn from_os() -> Args {
Args::from_args(&get_os_args())
}
pub fn from_str(param: &str) -> Args {
let queue = param.split(' ').collect();
let args: Vec<String> = into_string_vec(queue);
Args::from_args(&args)
}
}
pub trait ArgsFromOs {
fn new() -> Args;
}
impl ArgsFromOs for Args {
fn new() -> Args {
Args::from_os()
}
}
pub trait ArgsNew<T> {
fn new(param: T) -> Self;
}
impl ArgsNew<&Vec<String>> for Args {
fn new(param: &Vec<String>) -> Self {
Args::from_args(¶m)
}
}
impl<T> ArgsNew<Vec<T>> for Args
where
T: Display,
{
fn new(param: Vec<T>) -> Self {
let args: Vec<String> = into_string_vec(param);
Args::from_args(&args)
}
}
fn into_string_vec<T>(args: Vec<T>) -> Vec<String>
where
T: Display,
{
let mut value: Vec<String> = Vec::new();
for arg in args {
value.push(format!("{}", arg));
}
value
}