@@ -354,7 +354,7 @@ impl Options {
354354
355355 let mut vals = ( 0 ..opts. len ( ) )
356356 . map ( |_| Vec :: new ( ) )
357- . collect :: < Vec < Vec < Optval > > > ( ) ;
357+ . collect :: < Vec < Vec < ( usize , Optval ) > > > ( ) ;
358358 let mut free: Vec < String > = Vec :: new ( ) ;
359359 let args = args
360360 . into_iter ( )
@@ -365,6 +365,7 @@ impl Options {
365365 . map ( |s| s. to_owned ( ) )
366366 } ) . collect :: < :: std:: result:: Result < Vec < _ > , _ > > ( ) ?;
367367 let mut args = args. into_iter ( ) . peekable ( ) ;
368+ let mut arg_pos = 0 ;
368369 while let Some ( cur) = args. next ( ) {
369370 if !is_arg ( & cur) {
370371 free. push ( cur) ;
@@ -440,7 +441,7 @@ impl Options {
440441 if name_pos == names. len ( ) && i_arg. is_some ( ) {
441442 return Err ( UnexpectedArgument ( nm. to_string ( ) ) ) ;
442443 }
443- vals[ optid] . push ( Given ) ;
444+ vals[ optid] . push ( ( arg_pos , Given ) ) ;
444445 }
445446 Maybe => {
446447 // Note that here we do not handle `--arg value`.
@@ -450,28 +451,29 @@ impl Options {
450451 // option at the end of the arguments when
451452 // FloatingFrees is in use.
452453 if let Some ( i_arg) = i_arg. take ( ) {
453- vals[ optid] . push ( Val ( i_arg) ) ;
454+ vals[ optid] . push ( ( arg_pos , Val ( i_arg) ) ) ;
454455 } else if was_long
455456 || name_pos < names. len ( )
456457 || args. peek ( ) . map_or ( true , |n| is_arg ( & n) )
457458 {
458- vals[ optid] . push ( Given ) ;
459+ vals[ optid] . push ( ( arg_pos , Given ) ) ;
459460 } else {
460- vals[ optid] . push ( Val ( args. next ( ) . unwrap ( ) ) ) ;
461+ vals[ optid] . push ( ( arg_pos , Val ( args. next ( ) . unwrap ( ) ) ) ) ;
461462 }
462463 }
463464 Yes => {
464465 if let Some ( i_arg) = i_arg. take ( ) {
465- vals[ optid] . push ( Val ( i_arg) ) ;
466+ vals[ optid] . push ( ( arg_pos , Val ( i_arg) ) ) ;
466467 } else if let Some ( n) = args. next ( ) {
467- vals[ optid] . push ( Val ( n) ) ;
468+ vals[ optid] . push ( ( arg_pos , Val ( n) ) ) ;
468469 } else {
469470 return Err ( ArgumentMissing ( nm. to_string ( ) ) ) ;
470471 }
471472 }
472473 }
473474 }
474475 }
476+ arg_pos += 1 ;
475477 }
476478 debug_assert_eq ! ( vals. len( ) , opts. len( ) ) ;
477479 for ( vals, opt) in vals. iter ( ) . zip ( opts. iter ( ) ) {
@@ -701,8 +703,8 @@ enum Optval {
701703pub struct Matches {
702704 /// Options that matched
703705 opts : Vec < Opt > ,
704- /// Values of the Options that matched
705- vals : Vec < Vec < Optval > > ,
706+ /// Values of the Options that matched and their positions
707+ vals : Vec < Vec < ( usize , Optval ) > > ,
706708 /// Free string fragments
707709 pub free : Vec < String > ,
708710}
@@ -799,15 +801,15 @@ impl OptGroup {
799801}
800802
801803impl Matches {
802- fn opt_vals ( & self , nm : & str ) -> Vec < Optval > {
804+ fn opt_vals ( & self , nm : & str ) -> Vec < ( usize , Optval ) > {
803805 match find_opt ( & self . opts , & Name :: from_str ( nm) ) {
804806 Some ( id) => self . vals [ id] . clone ( ) ,
805807 None => panic ! ( "No option '{}' defined" , nm) ,
806808 }
807809 }
808810
809811 fn opt_val ( & self , nm : & str ) -> Option < Optval > {
810- self . opt_vals ( nm) . into_iter ( ) . next ( )
812+ self . opt_vals ( nm) . into_iter ( ) . map ( | ( _ , o ) | o ) . next ( )
811813 }
812814 /// Returns true if an option was defined
813815 pub fn opt_defined ( & self , nm : & str ) -> bool {
@@ -824,6 +826,11 @@ impl Matches {
824826 self . opt_vals ( nm) . len ( )
825827 }
826828
829+ /// Returns a vector of all the positions in which an option was matched.
830+ pub fn opt_positions ( & self , nm : & str ) -> Vec < usize > {
831+ self . opt_vals ( nm) . into_iter ( ) . map ( |( pos, _) | pos) . collect ( )
832+ }
833+
827834 /// Returns true if any of several options were matched.
828835 pub fn opts_present ( & self , names : & [ String ] ) -> bool {
829836 names
@@ -851,12 +858,25 @@ impl Matches {
851858 pub fn opt_strs ( & self , nm : & str ) -> Vec < String > {
852859 self . opt_vals ( nm)
853860 . into_iter ( )
854- . filter_map ( |v | match v {
861+ . filter_map ( |( _ , v ) | match v {
855862 Val ( s) => Some ( s) ,
856863 _ => None ,
857864 } ) . collect ( )
858865 }
859866
867+ /// Returns a vector of the arguments provided to all matches of the given
868+ /// option, together with their positions.
869+ ///
870+ /// Used when an option accepts multiple values.
871+ pub fn opt_strs_pos ( & self , nm : & str ) -> Vec < ( usize , String ) > {
872+ self . opt_vals ( nm)
873+ . into_iter ( )
874+ . filter_map ( |( p, v) | match v {
875+ Val ( s) => Some ( ( p, s) ) ,
876+ _ => None ,
877+ } ) . collect ( )
878+ }
879+
860880 /// Returns the string argument supplied to a matching option or `None`.
861881 pub fn opt_str ( & self , nm : & str ) -> Option < String > {
862882 match self . opt_val ( nm) {
0 commit comments