@@ -55,6 +55,7 @@ pub struct App<'a, 'v, 'ab, 'u, 'ar> {
55
55
needs_short_version : bool ,
56
56
needs_subcmd_help : bool ,
57
57
required : HashSet < & ' ar str > ,
58
+ matched_reqs : HashSet < & ' ar str > ,
58
59
arg_list : HashSet < & ' ar str > ,
59
60
short_list : HashSet < char > ,
60
61
long_list : HashSet < & ' ar str > ,
@@ -91,6 +92,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
91
92
needs_subcmd_help : true ,
92
93
needs_short_version : true ,
93
94
required : HashSet :: new ( ) ,
95
+ matched_reqs : HashSet :: new ( ) ,
94
96
arg_list : HashSet :: new ( ) ,
95
97
short_list : HashSet :: new ( ) ,
96
98
long_list : HashSet :: new ( ) ,
@@ -216,6 +218,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
216
218
if a. takes_value {
217
219
panic ! ( "Argument \" {}\" has conflicting requirements, both index() and takes_value(true) were supplied" , a. name) ;
218
220
}
221
+
219
222
// Create the Positional Arguemnt Builder with each HashSet = None to only allocate those that require it
220
223
let mut pb = PosBuilder {
221
224
name : a. name ,
@@ -238,7 +241,8 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
238
241
if let Some ( ref r) = a. requires {
239
242
let mut rhs = HashSet :: new ( ) ;
240
243
// without derefing n = &&str
241
- for n in r { rhs. insert ( * n) ; }
244
+ for n in r {
245
+ rhs. insert ( * n) ; }
242
246
pb. requires = Some ( rhs) ;
243
247
}
244
248
// Check if there is anything in the possible values and add those as well
@@ -409,16 +413,31 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
409
413
}
410
414
411
415
fn print_usage ( & self , more_info : bool ) {
416
+ let tab = " " ;
412
417
println ! ( "USAGE:" ) ;
413
418
if let Some ( u) = self . usage_str {
414
- println ! ( " {}" , u) ;
419
+ println ! ( "{}{}" , tab , u) ;
415
420
} else {
416
421
let flags = !self . flags . is_empty ( ) ;
417
422
let pos = !self . positionals_idx . is_empty ( ) ;
418
423
let opts = !self . opts . is_empty ( ) ;
419
424
let subcmds = !self . subcommands . is_empty ( ) ;
420
425
let mut num_req_pos = 0 ;
421
- let req_pos = self . positionals_idx . values ( ) . filter_map ( |ref x| if x. required || self . required . contains ( x. name ) {
426
+ let mut matched_pos_reqs = HashSet :: new ( ) ;
427
+ // If it's required we also need to ensure all previous positionals are required too
428
+ let mut found = false ;
429
+ for p in self . positionals_idx . values ( ) . rev ( ) {
430
+ if found {
431
+ matched_pos_reqs. insert ( p. name ) ;
432
+ continue ;
433
+ }
434
+ if self . matched_reqs . contains ( p. name ) {
435
+ matched_pos_reqs. insert ( p. name ) ;
436
+ found = true ;
437
+ }
438
+ }
439
+
440
+ let req_pos = self . positionals_idx . values ( ) . filter_map ( |ref x| if x. required || matched_pos_reqs. contains ( x. name ) {
422
441
num_req_pos += 1 ;
423
442
if x. multiple {
424
443
Some ( format ! ( "<{}>..." , x. name) )
@@ -430,7 +449,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
430
449
} )
431
450
. fold ( String :: new ( ) , |acc, ref name| acc + & format ! ( "{} " , name) [ ..] ) ;
432
451
let mut num_req_opts = 0 ;
433
- let req_opts = self . opts . values ( ) . filter_map ( |x| if x. required || self . required . contains ( x. name ) {
452
+ let req_opts = self . opts . values ( ) . filter_map ( |x| if x. required || self . matched_reqs . contains ( x. name ) {
434
453
num_req_opts += 1 ;
435
454
Some ( x)
436
455
} else {
@@ -442,7 +461,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
442
461
format!( "{} " , o. short. unwrap( ) )
443
462
} , o. name) ) ;
444
463
445
- print ! ( " {} {} {} {} {}" , self . bin_name. clone( ) . unwrap_or( self . name. clone( ) ) ,
464
+ print ! ( "{}{} {} {} {} {}" , tab , self . bin_name. clone( ) . unwrap_or( self . name. clone( ) ) ,
446
465
if flags { "[FLAGS]" } else { "" } ,
447
466
if opts {
448
467
if num_req_opts != self . opts. len( ) && !req_opts. is_empty( ) {
@@ -653,7 +672,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
653
672
654
673
pub fn get_matches ( mut self ) -> ArgMatches < ' ar > {
655
674
self . verify_positionals ( ) ;
656
- for sc in self . subcommands . values ( ) {
675
+ for ( _ , sc ) in self . subcommands . iter_mut ( ) {
657
676
sc. verify_positionals ( ) ;
658
677
}
659
678
@@ -674,7 +693,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
674
693
matches
675
694
}
676
695
677
- fn verify_positionals ( & self ) {
696
+ fn verify_positionals ( & mut self ) {
678
697
// Because you must wait until all arguments have been supplied, this is the first chance
679
698
// to make assertions on positional argument indexes
680
699
//
@@ -695,6 +714,19 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
695
714
panic ! ( "Found positional argument \" {}\" which accepts multiple values but it's not the last positional argument (i.e. others have a higher index)" ,
696
715
p. name) ;
697
716
}
717
+
718
+ // If it's required we also need to ensure all previous positionals are required too
719
+ let mut found = false ;
720
+ for ( _, p) in self . positionals_idx . iter_mut ( ) . rev ( ) {
721
+ if found {
722
+ p. required = true ;
723
+ self . required . insert ( p. name ) ;
724
+ continue ;
725
+ }
726
+ if p. required {
727
+ found = true ;
728
+ }
729
+ }
698
730
}
699
731
700
732
fn get_matches_from ( & mut self , matches : & mut ArgMatches < ' ar > , it : & mut IntoIter < String > ) {
@@ -738,6 +770,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
738
770
needs_val_of = None ;
739
771
continue ;
740
772
}
773
+
741
774
if arg_slice. starts_with ( "--" ) && !pos_only {
742
775
if arg_slice. len ( ) == 2 {
743
776
pos_only = true ;
@@ -762,6 +795,9 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
762
795
format ! ( "Found positional argument {}, but {} doesn't accept any" , arg, self . name) ,
763
796
true , true ) ;
764
797
}
798
+ // If we find that an argument requires a positiona, we need to update all the
799
+ // previous positionals too. This will denote where to start
800
+ // let mut req_pos_from_name = None;
765
801
if let Some ( p) = self . positionals_idx . get ( & pos_counter) {
766
802
if self . blacklist . contains ( p. name ) {
767
803
self . report_error ( format ! ( "The argument \" {}\" is mutually exclusive with one or more other arguments" , arg) ,
@@ -806,13 +842,16 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
806
842
self . required . remove ( name) ;
807
843
}
808
844
}
809
- if self . required . contains ( p. name ) {
845
+
846
+ // No need to check for existance, returns None if not found
847
+ // if self.required.contains(p.name) {
810
848
self . required . remove ( p. name ) ;
811
- }
849
+ // }
812
850
if let Some ( ref reqs) = p. requires {
813
851
// Add all required args which aren't already found in matches to the
814
852
// final required list
815
853
for n in reqs {
854
+ self . matched_reqs . insert ( n) ;
816
855
if matches. positionals . contains_key ( n) { continue ; }
817
856
if matches. opts . contains_key ( n) { continue ; }
818
857
if matches. flags . contains_key ( n) { continue ; }
@@ -955,13 +994,15 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
955
994
self . required . remove ( name) ;
956
995
}
957
996
}
958
- if self . required . contains ( v. name ) {
997
+ // No need to check for existance, returns None if not found
998
+ // if self.required.contains(v.name) {
959
999
self . required . remove ( v. name ) ;
960
- }
1000
+ // }
961
1001
if let Some ( ref reqs) = v. requires {
962
1002
// Add all required args which aren't already found in matches to the
963
1003
// final required list
964
1004
for n in reqs {
1005
+ self . matched_reqs . insert ( n) ;
965
1006
if matches. opts . contains_key ( n) { continue ; }
966
1007
if matches. flags . contains_key ( n) { continue ; }
967
1008
if matches. positionals . contains_key ( n) { continue ; }
@@ -1002,9 +1043,10 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
1002
1043
1003
1044
// If this flag was requierd, remove it
1004
1045
// .. even though Flags shouldn't be required
1005
- if self . required . contains ( v. name ) {
1046
+ // No need to check for existance, returns None if not found
1047
+ // if self.required.contains(v.name) {
1006
1048
self . required . remove ( v. name ) ;
1007
- }
1049
+ // }
1008
1050
1009
1051
// Add all of this flags "mutually excludes" list to the master list
1010
1052
if let Some ( ref bl) = v. blacklist {
@@ -1017,6 +1059,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
1017
1059
// Add all required args which aren't already found in matches to the master list
1018
1060
if let Some ( ref reqs) = v. requires {
1019
1061
for n in reqs {
1062
+ self . matched_reqs . insert ( n) ;
1020
1063
if matches. flags . contains_key ( n) { continue ; }
1021
1064
if matches. opts . contains_key ( n) { continue ; }
1022
1065
if matches. positionals . contains_key ( n) { continue ; }
@@ -1080,13 +1123,15 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
1080
1123
self . required . remove ( name) ;
1081
1124
}
1082
1125
}
1083
- if self . required . contains ( v. name ) {
1126
+ // No need to check for existance, returns None if not found
1127
+ // if self.required.contains(v.name) {
1084
1128
self . required . remove ( v. name ) ;
1085
- }
1129
+ // }
1086
1130
if let Some ( ref reqs) = v. requires {
1087
1131
// Add all required args which aren't already found in matches to the
1088
1132
// final required list
1089
1133
for n in reqs {
1134
+ self . matched_reqs . insert ( n) ;
1090
1135
if matches. opts . contains_key ( n) { continue ; }
1091
1136
if matches. flags . contains_key ( n) { continue ; }
1092
1137
if matches. positionals . contains_key ( n) { continue ; }
@@ -1130,9 +1175,11 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
1130
1175
1131
1176
// If this flag was requierd, remove it
1132
1177
// .. even though Flags shouldn't be required
1133
- if self . required . contains ( v. name ) {
1178
+
1179
+ // No need to check for existance, returns None if it didn't exist
1180
+ // if self.required.contains(v.name) {
1134
1181
self . required . remove ( v. name ) ;
1135
- }
1182
+ // }
1136
1183
1137
1184
// Add all of this flags "mutually excludes" list to the master list
1138
1185
if let Some ( ref bl) = v. blacklist {
@@ -1145,6 +1192,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
1145
1192
// Add all required args which aren't already found in matches to the master list
1146
1193
if let Some ( ref reqs) = v. requires {
1147
1194
for n in reqs {
1195
+ self . matched_reqs . insert ( n) ;
1148
1196
if matches. flags . contains_key ( n) { continue ; }
1149
1197
if matches. opts . contains_key ( n) { continue ; }
1150
1198
if matches. positionals . contains_key ( n) { continue ; }
0 commit comments