mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 21:51:40 +03:00
just return the value and assign it to the receiver. Renamed the conversion function and also cleaned up all the `typeof` calls, which were very verbose.
This commit is contained in:
parent
cafe864533
commit
79cbde1ab6
1 changed files with 40 additions and 33 deletions
73
std/getopt.d
73
std/getopt.d
|
@ -610,14 +610,14 @@ private template optionValidator(A...)
|
||||||
alias optionValidator = message;
|
alias optionValidator = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleConversion(R)(string option, string value, R* receiver,
|
private auto getoptTo(R)(string option, string value,
|
||||||
size_t idx, string file = __FILE__, size_t line = __LINE__)
|
size_t idx, string file = __FILE__, size_t line = __LINE__)
|
||||||
{
|
{
|
||||||
import std.conv : to, ConvException;
|
import std.conv : to, ConvException;
|
||||||
import std.format : format;
|
import std.format : format;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
*receiver = to!(typeof(*receiver))(value);
|
return to!R(value);
|
||||||
}
|
}
|
||||||
catch (ConvException e)
|
catch (ConvException e)
|
||||||
{
|
{
|
||||||
|
@ -876,12 +876,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
// (and potentially args[i + 1] too, but that comes later)
|
// (and potentially args[i + 1] too, but that comes later)
|
||||||
args = args[0 .. i] ~ args[i + 1 .. $];
|
args = args[0 .. i] ~ args[i + 1 .. $];
|
||||||
|
|
||||||
static if (is(typeof(*receiver) == bool))
|
static if (is(typeof(*receiver)))
|
||||||
|
alias Target = typeof(*receiver);
|
||||||
|
else
|
||||||
|
// delegate
|
||||||
|
alias Target = void;
|
||||||
|
|
||||||
|
static if (is(Target == bool))
|
||||||
{
|
{
|
||||||
if (val.length)
|
if (val.length)
|
||||||
{
|
{
|
||||||
// parse '--b=true/false'
|
// parse '--b=true/false'
|
||||||
handleConversion(option, val, receiver, i);
|
*receiver = getoptTo!(Target)(option, val, i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -894,23 +900,23 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
import std.exception : enforce;
|
import std.exception : enforce;
|
||||||
// non-boolean option, which might include an argument
|
// non-boolean option, which might include an argument
|
||||||
enum isCallbackWithLessThanTwoParameters =
|
enum isCallbackWithLessThanTwoParameters =
|
||||||
(is(typeof(receiver) == delegate) || is(typeof(*receiver) == function)) &&
|
(is(R == delegate) || is(Target == function)) &&
|
||||||
!is(typeof(receiver("", "")));
|
!is(typeof(receiver("", "")));
|
||||||
if (!isCallbackWithLessThanTwoParameters && !(val.length) && !incremental)
|
if (!isCallbackWithLessThanTwoParameters && !(val.length) && !incremental)
|
||||||
{
|
{
|
||||||
// Eat the next argument too. Check to make sure there's one
|
// Eat the next argument too. Check to make sure there's one
|
||||||
// to be eaten first, though.
|
// to be eaten first, though.
|
||||||
enforce!GetOptException(i < args.length,
|
enforce!GetOptException(i < args.length,
|
||||||
"Missing value for argument " ~ a ~ ".");
|
"Missing value for argument " ~ a ~ ".");
|
||||||
val = args[i];
|
val = args[i];
|
||||||
args = args[0 .. i] ~ args[i + 1 .. $];
|
args = args[0 .. i] ~ args[i + 1 .. $];
|
||||||
}
|
}
|
||||||
static if (is(typeof(*receiver) == enum) ||
|
static if (is(Target == enum) ||
|
||||||
is(typeof(*receiver) == string))
|
is(Target == string))
|
||||||
{
|
{
|
||||||
handleConversion(option, val, receiver, i);
|
*receiver = getoptTo!Target(option, val, i);
|
||||||
}
|
}
|
||||||
else static if (is(typeof(*receiver) : real))
|
else static if (is(Target : real))
|
||||||
{
|
{
|
||||||
// numeric receiver
|
// numeric receiver
|
||||||
if (incremental)
|
if (incremental)
|
||||||
|
@ -919,16 +925,16 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
handleConversion(option, val, receiver, i);
|
*receiver = getoptTo!Target(option, val, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else static if (is(typeof(*receiver) == string))
|
else static if (is(Target == string))
|
||||||
{
|
{
|
||||||
// string receiver
|
// string receiver
|
||||||
*receiver = to!(typeof(*receiver))(val);
|
*receiver = getoptTo!(Target)(option, val, i);
|
||||||
}
|
}
|
||||||
else static if (is(typeof(receiver) == delegate) ||
|
else static if (is(R == delegate) ||
|
||||||
is(typeof(*receiver) == function))
|
is(Target == function))
|
||||||
{
|
{
|
||||||
static if (is(typeof(receiver("", "")) : void))
|
static if (is(typeof(receiver("", "")) : void))
|
||||||
{
|
{
|
||||||
|
@ -952,29 +958,25 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
receiver();
|
receiver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else static if (isArray!(typeof(*receiver)))
|
else static if (isArray!(Target))
|
||||||
{
|
{
|
||||||
// array receiver
|
// array receiver
|
||||||
import std.range : ElementEncodingType;
|
import std.range : ElementEncodingType;
|
||||||
alias E = ElementEncodingType!(typeof(*receiver));
|
alias E = ElementEncodingType!(Target);
|
||||||
|
|
||||||
if (arraySep == "")
|
if (arraySep == "")
|
||||||
{
|
{
|
||||||
E tmp;
|
*receiver ~= getoptTo!E(option, val, i);
|
||||||
handleConversion(option, val, &tmp, i);
|
|
||||||
*receiver ~= tmp;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (elem; val.splitter(arraySep))
|
foreach (elem; val.splitter(arraySep))
|
||||||
{
|
{
|
||||||
E tmp;
|
*receiver ~= getoptTo!E(option, elem, i);
|
||||||
handleConversion(option, elem, &tmp, i);
|
|
||||||
*receiver ~= tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else static if (isAssociativeArray!(typeof(*receiver)))
|
else static if (isAssociativeArray!(Target))
|
||||||
{
|
{
|
||||||
// hash receiver
|
// hash receiver
|
||||||
alias K = typeof(receiver.keys[0]);
|
alias K = typeof(receiver.keys[0]);
|
||||||
|
@ -991,14 +993,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
~ to!string(assignChar) ~ "' in argument '" ~ input ~ "'.");
|
~ to!string(assignChar) ~ "' in argument '" ~ input ~ "'.");
|
||||||
auto key = input[0 .. j];
|
auto key = input[0 .. j];
|
||||||
auto value = input[j + 1 .. $];
|
auto value = input[j + 1 .. $];
|
||||||
|
return tuple(getoptTo!K("", key, 0), getoptTo!V("", value, 0));
|
||||||
K k;
|
|
||||||
handleConversion("", key, &k, 0);
|
|
||||||
|
|
||||||
V v;
|
|
||||||
handleConversion("", value, &v, 0);
|
|
||||||
|
|
||||||
return tuple(k,v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setHash(Range)(R receiver, Range range)
|
static void setHash(Range)(R receiver, Range range)
|
||||||
|
@ -1013,7 +1008,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
setHash(receiver, val.splitter(arraySep));
|
setHash(receiver, val.splitter(arraySep));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
static assert(false, "getopt does not know how to handle the type " ~ typeof(receiver).stringof);
|
static assert(false, "getopt does not know how to handle the type " ~ R.stringof);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,6 +1094,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
||||||
assert(values == ["foo":0, "bar":1, "baz":2], to!string(values));
|
assert(values == ["foo":0, "bar":1, "baz":2], to!string(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/dlang/phobos/issues/10680
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
arraySep = ",";
|
||||||
|
scope(exit) arraySep = "";
|
||||||
|
const(string)[] s;
|
||||||
|
string[] args = ["program.name", "-s", "a", "-s", "b", "-s", "c,d,e"];
|
||||||
|
getopt(args, "values|s", &s);
|
||||||
|
assert(s == ["a", "b", "c", "d", "e"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The option character (default '-').
|
The option character (default '-').
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue