use std::env;
use std::collections::HashMap;
use command::Command;
use flag::Flag;
use show_help_tips;
#[derive(Debug)]
pub struct Parser {
args: Vec<String>,
command: Option<Command>,
flags: HashMap<String, Flag>
}
impl Parser {
pub fn new() -> Parser {
let mut args = env::args().collect::<Vec<String>>();
args.remove(0);
let mut parser = Parser {
args: args,
command: None,
flags: HashMap::new()
};
parser.parse();
parser
}
pub fn get_command(&self, name: &str) -> Option<Command> {
if self.command.is_none() || self.command.as_ref().unwrap().get_name() != name {
None
} else {
self.command.clone()
}
}
pub fn get_unknown_command(&self) -> Command {
self.command.clone().unwrap()
}
pub fn get_flag(&self, name: &str) -> Option<Flag> {
match self.flags.get(name) {
Some(flag) => Some(flag.clone()),
None => None
}
}
pub fn no_args(&self) -> bool {
self.args.is_empty()
}
pub fn has_flag(&self) -> bool {
! self.flags.is_empty()
}
pub fn no_command(&self) -> bool {
self.command.is_none()
}
fn is_command(&self) -> bool {
! self.args.is_empty() && ! is_flag(self.args.get(0).unwrap())
}
fn parse(&mut self) {
if ! self.args.is_empty() {
if self.is_command() {
self.command = Some(parse_command(&self.args));
} else {
self.flags = parse_flags(&self.args);
}
}
}
}
fn is_flag(arg: &str) -> bool {
arg.starts_with('-')
}
fn parse_command(args: &[String]) -> Command {
let mut command = Command::new(args.first().unwrap().clone());
if args.len() > 1 {
for (index, arg) in args[1..].iter().enumerate() {
if is_flag(arg) {
command.set_flags(parse_flags(&args[(index+1)..]));
} else {
command.add_value(arg.clone());
}
}
}
command
}
fn parse_flags(args: &[String]) -> HashMap<String, Flag> {
let mut flags = HashMap::new();
let mut prev_name: Option<String> = None;
let len = args.len();
for (index, arg) in args.iter().enumerate() {
if arg.starts_with('-') {
if prev_name.is_some() {
let name = prev_name.take().unwrap();
flags.insert(name.clone(), Flag::new(name.clone(), None));
}
if index + 1 == len {
flags.insert(arg.clone(), Flag::new(arg.clone(), None));
} else {
prev_name = Some(arg.clone());
}
} else {
if prev_name.is_some() {
let name = prev_name.take().unwrap();
flags.insert(name.clone(), Flag::new(name.clone(), Some(arg.clone())));
} else {
invalid_arguments();
}
}
}
flags
}
fn invalid_arguments() {
errors!("invalid arguments");
show_help_tips();
}