use std::collections::BTreeMap;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct CommanderOption {
pub short: Option<String>,
pub long: String,
}
pub fn get_remaining_flags(
raw_args: &[String],
consumed_options: &[CommanderOption],
consumed_values: &BTreeMap<String, String>,
) -> Vec<String> {
let start = raw_args
.iter()
.position(|item| item.starts_with("--"))
.unwrap_or(0);
raw_args[start..]
.iter()
.enumerate()
.filter_map(|(index, item)| {
if consumed_options
.iter()
.any(|option| option.short.as_deref() == Some(item) || option.long == *item)
{
return None;
}
if let Some(previous) = index
.checked_sub(1)
.and_then(|previous| raw_args[start..].get(previous))
{
let previous_key =
camel_case_flag(&previous.replace("--", "").replacen("no", "", 1));
if consumed_values
.get(&previous_key)
.is_some_and(|value| value == item)
{
return None;
}
}
Some(item.clone())
})
.collect()
}
pub fn get_remaining_flags_simple(raw_args: &[String], consumed_options: &[&str]) -> Vec<String> {
let options = consumed_options
.iter()
.map(|option| CommanderOption {
short: None,
long: (*option).to_string(),
})
.collect::<Vec<_>>();
get_remaining_flags(raw_args, &options, &BTreeMap::new())
}
pub fn camel_case_flag(flag: &str) -> String {
let mut words = flag.split('-');
let Some(first) = words.next() else {
return String::new();
};
words.fold(first.to_string(), |mut output, word| {
let mut chars = word.chars();
if let Some(first_char) = chars.next() {
output.push(first_char.to_ascii_uppercase());
output.push_str(chars.as_str());
}
output
})
}