@@ -408,14 +408,40 @@ mod clap {
408408 . parse_ref ( cmd, arg, value)
409409 }
410410 }
411+
412+ #[ derive( Clone ) ]
413+ pub struct AsRange ;
414+
415+ impl TypedValueParser for AsRange {
416+ type Value = std:: ops:: Range < u32 > ;
417+
418+ fn parse_ref ( & self , cmd : & Command , arg : Option < & Arg > , value : & OsStr ) -> Result < Self :: Value , Error > {
419+ StringValueParser :: new ( )
420+ . try_map ( |arg| -> Result < _ , Box < dyn std:: error:: Error + Send + Sync > > {
421+ let parts = arg. split_once ( ',' ) ;
422+ if let Some ( ( start, end) ) = parts {
423+ let start = u32:: from_str ( start) ?;
424+ let end = u32:: from_str ( end) ?;
425+
426+ if start <= end {
427+ return Ok ( start..end) ;
428+ }
429+ }
430+
431+ Err ( Box :: new ( Error :: new ( ErrorKind :: ValueValidation ) ) )
432+ } )
433+ . parse_ref ( cmd, arg, value)
434+ }
435+ }
411436}
412437pub use self :: clap:: {
413- AsBString , AsHashKind , AsOutputFormat , AsPartialRefName , AsPathSpec , AsTime , CheckPathSpec , ParseRenameFraction ,
438+ AsBString , AsHashKind , AsOutputFormat , AsPartialRefName , AsPathSpec , AsRange , AsTime , CheckPathSpec ,
439+ ParseRenameFraction ,
414440} ;
415441
416442#[ cfg( test) ]
417443mod value_parser_tests {
418- use super :: ParseRenameFraction ;
444+ use super :: { AsRange , ParseRenameFraction } ;
419445 use clap:: Parser ;
420446
421447 #[ test]
@@ -441,4 +467,16 @@ mod value_parser_tests {
441467 let c = Cmd :: parse_from ( [ "cmd" , "-a=75" ] ) ;
442468 assert_eq ! ( c. arg, Some ( Some ( 0.75 ) ) ) ;
443469 }
470+
471+ #[ test]
472+ fn range ( ) {
473+ #[ derive( Debug , clap:: Parser ) ]
474+ pub struct Cmd {
475+ #[ clap( long, short='l' , value_parser = AsRange ) ]
476+ pub arg : Option < std:: ops:: Range < u32 > > ,
477+ }
478+
479+ let c = Cmd :: parse_from ( [ "cmd" , "-l=1,10" ] ) ;
480+ assert_eq ! ( c. arg, Some ( 1 ..10 ) ) ;
481+ }
444482}
0 commit comments