@ -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 ;
}
}