@@ -433,6 +433,8 @@ impl Options {
433433 . map ( |_| Vec :: new ( ) )
434434 . collect :: < Vec < Vec < ( usize , Optval ) > > > ( ) ;
435435 let mut free: Vec < String > = Vec :: new ( ) ;
436+ let mut args_end = None ;
437+
436438 let args = args
437439 . into_iter ( )
438440 . map ( |i| {
@@ -455,6 +457,7 @@ impl Options {
455457 }
456458 }
457459 } else if cur == "--" {
460+ args_end = Some ( free. len ( ) ) ;
458461 free. extend ( args) ;
459462 break ;
460463 } else {
@@ -557,7 +560,12 @@ impl Options {
557560 return Err ( OptionDuplicated ( opt. name . to_string ( ) ) ) ;
558561 }
559562 }
560- Ok ( Matches { opts, vals, free } )
563+
564+ // Note that if "--" is last argument on command line, then index stored
565+ // in option does not exist in `free` and must be replaced with `None`
566+ args_end = args_end. filter ( |pos| pos != & free. len ( ) ) ;
567+
568+ Ok ( Matches { opts, vals, free, args_end } )
561569 }
562570
563571 /// Derive a short one-line usage summary from a set of long options.
@@ -778,8 +786,12 @@ pub struct Matches {
778786 opts : Vec < Opt > ,
779787 /// Values of the Options that matched and their positions
780788 vals : Vec < Vec < ( usize , Optval ) > > ,
789+
781790 /// Free string fragments
782791 pub free : Vec < String > ,
792+
793+ /// Index of first free fragment after "--" separator
794+ args_end : Option < usize > ,
783795}
784796
785797/// The type returned when the command line does not conform to the
@@ -1104,6 +1116,43 @@ impl Matches {
11041116 None => Ok ( def) ,
11051117 }
11061118 }
1119+
1120+ /// Returns index of first free argument after "--".
1121+ ///
1122+ /// If double-dash separator is present and there are some args after it in
1123+ /// the argument list then the method returns index into `free` vector
1124+ /// indicating first argument after it.
1125+ /// behind it.
1126+ ///
1127+ /// # Examples
1128+ ///
1129+ /// ```
1130+ /// # use getopts::Options;
1131+ /// let mut opts = Options::new();
1132+ ///
1133+ /// let matches = opts.parse(&vec!["arg1", "--", "arg2"]).unwrap();
1134+ /// let end_pos = matches.free_trailing_start().unwrap();
1135+ /// assert_eq!(end_pos, 1);
1136+ /// assert_eq!(matches.free[end_pos], "arg2".to_owned());
1137+ /// ```
1138+ ///
1139+ /// If the double-dash is missing from argument list or if there are no
1140+ /// arguments after it:
1141+ ///
1142+ /// ```
1143+ /// # use getopts::Options;
1144+ /// let mut opts = Options::new();
1145+ ///
1146+ /// let matches = opts.parse(&vec!["arg1", "--"]).unwrap();
1147+ /// assert_eq!(matches.free_trailing_start(), None);
1148+ ///
1149+ /// let matches = opts.parse(&vec!["arg1", "arg2"]).unwrap();
1150+ /// assert_eq!(matches.free_trailing_start(), None);
1151+ /// ```
1152+ ///
1153+ pub fn free_trailing_start ( & self ) -> Option < usize > {
1154+ self . args_end
1155+ }
11071156}
11081157
11091158fn is_arg ( arg : & str ) -> bool {
0 commit comments