use std::collections::HashMap;
use std::collections::HashSet;
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum ArgDesc {
Flag,
Param(bool),
Alias(String),
}
pub struct ParsingConfig {
pub(crate) dh_marker: bool,
pub(crate) store_dh_marker: bool,
pub(crate) sh_syntax: bool,
pub(crate) dh_syntax: bool,
pub(crate) dha_syntax: bool,
pub(crate) a_syntax: bool,
pub(crate) param_stacking: bool,
pub(crate) param_duplication: bool,
pub(crate) option_completion: bool,
pub(crate) subcmd_completion: bool,
pub(crate) subcmd_index: bool,
pub(crate) subcmd_required: bool,
pub(crate) subcmd_index_value: usize,
pub(crate) options: HashMap<String, ArgDesc>,
pub(crate) subcmds: HashSet<String>,
}
impl ParsingConfig {
pub fn new() -> Self {
Self {
dh_marker: true,
store_dh_marker: false,
sh_syntax: true,
dh_syntax: true,
dha_syntax: true,
a_syntax: false,
param_stacking: true,
param_duplication: false,
option_completion: true,
subcmd_completion: false,
subcmd_index: false,
subcmd_required: false,
subcmd_index_value: 0,
options: HashMap::new(),
subcmds: HashSet::new(),
}
}
pub fn new_all_disabled() -> Self {
Self {
dh_marker: false,
store_dh_marker: false,
sh_syntax: false,
dh_syntax: false,
dha_syntax: false,
a_syntax: false,
param_stacking: false,
param_duplication: false,
option_completion: false,
subcmd_completion: false,
subcmd_index: false,
subcmd_required: false,
subcmd_index_value: 0,
options: HashMap::new(),
subcmds: HashSet::new(),
}
}
pub fn is_valid_name(name: &str) -> bool {
!name.chars().any(|x| x.is_whitespace() || x == '=' || x == '\'' || x == '"') && name.chars().next().unwrap_or('a').is_alphabetic()
}
pub fn set_double_hyphen_marker(&mut self, value: bool) {
self.dh_marker = value;
}
pub fn set_store_double_hyphen_marker(&mut self, value: bool) {
self.store_dh_marker = value;
}
pub fn set_single_hyphen_syntax(&mut self, value: bool) {
self.sh_syntax = value;
}
pub fn set_double_hyphen_syntax(&mut self, value: bool) {
self.dh_syntax = value;
}
pub fn set_double_hyphen_assignment_syntax(&mut self, value: bool) {
self.dha_syntax = value;
}
pub fn set_assignment_syntax(&mut self, value: bool) {
self.a_syntax = value;
}
pub fn set_parameter_stacking(&mut self, value: bool) {
self.param_stacking = value;
}
pub fn set_parameter_duplication(&mut self, value: bool) {
self.param_duplication = value;
}
pub fn set_option_completion(&mut self, value: bool) {
self.option_completion = value;
}
pub fn set_subcommand_completion(&mut self, value: bool) {
self.subcmd_completion = value;
}
pub fn set_subcommand_index(&mut self, value: bool) {
self.subcmd_index = value;
}
pub fn set_subcommand_required(&mut self, value: bool) {
self.subcmd_required = value;
}
pub fn set_subcommand_index_value(&mut self, value: usize) {
self.subcmd_index_value = value;
}
pub fn add_flag(&mut self, name: String) {
assert!(Self::is_valid_name(&name), "clargs: invalid flag name");
assert!(!self.options.contains_key(&name), "clargs: flag name is already taken");
assert!(!self.subcmds.contains(&name), "clargs: flag name is already taken");
self.options.insert(name, ArgDesc::Flag);
}
pub fn add_param(&mut self, name: String, required: bool) {
assert!(Self::is_valid_name(&name), "clargs: invalid parameter name");
assert!(!self.options.contains_key(&name), "clargs: parameter name is already taken");
assert!(!self.subcmds.contains(&name), "clargs: parameter name is already taken");
self.options.insert(name, ArgDesc::Param(required));
}
pub fn add_alias(&mut self, name: String, target: String) {
assert!(Self::is_valid_name(&name), "clargs: invalid alias name");
assert!(!self.options.contains_key(&name), "clargs: alias name is already taken");
assert!(!self.subcmds.contains(&name), "clargs: alias name is already taken");
assert!(name != target, "clargs: alias target cannot be the same as its name");
assert!(self.options.contains_key(&target), "clargs: alias must point to a valid target");
let target = match self.options.get(&target).unwrap() {
ArgDesc::Alias(target) => target.to_string(),
_ => target,
};
self.options.insert(name, ArgDesc::Alias(target));
}
pub fn add_subcommand(&mut self, name: String) {
assert!(!name.is_empty(), "clargs: subcommand name cannot be an empty string");
assert!(Self::is_valid_name(&name), "clargs: invalid subcommand name");
assert!(!self.options.contains_key(&name), "clargs: subcommand name is already taken");
assert!(!self.subcmds.contains(&name), "clargs: subcommand name is already taken");
self.subcmds.insert(name);
}
}