@@ -433,6 +433,8 @@ impl Options {
433
433
. map ( |_| Vec :: new ( ) )
434
434
. collect :: < Vec < Vec < ( usize , Optval ) > > > ( ) ;
435
435
let mut free: Vec < String > = Vec :: new ( ) ;
436
+ let mut args_end = None ;
437
+
436
438
let args = args
437
439
. into_iter ( )
438
440
. map ( |i| {
@@ -455,6 +457,7 @@ impl Options {
455
457
}
456
458
}
457
459
} else if cur == "--" {
460
+ args_end = Some ( free. len ( ) ) ;
458
461
free. extend ( args) ;
459
462
break ;
460
463
} else {
@@ -557,7 +560,12 @@ impl Options {
557
560
return Err ( OptionDuplicated ( opt. name . to_string ( ) ) ) ;
558
561
}
559
562
}
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 } )
561
569
}
562
570
563
571
/// Derive a short one-line usage summary from a set of long options.
@@ -778,8 +786,12 @@ pub struct Matches {
778
786
opts : Vec < Opt > ,
779
787
/// Values of the Options that matched and their positions
780
788
vals : Vec < Vec < ( usize , Optval ) > > ,
789
+
781
790
/// Free string fragments
782
791
pub free : Vec < String > ,
792
+
793
+ /// Index of first free fragment after "--" separator
794
+ args_end : Option < usize > ,
783
795
}
784
796
785
797
/// The type returned when the command line does not conform to the
@@ -1104,6 +1116,43 @@ impl Matches {
1104
1116
None => Ok ( def) ,
1105
1117
}
1106
1118
}
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
+ }
1107
1156
}
1108
1157
1109
1158
fn is_arg ( arg : & str ) -> bool {
0 commit comments