pub struct Parser {
flags: Vec<Flag>,
accept_flag_option: bool,
}
impl Parser {
pub fn new() -> Self {
Self {
flags: vec![],
accept_flag_option: false,
}
}
#[allow(dead_code)]
pub fn clear(&mut self) {
*self = Self::new();
}
pub fn parse_from_vec(&mut self, source: &Vec<impl AsRef<str>>) -> Vec<Flag> {
for item in source {
let should_break = self.find_word_variant(item.as_ref());
if should_break {
return std::mem::take(&mut self.flags);
}
}
std::mem::take(&mut self.flags)
}
fn find_word_variant(&mut self, word: &str) -> bool {
if !self.accept_flag_option && !word.starts_with('-') {
self.flags.push(Flag::argument(word))
} else {
if self.accept_flag_option {
self.flags.last_mut().unwrap().option = word.to_string();
self.accept_flag_option = false;
return false;
}
let flag = Self::match_word(word);
if flag.early_exit {
self.flags = vec![flag];
return true;
}
if flag.need_option {
self.accept_flag_option = true;
}
if flag.ftype != FlagType::None {
self.flags.push(flag);
}
}
false
}
fn match_word(word: &str) -> Flag {
match word.trim() {
"--version" | "-v" => Flag::version(),
"--help" | "-h" => Flag::help(),
"--command" | "-c" => Flag::command(),
"--schema" | "-s" => Flag::schema(),
"--confirm" | "-C" => Flag::confirm(),
"--nolog" | "-n" => Flag::nolog(),
_ => Flag::empty(),
}
}
}
#[derive(Debug)]
pub struct Flag {
pub ftype: FlagType,
pub need_option: bool,
pub option: String,
pub early_exit: bool,
}
impl Flag {
pub fn empty() -> Self {
Self {
ftype: FlagType::None,
need_option: false,
option: String::new(),
early_exit: false,
}
}
pub fn argument(arg: &str) -> Self {
Self {
ftype: FlagType::Argument,
need_option: false,
option: arg.to_string(),
early_exit: false,
}
}
pub fn schema() -> Self {
Self {
ftype: FlagType::Schema,
need_option: true,
option: String::new(),
early_exit: false,
}
}
pub fn command() -> Self {
Self {
ftype: FlagType::Command,
need_option: true,
option: String::new(),
early_exit: false,
}
}
pub fn confirm() -> Self {
Self {
ftype: FlagType::Confirm,
need_option: false,
option: String::new(),
early_exit: false,
}
}
pub fn nolog() -> Self {
Self {
ftype: FlagType::NoLog,
need_option: false,
option: String::new(),
early_exit: false,
}
}
pub fn version() -> Self {
Self {
ftype: FlagType::Version,
need_option: false,
option: String::new(),
early_exit: true,
}
}
pub fn help() -> Self {
Self {
ftype: FlagType::Help,
need_option: false,
option: String::new(),
early_exit: true,
}
}
}
#[derive(PartialEq, Debug)]
pub enum FlagType {
Argument,
Command,
Confirm,
Help,
Schema,
Version,
NoLog,
None,
}