use std::cell::RefCell;
pub struct Arguments {
args: Vec<Arg>,
operations: Vec<Operation>,
flags: Option<Vec<Flag>>,
}
#[derive(Clone)]
pub struct Operation {
arg: String,
func: RefCell<&'static dyn Fn(&[Arg], &Arguments) -> ()>,
}
impl Operation {
pub fn new(arg: String, func: &'static dyn Fn(&[Arg], &Arguments)) -> Self {
Self {
arg,
func: RefCell::new(func),
}
}
pub fn select(name: &str, ops: &[Operation]) -> Option<Self> {
for op in ops.iter() {
if name == op.arg {
return Some(op.clone());
}
}
None
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Flag {
flag: String,
values: Vec<String>,
}
#[derive(Debug, Clone)]
pub enum ArgType {
OPTION,
VALUE,
FLAG,
}
#[derive(Debug, Clone)]
pub struct Arg {
name: String,
kind: ArgType,
}
impl Arg {
pub fn new(name: String, kind: ArgType) -> Self {
Self { name, kind }
}
pub fn get_name(&self) -> String {
self.name.clone()
}
}
impl Flag {
pub fn new(flag: String, values: Vec<String>) -> Self {
Self { flag, values }
}
pub fn get_name(&self) -> String {
self.flag.clone()
}
}
impl Arguments {
pub fn new() -> Self {
let mut args: Vec<String> = std::env::args().skip(1).collect();
let mut flags = Vec::new();
let option: String = args.remove(0);
flags.push(Arg::new(option, ArgType::OPTION));
for arg in args.iter() {
if arg.find("--").is_some() {
flags.push(Arg::new(arg.clone(), ArgType::FLAG));
} else {
flags.push(Arg::new(arg.clone(), ArgType::VALUE));
}
}
Self {
args: flags,
operations: Vec::new(),
flags: None,
}
}
pub fn invoke_callback(&mut self, flag: &str, func: &'static dyn Fn(&[Arg], &Arguments) -> ()) {
self.operations.push(Operation::new(flag.to_string(), func));
}
pub fn parse(&self) {
let mut flags_index: Vec<usize> = Vec::new();
flags_index.push(0);
for (index, a) in self.args.iter().enumerate() {
if a.name.find("--").is_some() && index != 0 {
flags_index.push(index);
}
}
let slice_args = self.args.as_slice();
for (ind, flag_index) in flags_index.iter().enumerate() {
let flag = &slice_args[*flag_index];
if let Some(mut op) = Operation::select(&flag.name, &self.operations) {
let start: usize = flag_index + 1;
let end: usize = match flags_index.get(ind + 1) {
Some(index) => *index,
None => slice_args.len(),
};
let fun = op.func.get_mut();
fun(&slice_args[start..end], &self);
}
}
}
pub fn get_flag(&self, flag_name: &str) -> Option<Flag> {
match &self.flags {
Some(fs) => {
for flag in fs.iter() {
if flag.get_name() == flag_name {
return Some(flag.clone());
}
println!("flag_name: {}", flag_name);
}
None
}
None => None,
}
}
pub fn get_arg(&self, flag_name: &str) -> Option<Arg> {
for arg in self.args.iter() {
if arg.get_name() == flag_name {
return Some(arg.clone());
}
}
None
}
pub fn has_arg(&self, flag_name: &str) -> bool {
self.get_arg(flag_name).is_some()
}
pub fn get_flags(&self) -> Vec<Arg> {
self.args.clone()
}
}