@@ -610,14 +610,14 @@ private template optionValidator(A...)
610
610
alias optionValidator = message;
611
611
}
612
612
613
- private void handleConversion (R)(string option, string value, R * receiver ,
613
+ private auto getoptTo (R)(string option, string value,
614
614
size_t idx, string file = __FILE__ , size_t line = __LINE__ )
615
615
{
616
616
import std.conv : to, ConvException;
617
617
import std.format : format;
618
618
try
619
619
{
620
- * receiver = to! ( typeof ( * receiver)) (value);
620
+ return to! R (value);
621
621
}
622
622
catch (ConvException e)
623
623
{
@@ -876,12 +876,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
876
876
// (and potentially args[i + 1] too, but that comes later)
877
877
args = args[0 .. i] ~ args[i + 1 .. $];
878
878
879
- static if (is (typeof (* receiver) == bool ))
879
+ static if (is (typeof (* receiver)))
880
+ alias Target = typeof (* receiver);
881
+ else
882
+ // delegate
883
+ alias Target = void ;
884
+
885
+ static if (is (Target == bool ))
880
886
{
881
887
if (val.length)
882
888
{
883
889
// parse '--b=true/false'
884
- handleConversion( option, val, receiver , i);
890
+ * receiver = getoptTo ! (Target)( option, val, i);
885
891
}
886
892
else
887
893
{
@@ -894,23 +900,23 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
894
900
import std.exception : enforce;
895
901
// non-boolean option, which might include an argument
896
902
enum isCallbackWithLessThanTwoParameters =
897
- (is (typeof (receiver) == delegate ) || is (typeof ( * receiver) == function )) &&
903
+ (is (R == delegate ) || is (Target == function )) &&
898
904
! is (typeof (receiver(" " , " " )));
899
905
if (! isCallbackWithLessThanTwoParameters && ! (val.length) && ! incremental)
900
906
{
901
907
// Eat the next argument too. Check to make sure there's one
902
908
// to be eaten first, though.
903
909
enforce! GetOptException(i < args.length,
904
- " Missing value for argument " ~ a ~ " ." );
910
+ " Missing value for argument " ~ a ~ " ." );
905
911
val = args[i];
906
912
args = args[0 .. i] ~ args[i + 1 .. $];
907
913
}
908
- static if (is (typeof ( * receiver) == enum ) ||
909
- is (typeof ( * receiver) == string ))
914
+ static if (is (Target == enum ) ||
915
+ is (Target == string ))
910
916
{
911
- handleConversion (option, val, receiver , i);
917
+ * receiver = getoptTo ! Target (option, val, i);
912
918
}
913
- else static if (is (typeof ( * receiver) : real ))
919
+ else static if (is (Target : real ))
914
920
{
915
921
// numeric receiver
916
922
if (incremental)
@@ -919,16 +925,16 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
919
925
}
920
926
else
921
927
{
922
- handleConversion (option, val, receiver , i);
928
+ * receiver = getoptTo ! Target (option, val, i);
923
929
}
924
930
}
925
- else static if (is (typeof ( * receiver) == string ))
931
+ else static if (is (Target == string ))
926
932
{
927
933
// string receiver
928
- * receiver = to ! ( typeof ( * receiver))( val);
934
+ * receiver = getoptTo ! (Target)(option, val, i );
929
935
}
930
- else static if (is (typeof (receiver) == delegate ) ||
931
- is (typeof ( * receiver) == function ))
936
+ else static if (is (R == delegate ) ||
937
+ is (Target == function ))
932
938
{
933
939
static if (is (typeof (receiver(" " , " " )) : void ))
934
940
{
@@ -952,29 +958,25 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
952
958
receiver();
953
959
}
954
960
}
955
- else static if (isArray! (typeof ( * receiver) ))
961
+ else static if (isArray! (Target ))
956
962
{
957
963
// array receiver
958
964
import std.range : ElementEncodingType;
959
- alias E = ElementEncodingType! (typeof ( * receiver) );
965
+ alias E = ElementEncodingType! (Target );
960
966
961
967
if (arraySep == " " )
962
968
{
963
- E tmp;
964
- handleConversion(option, val, &tmp, i);
965
- * receiver ~= tmp;
969
+ * receiver ~= getoptTo! E(option, val, i);
966
970
}
967
971
else
968
972
{
969
973
foreach (elem; val.splitter(arraySep))
970
974
{
971
- E tmp;
972
- handleConversion(option, elem, &tmp, i);
973
- * receiver ~= tmp;
975
+ * receiver ~= getoptTo! E(option, elem, i);
974
976
}
975
977
}
976
978
}
977
- else static if (isAssociativeArray! (typeof ( * receiver) ))
979
+ else static if (isAssociativeArray! (Target ))
978
980
{
979
981
// hash receiver
980
982
alias K = typeof (receiver.keys [0 ]);
@@ -991,14 +993,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
991
993
~ to! string (assignChar) ~ " ' in argument '" ~ input ~ " '." );
992
994
auto key = input[0 .. j];
993
995
auto value = input[j + 1 .. $];
994
-
995
- K k;
996
- handleConversion(" " , key, &k, 0 );
997
-
998
- V v;
999
- handleConversion(" " , value, &v, 0 );
1000
-
1001
- return tuple (k,v);
996
+ return tuple (getoptTo! K(" " , key, 0 ), getoptTo! V(" " , value, 0 ));
1002
997
}
1003
998
1004
999
static void setHash (Range )(R receiver, Range range)
@@ -1013,7 +1008,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
1013
1008
setHash(receiver, val.splitter(arraySep));
1014
1009
}
1015
1010
else
1016
- static assert (false , " getopt does not know how to handle the type " ~ typeof (receiver) .stringof);
1011
+ static assert (false , " getopt does not know how to handle the type " ~ R .stringof);
1017
1012
}
1018
1013
}
1019
1014
@@ -1099,6 +1094,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
1099
1094
assert (values == [" foo" :0 , " bar" :1 , " baz" :2 ], to! string (values ));
1100
1095
}
1101
1096
1097
+ // https://github.com/dlang/phobos/issues/10680
1098
+ @safe unittest
1099
+ {
1100
+ arraySep = " ," ;
1101
+ scope (exit) arraySep = " " ;
1102
+ const (string )[] s;
1103
+ string [] args = [" program.name" , " -s" , " a" , " -s" , " b" , " -s" , " c,d,e" ];
1104
+ getopt(args, " values|s" , &s);
1105
+ assert (s == [" a" , " b" , " c" , " d" , " e" ]);
1106
+ }
1107
+
1108
+
1102
1109
/**
1103
1110
The option character (default '-').
1104
1111
0 commit comments