@@ -59,6 +59,7 @@ impl<'b, 'a> Cmd<'a> {
59
59
collect_opts,
60
60
take_opt_args,
61
61
false ,
62
+ self . is_after_end_opt ,
62
63
) {
63
64
Ok ( _) => { }
64
65
Err ( err) => return Err ( err) ,
@@ -112,14 +113,15 @@ impl<'b, 'a> Cmd<'a> {
112
113
let take_opt_args = |_arg : & str | false ;
113
114
114
115
if self . _num_of_args > 0 {
115
- if let Some ( idx) = parse_args (
116
+ if let Some ( ( idx, is_after_end_opt ) ) = parse_args (
116
117
& self . _leaked_strs [ 1 ..( self . _num_of_args ) ] ,
117
118
collect_args,
118
119
collect_opts,
119
120
take_opt_args,
120
121
true ,
122
+ self . is_after_end_opt ,
121
123
) ? {
122
- return Ok ( Some ( self . sub_cmd ( idx + 1 ) ) ) ; // +1, because parse_args parses from 1.
124
+ return Ok ( Some ( self . sub_cmd ( idx + 1 , is_after_end_opt ) ) ) ; // +1, because parse_args parses from 1.
123
125
}
124
126
}
125
127
@@ -823,4 +825,190 @@ mod tests_of_parse_until_sub_cmd {
823
825
assert_eq ! ( sub_cmd. has_opt( "baz" ) , true ) ;
824
826
}
825
827
}
828
+
829
+ #[ test]
830
+ fn should_parse_single_hyphen ( ) {
831
+ let mut cmd = Cmd :: with_strings ( [
832
+ "/path/to/app" . to_string ( ) ,
833
+ "-a" . to_string ( ) ,
834
+ "-" . to_string ( ) ,
835
+ "b" . to_string ( ) ,
836
+ "-" . to_string ( ) ,
837
+ ] ) ;
838
+
839
+ match cmd. parse_until_sub_cmd ( ) {
840
+ Ok ( None ) => assert ! ( false ) ,
841
+ Ok ( Some ( mut sub_cmd) ) => {
842
+ assert_eq ! ( cmd. name( ) , "app" ) ;
843
+ assert_eq ! ( cmd. args( ) , & [ ] as & [ & str ] ) ;
844
+ assert_eq ! ( cmd. has_opt( "a" ) , true ) ;
845
+
846
+ match sub_cmd. parse ( ) {
847
+ Ok ( _) => {
848
+ assert_eq ! ( sub_cmd. name( ) , "-" ) ;
849
+ assert_eq ! ( sub_cmd. args( ) , & [ "b" , "-" ] ) ;
850
+ assert_eq ! ( sub_cmd. has_opt( "a" ) , false ) ;
851
+ }
852
+ Err ( _) => assert ! ( false ) ,
853
+ }
854
+ }
855
+ Err ( _) => assert ! ( false ) ,
856
+ }
857
+ }
858
+
859
+ #[ test]
860
+ fn should_parse_single_hyphen_but_error ( ) {
861
+ let mut cmd = Cmd :: with_strings ( [
862
+ "/path/to/app" . to_string ( ) ,
863
+ "-a" . to_string ( ) ,
864
+ "-@" . to_string ( ) ,
865
+ "-" . to_string ( ) ,
866
+ "b" . to_string ( ) ,
867
+ "-" . to_string ( ) ,
868
+ ] ) ;
869
+
870
+ match cmd. parse_until_sub_cmd ( ) {
871
+ Ok ( _) => assert ! ( false ) ,
872
+ Err ( InvalidOption :: OptionContainsInvalidChar { option } ) => {
873
+ assert_eq ! ( option, "@" ) ;
874
+ }
875
+ Err ( _) => assert ! ( false ) ,
876
+ }
877
+
878
+ assert_eq ! ( cmd. name( ) , "app" ) ;
879
+ assert_eq ! ( cmd. args( ) , & [ ] as & [ & str ] ) ;
880
+ assert_eq ! ( cmd. has_opt( "a" ) , true ) ;
881
+ }
882
+
883
+ #[ test]
884
+ fn should_parse_with_end_opt_mark ( ) {
885
+ let mut cmd = Cmd :: with_strings ( [
886
+ "/path/to/app" . to_string ( ) ,
887
+ "sub" . to_string ( ) ,
888
+ "--" . to_string ( ) ,
889
+ "-a" . to_string ( ) ,
890
+ "-s@" . to_string ( ) ,
891
+ "--" . to_string ( ) ,
892
+ "xxx" . to_string ( ) ,
893
+ ] ) ;
894
+
895
+ match cmd. parse_until_sub_cmd ( ) {
896
+ Ok ( None ) => assert ! ( false ) ,
897
+ Ok ( Some ( mut sub_cmd) ) => {
898
+ assert_eq ! ( cmd. name( ) , "app" ) ;
899
+ assert_eq ! ( cmd. args( ) , & [ ] as & [ & str ] ) ;
900
+ assert_eq ! ( cmd. has_opt( "a" ) , false ) ;
901
+ assert_eq ! ( cmd. opt_arg( "a" ) , None ) ;
902
+ assert_eq ! ( cmd. opt_args( "a" ) , None ) ;
903
+ assert_eq ! ( cmd. has_opt( "alphabet" ) , false ) ;
904
+ assert_eq ! ( cmd. opt_arg( "alphabet" ) , None ) ;
905
+ assert_eq ! ( cmd. opt_args( "alphabet" ) , None ) ;
906
+ assert_eq ! ( cmd. has_opt( "s" ) , false ) ;
907
+ assert_eq ! ( cmd. opt_arg( "s" ) , None ) ;
908
+ assert_eq ! ( cmd. opt_args( "s" ) , None ) ;
909
+ assert_eq ! ( cmd. has_opt( "silent" ) , false ) ;
910
+ assert_eq ! ( cmd. opt_arg( "silent" ) , None ) ;
911
+ assert_eq ! ( cmd. opt_args( "silent" ) , None ) ;
912
+
913
+ match sub_cmd. parse ( ) {
914
+ Err ( _) => assert ! ( false ) ,
915
+ Ok ( _) => {
916
+ assert_eq ! ( sub_cmd. name( ) , "sub" ) ;
917
+ assert_eq ! ( sub_cmd. args( ) , & [ "-a" , "-s@" , "--" , "xxx" ] ) ;
918
+ assert_eq ! ( sub_cmd. has_opt( "a" ) , false ) ;
919
+ assert_eq ! ( sub_cmd. opt_arg( "a" ) , None ) ;
920
+ assert_eq ! ( sub_cmd. opt_args( "a" ) , None ) ;
921
+ assert_eq ! ( sub_cmd. has_opt( "alphabet" ) , false ) ;
922
+ assert_eq ! ( sub_cmd. opt_arg( "alphabet" ) , None ) ;
923
+ assert_eq ! ( sub_cmd. opt_args( "alphabet" ) , None ) ;
924
+ assert_eq ! ( sub_cmd. has_opt( "s" ) , false ) ;
925
+ assert_eq ! ( sub_cmd. opt_arg( "s" ) , None ) ;
926
+ assert_eq ! ( sub_cmd. opt_args( "s" ) , None ) ;
927
+ assert_eq ! ( sub_cmd. has_opt( "silent" ) , false ) ;
928
+ assert_eq ! ( sub_cmd. opt_arg( "silent" ) , None ) ;
929
+ assert_eq ! ( sub_cmd. opt_args( "silent" ) , None ) ;
930
+ }
931
+ }
932
+ }
933
+ Err ( _) => assert ! ( false ) ,
934
+ }
935
+ }
936
+
937
+ #[ test]
938
+ fn should_parse_after_end_opt_mark ( ) {
939
+ let mut cmd = Cmd :: with_strings ( [
940
+ "/path/to/app" . to_string ( ) ,
941
+ "-s" . to_string ( ) ,
942
+ "--" . to_string ( ) ,
943
+ "-a" . to_string ( ) ,
944
+ "-s@" . to_string ( ) ,
945
+ "--" . to_string ( ) ,
946
+ "xxx" . to_string ( ) ,
947
+ ] ) ;
948
+
949
+ match cmd. parse_until_sub_cmd ( ) {
950
+ Ok ( None ) => assert ! ( false ) ,
951
+ Ok ( Some ( mut sub_cmd) ) => {
952
+ assert_eq ! ( cmd. name( ) , "app" ) ;
953
+ assert_eq ! ( cmd. args( ) , & [ ] as & [ & str ] ) ;
954
+ assert_eq ! ( cmd. has_opt( "a" ) , false ) ;
955
+ assert_eq ! ( cmd. opt_arg( "a" ) , None ) ;
956
+ assert_eq ! ( cmd. opt_args( "a" ) , None ) ;
957
+ assert_eq ! ( cmd. has_opt( "alphabet" ) , false ) ;
958
+ assert_eq ! ( cmd. opt_arg( "alphabet" ) , None ) ;
959
+ assert_eq ! ( cmd. opt_args( "alphabet" ) , None ) ;
960
+ assert_eq ! ( cmd. has_opt( "s" ) , true ) ;
961
+ assert_eq ! ( cmd. opt_arg( "s" ) , None ) ;
962
+ assert_eq ! ( cmd. opt_args( "s" ) , Some ( & [ ] as & [ & str ] ) ) ;
963
+ assert_eq ! ( cmd. has_opt( "silent" ) , false ) ;
964
+ assert_eq ! ( cmd. opt_arg( "silent" ) , None ) ;
965
+ assert_eq ! ( cmd. opt_args( "silent" ) , None ) ;
966
+
967
+ match sub_cmd. parse ( ) {
968
+ Err ( _) => assert ! ( false ) ,
969
+ Ok ( _) => {
970
+ assert_eq ! ( sub_cmd. name( ) , "-a" ) ;
971
+ assert_eq ! ( sub_cmd. args( ) , & [ "-s@" , "--" , "xxx" ] ) ;
972
+ assert_eq ! ( sub_cmd. has_opt( "a" ) , false ) ;
973
+ assert_eq ! ( sub_cmd. opt_arg( "a" ) , None ) ;
974
+ assert_eq ! ( sub_cmd. opt_args( "a" ) , None ) ;
975
+ assert_eq ! ( sub_cmd. has_opt( "alphabet" ) , false ) ;
976
+ assert_eq ! ( sub_cmd. opt_arg( "alphabet" ) , None ) ;
977
+ assert_eq ! ( sub_cmd. opt_args( "alphabet" ) , None ) ;
978
+ assert_eq ! ( sub_cmd. has_opt( "s" ) , false ) ;
979
+ assert_eq ! ( sub_cmd. opt_arg( "s" ) , None ) ;
980
+ assert_eq ! ( sub_cmd. opt_args( "s" ) , None ) ;
981
+ assert_eq ! ( sub_cmd. has_opt( "silent" ) , false ) ;
982
+ assert_eq ! ( sub_cmd. opt_arg( "silent" ) , None ) ;
983
+ assert_eq ! ( sub_cmd. opt_args( "silent" ) , None ) ;
984
+ }
985
+ }
986
+ }
987
+ Err ( _) => assert ! ( false ) ,
988
+ }
989
+ }
990
+
991
+ #[ test]
992
+ fn should_parse_after_end_opt_mark_but_error ( ) {
993
+ let mut cmd = Cmd :: with_strings ( [
994
+ "/path/to/app" . to_string ( ) ,
995
+ "-@" . to_string ( ) ,
996
+ "--" . to_string ( ) ,
997
+ "-a" . to_string ( ) ,
998
+ "-s@" . to_string ( ) ,
999
+ "--" . to_string ( ) ,
1000
+ "xxx" . to_string ( ) ,
1001
+ ] ) ;
1002
+
1003
+ match cmd. parse_until_sub_cmd ( ) {
1004
+ Ok ( _) => assert ! ( false ) ,
1005
+ Err ( InvalidOption :: OptionContainsInvalidChar { option } ) => {
1006
+ assert_eq ! ( option, "@" ) ;
1007
+ }
1008
+ Err ( _) => assert ! ( false ) ,
1009
+ }
1010
+
1011
+ assert_eq ! ( cmd. name( ) , "app" ) ;
1012
+ assert_eq ! ( cmd. args( ) , & [ ] as & [ & str ] ) ;
1013
+ }
826
1014
}
0 commit comments