@@ -610,14 +610,14 @@ private template optionValidator(A...)
610610 alias optionValidator = message;
611611}
612612
613- private void handleConversion (R)(string option, string value, R * receiver ,
613+ private auto getoptTo (R)(string option, string value,
614614 size_t idx, string file = __FILE__ , size_t line = __LINE__ )
615615{
616616 import std.conv : to, ConvException;
617617 import std.format : format;
618618 try
619619 {
620- * receiver = to! ( typeof ( * receiver)) (value);
620+ return to! R (value);
621621 }
622622 catch (ConvException e)
623623 {
@@ -876,12 +876,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
876876 // (and potentially args[i + 1] too, but that comes later)
877877 args = args[0 .. i] ~ args[i + 1 .. $];
878878
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 ))
880886 {
881887 if (val.length)
882888 {
883889 // parse '--b=true/false'
884- handleConversion( option, val, receiver , i);
890+ * receiver = getoptTo ! (Target)( option, val, i);
885891 }
886892 else
887893 {
@@ -894,23 +900,23 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
894900 import std.exception : enforce;
895901 // non-boolean option, which might include an argument
896902 enum isCallbackWithLessThanTwoParameters =
897- (is (typeof (receiver) == delegate ) || is (typeof ( * receiver) == function )) &&
903+ (is (R == delegate ) || is (Target == function )) &&
898904 ! is (typeof (receiver(" " , " " )));
899905 if (! isCallbackWithLessThanTwoParameters && ! (val.length) && ! incremental)
900906 {
901907 // Eat the next argument too. Check to make sure there's one
902908 // to be eaten first, though.
903909 enforce! GetOptException(i < args.length,
904- " Missing value for argument " ~ a ~ " ." );
910+ " Missing value for argument " ~ a ~ " ." );
905911 val = args[i];
906912 args = args[0 .. i] ~ args[i + 1 .. $];
907913 }
908- static if (is (typeof ( * receiver) == enum ) ||
909- is (typeof ( * receiver) == string ))
914+ static if (is (Target == enum ) ||
915+ is (Target == string ))
910916 {
911- handleConversion (option, val, receiver , i);
917+ * receiver = getoptTo ! Target (option, val, i);
912918 }
913- else static if (is (typeof ( * receiver) : real ))
919+ else static if (is (Target : real ))
914920 {
915921 // numeric receiver
916922 if (incremental)
@@ -919,16 +925,16 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
919925 }
920926 else
921927 {
922- handleConversion (option, val, receiver , i);
928+ * receiver = getoptTo ! Target (option, val, i);
923929 }
924930 }
925- else static if (is (typeof ( * receiver) == string ))
931+ else static if (is (Target == string ))
926932 {
927933 // string receiver
928- * receiver = to ! ( typeof ( * receiver))( val);
934+ * receiver = getoptTo ! (Target)(option, val, i );
929935 }
930- else static if (is (typeof (receiver) == delegate ) ||
931- is (typeof ( * receiver) == function ))
936+ else static if (is (R == delegate ) ||
937+ is (Target == function ))
932938 {
933939 static if (is (typeof (receiver(" " , " " )) : void ))
934940 {
@@ -952,29 +958,25 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
952958 receiver();
953959 }
954960 }
955- else static if (isArray! (typeof ( * receiver) ))
961+ else static if (isArray! (Target ))
956962 {
957963 // array receiver
958964 import std.range : ElementEncodingType;
959- alias E = ElementEncodingType! (typeof ( * receiver) );
965+ alias E = ElementEncodingType! (Target );
960966
961967 if (arraySep == " " )
962968 {
963- E tmp;
964- handleConversion(option, val, &tmp, i);
965- * receiver ~= tmp;
969+ * receiver ~= getoptTo! E(option, val, i);
966970 }
967971 else
968972 {
969973 foreach (elem; val.splitter(arraySep))
970974 {
971- E tmp;
972- handleConversion(option, elem, &tmp, i);
973- * receiver ~= tmp;
975+ * receiver ~= getoptTo! E(option, elem, i);
974976 }
975977 }
976978 }
977- else static if (isAssociativeArray! (typeof ( * receiver) ))
979+ else static if (isAssociativeArray! (Target ))
978980 {
979981 // hash receiver
980982 alias K = typeof (receiver.keys [0 ]);
@@ -991,14 +993,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
991993 ~ to! string (assignChar) ~ " ' in argument '" ~ input ~ " '." );
992994 auto key = input[0 .. j];
993995 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 ));
1002997 }
1003998
1004999 static void setHash (Range )(R receiver, Range range)
@@ -1013,7 +1008,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
10131008 setHash(receiver, val.splitter(arraySep));
10141009 }
10151010 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);
10171012 }
10181013 }
10191014
@@ -1099,6 +1094,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
10991094 assert (values == [" foo" :0 , " bar" :1 , " baz" :2 ], to! string (values ));
11001095}
11011096
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+
11021109/**
11031110 The option character (default '-').
11041111
0 commit comments