@@ -5,9 +5,7 @@ use std::collections::HashMap;
5
5
use std:: env;
6
6
use std:: path:: Path ;
7
7
use std:: vec:: IntoIter ;
8
- use std:: borrow:: ToOwned ;
9
8
use std:: process;
10
- use std:: fmt:: Write ;
11
9
12
10
use args:: { ArgMatches , Arg , SubCommand , MatchedArg } ;
13
11
use args:: { FlagBuilder , OptBuilder , PosBuilder } ;
@@ -336,7 +334,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
336
334
let mut rhs = HashSet :: new ( ) ;
337
335
// without derefing n = &&str
338
336
for n in r {
339
- rhs. insert ( * n) ; }
337
+ rhs. insert ( * n) ;
338
+ if pb. required {
339
+ self . required . insert ( * n) ;
340
+ }
341
+ }
340
342
pb. requires = Some ( rhs) ;
341
343
}
342
344
// Check if there is anything in the possible values and add those as well
@@ -387,7 +389,12 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
387
389
if let Some ( ref r) = a. requires {
388
390
let mut rhs = HashSet :: new ( ) ;
389
391
// without derefing n = &&str
390
- for n in r { rhs. insert ( * n) ; }
392
+ for n in r {
393
+ rhs. insert ( * n) ;
394
+ if ob. required {
395
+ self . required . insert ( * n) ;
396
+ }
397
+ }
391
398
ob. requires = Some ( rhs) ;
392
399
}
393
400
// Check if there is anything in the possible values and add those as well
@@ -657,10 +664,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
657
664
self
658
665
}
659
666
660
- fn group_string ( & self , g : & ArgGroup , r : & str , vec : & Vec < & str > ) -> Option < Vec < String > > {
667
+ fn group_string ( & self , g : & ArgGroup , r : & str , vec : & HashSet < & ' ar str > ) -> Option < Vec < String > > {
661
668
let mut g_vec = vec ! [ ] ;
662
669
for a in g. args . iter ( ) {
663
- if vec. contains ( & a) { return None }
670
+ if vec. contains ( a) { return None }
664
671
if let Some ( f) = self . flags . get ( r) {
665
672
g_vec. push ( format ! ( "{}" , f) ) ;
666
673
} else if let Some ( o) = self . opts . get ( r) {
@@ -677,141 +684,149 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
677
684
Some ( g_vec)
678
685
}
679
686
680
- // Creates a usage string if one was not provided by the user manually. This happens just
681
- // after all arguments were parsed, but before any subcommands have been parsed (so as to
682
- // give subcommands their own usage recursively)
683
- fn create_usage ( & self , matches : Option < Vec < & str > > ) -> String {
684
- let tab = " " ;
685
- let mut usage = String :: with_capacity ( 75 ) ;
686
- usage. push_str ( "USAGE:\n " ) ;
687
- usage. push_str ( tab) ;
688
- if let Some ( u) = self . usage_str {
689
- usage. push_str ( u) ;
690
- } else if let Some ( vec) = matches {
691
- let mut c_flags = vec ! [ ] ;
692
- let mut c_pos = vec ! [ ] ;
693
- let mut c_opt = vec ! [ ] ;
694
- let mut grps = vec ! [ ] ;
695
- vec. iter ( ) . map ( |name| if let Some ( f) = self . flags . get ( name) {
696
- c_flags. push ( f) ;
697
- } else if let Some ( o) = self . opts . get ( name) {
698
- c_opt. push ( o) ;
699
- } else {
700
- c_pos. push (
701
- self . positionals_idx . get ( self . positionals_name . get ( name)
702
- . unwrap ( ) )
703
- . unwrap ( )
704
- ) ;
705
- } ) . collect :: < Vec < _ > > ( ) ;
706
- let mut tmp_f = vec ! [ ] ;
707
- for f in c_flags. iter_mut ( ) {
708
- if let Some ( ref rl) = f. requires {
709
- for r in rl {
710
- if !vec. contains ( & & r) {
711
- if let Some ( f) = self . flags . get ( r) {
712
- tmp_f. push ( f) ;
713
- } else if let Some ( o) = self . opts . get ( r) {
714
- c_opt. push ( o) ;
715
- } else if let Some ( g) = self . groups . get ( r) {
716
- if let Some ( vec) = self . group_string ( g, r, & vec) {
717
- let g_string = vec. iter ( )
718
- . map ( |s| format ! ( "{}|" , s) )
719
- . fold ( String :: new ( ) , |acc, i| {
720
- acc + & format ! ( "{}" , i) [ ..]
721
- } ) ;
722
- grps. push ( format ! ( "[{}]" , & g_string[ ..g_string. len( ) -1 ] ) ) ;
723
- }
724
- } else {
725
- c_pos. push (
726
- self . positionals_idx . get ( self . positionals_name . get ( r)
727
- . unwrap ( ) )
728
- . unwrap ( ) ) ;
687
+ fn get_required_from ( & self , reqs : HashSet < & ' ar str > ) -> Vec < String > {
688
+ let mut c_flags = vec ! [ ] ;
689
+ let mut c_pos = vec ! [ ] ;
690
+ let mut c_opt = vec ! [ ] ;
691
+ let mut grps = vec ! [ ] ;
692
+ reqs. iter ( ) . map ( |name| if let Some ( f) = self . flags . get ( name) {
693
+ c_flags. push ( f) ;
694
+ } else if let Some ( o) = self . opts . get ( name) {
695
+ c_opt. push ( o) ;
696
+ } else {
697
+ c_pos. push (
698
+ self . positionals_idx . get ( self . positionals_name . get ( name)
699
+ . unwrap ( ) )
700
+ . unwrap ( )
701
+ ) ;
702
+ } ) . collect :: < Vec < _ > > ( ) ;
703
+ let mut tmp_f = vec ! [ ] ;
704
+ for f in c_flags. iter_mut ( ) {
705
+ if let Some ( ref rl) = f. requires {
706
+ for r in rl {
707
+ if !reqs. contains ( r) {
708
+ if let Some ( f) = self . flags . get ( r) {
709
+ tmp_f. push ( f) ;
710
+ } else if let Some ( o) = self . opts . get ( r) {
711
+ c_opt. push ( o) ;
712
+ } else if let Some ( g) = self . groups . get ( r) {
713
+ if let Some ( vec) = self . group_string ( g, r, & reqs) {
714
+ let g_string = vec. iter ( )
715
+ . map ( |s| format ! ( "{}|" , s) )
716
+ . fold ( String :: new ( ) , |acc, i| {
717
+ acc + & format ! ( "{}" , i) [ ..]
718
+ } ) ;
719
+ grps. push ( format ! ( "[{}]" , & g_string[ ..g_string. len( ) -1 ] ) ) ;
729
720
}
721
+ } else {
722
+ c_pos. push (
723
+ self . positionals_idx . get ( self . positionals_name . get ( r)
724
+ . unwrap ( ) )
725
+ . unwrap ( ) ) ;
730
726
}
731
727
}
732
728
}
733
729
}
734
- for f in tmp_f {
735
- c_flags. push ( f) ;
736
- }
737
- let mut tmp_o = vec ! [ ] ;
738
- for o in c_opt. iter_mut ( ) {
739
- if let Some ( ref rl) = o. requires {
740
- for r in rl {
741
- if !vec. contains ( & & r) {
742
- if let Some ( f) = self . flags . get ( r) {
743
- c_flags. push ( f) ;
744
- } else if let Some ( o) = self . opts . get ( r) {
745
- tmp_o. push ( o) ;
746
- } else if let Some ( g) = self . groups . get ( r) {
747
- if let Some ( vec) = self . group_string ( g, r, & vec) {
748
- let g_string = vec. iter ( )
749
- . map ( |s| format ! ( "{}|" , s) )
750
- . fold ( String :: new ( ) , |acc, i| {
751
- acc + & format ! ( "{}" , i) [ ..]
752
- } ) ;
753
- grps. push ( format ! ( "[{}]" , & g_string[ ..g_string. len( ) -1 ] ) ) ;
754
- }
755
- } else {
756
- c_pos. push ( self . positionals_idx . get ( self . positionals_name . get ( r)
757
- . unwrap ( ) )
758
- . unwrap ( ) ) ;
730
+ }
731
+ for f in tmp_f {
732
+ c_flags. push ( f) ;
733
+ }
734
+ let mut tmp_o = vec ! [ ] ;
735
+ for o in c_opt. iter_mut ( ) {
736
+ if let Some ( ref rl) = o. requires {
737
+ for r in rl {
738
+ if !reqs. contains ( r) {
739
+ if let Some ( f) = self . flags . get ( r) {
740
+ c_flags. push ( f) ;
741
+ } else if let Some ( o) = self . opts . get ( r) {
742
+ tmp_o. push ( o) ;
743
+ } else if let Some ( g) = self . groups . get ( r) {
744
+ if let Some ( vec) = self . group_string ( g, r, & reqs) {
745
+ let g_string = vec. iter ( )
746
+ . map ( |s| format ! ( "{}|" , s) )
747
+ . fold ( String :: new ( ) , |acc, i| {
748
+ acc + & format ! ( "{}" , i) [ ..]
749
+ } ) ;
750
+ grps. push ( format ! ( "[{}]" , & g_string[ ..g_string. len( ) -1 ] ) ) ;
759
751
}
752
+ } else {
753
+ c_pos. push ( self . positionals_idx . get ( self . positionals_name . get ( r)
754
+ . unwrap ( ) )
755
+ . unwrap ( ) ) ;
760
756
}
761
757
}
762
758
}
763
759
}
764
- for o in tmp_o {
765
- c_opt. push ( o) ;
766
- }
767
- let mut tmp_p = vec ! [ ] ;
768
- for p in c_pos. iter_mut ( ) {
769
- if let Some ( ref rl) = p. requires {
770
- for r in rl {
771
- if !vec. contains ( & & r) {
772
- if let Some ( f) = self . flags . get ( r) {
773
- c_flags. push ( f) ;
774
- } else if let Some ( o) = self . opts . get ( r) {
775
- c_opt. push ( o) ;
776
- } else if let Some ( g) = self . groups . get ( r) {
777
- if let Some ( vec) = self . group_string ( g, r, & vec) {
778
- let g_string = vec. iter ( )
779
- . map ( |s| format ! ( "{}|" , s) )
780
- . fold ( String :: new ( ) , |acc, i| {
781
- acc + & format ! ( "{}" , i) [ ..]
782
- } ) ;
783
- grps. push ( format ! ( "[{}]" , & g_string[ ..g_string. len( ) -1 ] ) ) ;
784
- }
785
- } else {
786
- tmp_p. push ( self . positionals_idx . get ( self . positionals_name . get ( r)
787
- . unwrap ( ) )
788
- . unwrap ( ) ) ;
760
+ }
761
+ for o in tmp_o {
762
+ c_opt. push ( o) ;
763
+ }
764
+ let mut tmp_p = vec ! [ ] ;
765
+ for p in c_pos. iter_mut ( ) {
766
+ if let Some ( ref rl) = p. requires {
767
+ for r in rl {
768
+ if !reqs. contains ( r) {
769
+ if let Some ( f) = self . flags . get ( r) {
770
+ c_flags. push ( f) ;
771
+ } else if let Some ( o) = self . opts . get ( r) {
772
+ c_opt. push ( o) ;
773
+ } else if let Some ( g) = self . groups . get ( r) {
774
+ if let Some ( vec) = self . group_string ( g, r, & reqs) {
775
+ let g_string = vec. iter ( )
776
+ . map ( |s| format ! ( "{}|" , s) )
777
+ . fold ( String :: new ( ) , |acc, i| {
778
+ acc + & format ! ( "{}" , i) [ ..]
779
+ } ) ;
780
+ grps. push ( format ! ( "[{}]" , & g_string[ ..g_string. len( ) -1 ] ) ) ;
789
781
}
782
+ } else {
783
+ tmp_p. push ( self . positionals_idx . get ( self . positionals_name . get ( r)
784
+ . unwrap ( ) )
785
+ . unwrap ( ) ) ;
790
786
}
791
787
}
792
788
}
793
789
}
794
- for p in tmp_p {
795
- c_pos. push ( p) ;
796
- }
797
- let f_string = c_flags. iter ( )
798
- . map ( |f| format ! ( "{}" , f) )
799
- . fold ( String :: new ( ) , |acc, i| acc + & format ! ( " {}" , i) ) ;
800
- let o_string = c_opt. iter ( )
801
- . map ( |f| format ! ( "{}" , f) )
802
- . fold ( String :: new ( ) , |acc, i| acc + & format ! ( " {}" , i) ) ;
803
- let p_string = c_pos. iter ( )
804
- . map ( |f| format ! ( "{}" , f) )
805
- . fold ( String :: new ( ) , |acc, i| acc + & format ! ( " {}" , i) ) ;
806
- let g_string = grps. iter ( )
807
- . map ( |f| format ! ( " {}" , f) )
808
- . fold ( String :: new ( ) , |acc, i| acc + & format ! ( "{}" , i) ) ;
809
- usage. push_str ( & format ! ( "{} {} {} {} {}" ,
790
+ }
791
+ for p in tmp_p {
792
+ c_pos. push ( p) ;
793
+ }
794
+ let mut ret_val = vec ! [ ] ;
795
+
796
+ c_pos. iter ( )
797
+ . map ( |f| ret_val. push ( format ! ( "{}" , f) ) ) . collect :: < Vec < _ > > ( ) ;
798
+ c_flags. iter ( )
799
+ . map ( |f| ret_val. push ( format ! ( "{}" , f) ) ) . collect :: < Vec < _ > > ( ) ;
800
+ c_opt. iter ( )
801
+ . map ( |f| ret_val. push ( format ! ( "{}" , f) ) ) . collect :: < Vec < _ > > ( ) ;
802
+ grps. iter ( )
803
+ . map ( |f| ret_val. push ( format ! ( "{}" , f) ) ) . collect :: < Vec < _ > > ( ) ;
804
+
805
+ ret_val
806
+
807
+ }
808
+
809
+ // Creates a usage string if one was not provided by the user manually. This happens just
810
+ // after all arguments were parsed, but before any subcommands have been parsed (so as to
811
+ // give subcommands their own usage recursively)
812
+ fn create_usage ( & self , matches : Option < Vec < & ' ar str > > ) -> String {
813
+ let tab = " " ;
814
+ let mut usage = String :: with_capacity ( 75 ) ;
815
+ usage. push_str ( "USAGE:\n " ) ;
816
+ usage. push_str ( tab) ;
817
+ if let Some ( u) = self . usage_str {
818
+ usage. push_str ( u) ;
819
+ } else if let Some ( tmp_vec) = matches {
820
+ let mut hs = HashSet :: new ( ) ;
821
+ self . required . iter ( ) . map ( |n| hs. insert ( * n) ) . collect :: < Vec < _ > > ( ) ;
822
+ tmp_vec. iter ( ) . map ( |n| hs. insert ( * n) ) . collect :: < Vec < _ > > ( ) ;
823
+ let reqs = self . get_required_from ( hs) ;
824
+
825
+ let r_string = reqs. iter ( ) . fold ( String :: new ( ) , |acc, s| acc + & format ! ( " {}" , s) [ ..] ) ;
826
+
827
+ usage. push_str ( & format ! ( "{}{}" ,
810
828
self . bin_name. clone( ) . unwrap_or( self . name. clone( ) ) ,
811
- p_string,
812
- f_string,
813
- o_string,
814
- g_string) [ ..] ) ;
829
+ r_string) [ ..] ) ;
815
830
} else {
816
831
let flags = !self . flags . is_empty ( ) ;
817
832
let pos = !self . positionals_idx . is_empty ( ) ;
@@ -1448,10 +1463,15 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
1448
1463
if let Some ( o) = self . opts . get ( a) {
1449
1464
if o. multiple && self . required . is_empty ( ) { ( ) }
1450
1465
else {
1451
- self . report_error ( "One or more required arguments were not \
1452
- supplied". to_owned ( ) ,
1453
- true ,
1454
- true ,
1466
+ self . report_error ( format ! ( "The following required arguments were not \
1467
+ supplied:\n {}",
1468
+ self . get_required_from( self . required. iter( )
1469
+ . map( |s| * s)
1470
+ . collect:: <HashSet <_>>( ) )
1471
+ . iter( )
1472
+ . fold( String :: new( ) , |acc, s| acc + & format!( "\t {}\n " , s) [ ..] ) ) ,
1473
+ true ,
1474
+ true ,
1455
1475
Some ( matches. args . keys ( ) . map ( |k| * k) . collect :: < Vec < _ > > ( ) ) ) ;
1456
1476
}
1457
1477
} else {
@@ -1478,8 +1498,16 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
1478
1498
1479
1499
if !self . required . is_empty ( ) {
1480
1500
if self . validate_required ( & matches) {
1481
- self . report_error ( "One or more required arguments were not supplied" . to_owned ( ) ,
1482
- true , true , Some ( matches. args . keys ( ) . map ( |k| * k) . collect :: < Vec < _ > > ( ) ) ) ;
1501
+ self . report_error ( format ! ( "The following required arguments were not \
1502
+ supplied:\n {}",
1503
+ self . get_required_from( self . required. iter( )
1504
+ . map( |s| * s)
1505
+ . collect:: <HashSet <_>>( ) )
1506
+ . iter( )
1507
+ . fold( String :: new( ) , |acc, s| acc + & format!( "\t {}\n " , s) [ ..] ) ) ,
1508
+ true ,
1509
+ true ,
1510
+ Some ( matches. args . keys ( ) . map ( |k| * k) . collect :: < Vec < _ > > ( ) ) ) ;
1483
1511
}
1484
1512
}
1485
1513
0 commit comments