kind is_match

args
Avril 4 years ago
parent bdbadf60b1
commit 1fa8286fd6
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -28,21 +28,97 @@ pub enum Kind<'a>
/// A single `--`. /// A single `--`.
/// ///
/// # Note /// # Note
/// Shorthand for `Long(&[], false)` /// Shorthand for `Long(&[], _)`
Terminator, Terminator,
/// A single `-`. /// A single `-`.
/// ///
/// # Note /// # Note
/// Shorthand for `Short(&[], false)` /// Shorthand for `Short(&[], _)`
TerminatorShort, TerminatorShort,
/// An exact match with no prefix and flag for case-sensitivity. /// An exact match with no prefix and flag for case-sensitivity.
Exact(&'a str, bool), Exact(&'a str, bool),
/// Match everything, /// Match everything.
Any, Any,
} }
impl<'b> Kind<'b> impl<'b> Kind<'b>
{ {
/// Check if string `value` matches this `Kind`.
///
/// Returns the matched part.
/// # Note
/// In this case of `Short` (or `Abrev` short match), return the rest of the argument string including the matched character
///
/// # Short case-sensitivity
/// Single character matching case sensitivity can produce unexpected results if the lowercase transform of that character yields multiple characters. They are all checked for match.
pub fn is_match<'a, 'c>(&'a self, value: &'b str) -> Option<&'a str>
where 'c: 'a,
'a: 'b
{
match self {
Self::Long(&[], _) |
Self::Abrev(&[], &[], _, _) |
Self::Terminator if value == "--" => Some("--"),
Self::Short(&[], _) |
Self::TerminatorShort if value == "-" => Some("-"),
Self::Abrev(any, _, true, _) |
Self::Long(any, true) if value.starts_with("--") => {
let value = &value[2..];
for &which in any.iter() {
if which == value {
return Some(which);
}
}
None
},
Self::Abrev(any, _, false, _) |
Self::Long(any, false) if value.starts_with("--") => {
let value = value[2..].to_lowercase();
for (orig, which) in any.iter().map(|x| (x, x.to_lowercase())) {
if which == value {
return Some(orig);
}
}
None
},
Self::Abrev(_, any, _, true) |
Self::Short(any, true) if value.starts_with("-") => {
let mut value = value[1..].chars();
let iter = &mut value;
for can_be in iter {
if any.contains(&(can_be,)) {
return Some(value.as_str());
}
}
None
},
//Self::Abrev(_, any, _, false) |
Self::Short(any, false) if value.starts_with("-") => {
let mut value = value[1..].chars();
let iter = &mut value;
let any: Vec<_> = any.iter().flat_map(|(chr,)| chr.to_lowercase()).collect();
for can_be in iter.flat_map(|x| x.to_lowercase()) {
if any.contains(&can_be) {
return Some(value.as_str());
}
}
None
},
Self::Exact(exact, false) if value.to_lowercase() == exact.to_lowercase() => Some(value),
Self::Exact(exact, true) if &value == exact => Some(value),
Self::Any => Some(value),
_ => None,
}
}
/// Create a reference to this `Kind` with a lower lifetime.
pub fn as_ref<'a>(&'a self) -> Kind<'a> pub fn as_ref<'a>(&'a self) -> Kind<'a>
{ {
match &self { match &self {
@ -55,8 +131,18 @@ impl<'b> Kind<'b>
Self::Any => Kind::Any, Self::Any => Kind::Any,
} }
} }
}
/// Split `Kind::Abrev` into short and long
pub fn split_abrev(&self) -> Result<(Kind<'_>, Kind<'_>), &Self>
{
match self {
Self::Abrev(long, short, lcase, scase) => {
Ok((Kind::Long(long,*lcase), Kind::Short(short, *scase)))
},
e => Err(e)
}
}
}
/// Helper for `Cow` variants /// Helper for `Cow` variants
macro_rules! cow macro_rules! cow
@ -274,16 +360,19 @@ impl<U> ArgState<U>
if *single { if *single {
*chk = false; *chk = false;
} }
//TODO: Check Kind matches `arg`, check `value` matches `input` and get the values. //TODO: When value is `Equals`, split at `=` and pass only the first part to `is_match`.
if let Some(kind_match) = kind.is_match(&arg[..]) {
//TODO: Check `value` matches `input` or `kind_match`
output.push(callback(&mut StateHandle{ output.push(callback(&mut StateHandle{
state: &mut self.user, state: &mut self.user,
args: &mut input, args: &mut input,
chk, chk,
idx: i, idx: i,
held: Either::None, //TODO: This will be for either one `=<value>` or many `<values...>` from args as according to `value`. held: Either::None, //TODO: This will be for either one `=<value>` or many `<values...>` from args as according to `value`.
}, i, &arg[..]) }, i, kind_match)
.map_err(|err| Error{flag: kind.clone(), from: err, desc: Some(desc.clone().into_owned()), arg: (i, arg.clone())})?); .map_err(|err| Error{flag: kind.clone(), from: err, desc: Some(desc.clone().into_owned()), arg: (i, arg.clone())})?);
} }
}
i+=1; i+=1;
} }

Loading…
Cancel
Save