mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 23:20:29 +03:00
added getOpt constraint that checks the options
on invalid pattern: - outputs a message that gives a hint about the wrong type - includes the index of the wrong option the message doesn't hide the error origin becasue pragma(msg) is used instead or assert(0)
This commit is contained in:
parent
deaee8521c
commit
ad226e92d5
1 changed files with 90 additions and 3 deletions
87
std/getopt.d
87
std/getopt.d
|
@ -534,9 +534,96 @@ private pure Option splitAndGet(string opt) @trusted nothrow
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function verifies that the variadic parameters passed in getOpt
|
||||||
|
follow this pattern:
|
||||||
|
|
||||||
|
[config override], option, [description], receiver,
|
||||||
|
|
||||||
|
- config override: a config value, optional
|
||||||
|
- option: a string
|
||||||
|
- description: a string, optional
|
||||||
|
- receiver: a pointer or a callable
|
||||||
|
*/
|
||||||
|
private template optionValidator(A...)
|
||||||
|
{
|
||||||
|
import std.typecons: staticIota;
|
||||||
|
import std.format: format;
|
||||||
|
|
||||||
|
enum fmt = "getopt validator: %s (at position %d)";
|
||||||
|
enum isReceiver(T) = isPointer!T || (is(T==function)) || (is(T==delegate));
|
||||||
|
|
||||||
|
auto validator()
|
||||||
|
{
|
||||||
|
string msg;
|
||||||
|
static if (A.length > 0)
|
||||||
|
{
|
||||||
|
static if (isReceiver!(A[0]))
|
||||||
|
{
|
||||||
|
msg = format(fmt, "first argument must be a string or a config", 0);
|
||||||
|
}
|
||||||
|
else static if (!isSomeString!(A[0]) && !is(A[0] == config))
|
||||||
|
{
|
||||||
|
msg = format(fmt, "invalid argument type " ~ A[0].stringof, 0);
|
||||||
|
}
|
||||||
|
else foreach(i; staticIota!(1, A.length))
|
||||||
|
{
|
||||||
|
static if (!isReceiver!(A[i]) && !isSomeString!(A[i]) &&
|
||||||
|
!(is(A[i] == config)))
|
||||||
|
{
|
||||||
|
msg = format(fmt, "invalid argument type " ~ A[i].stringof, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else static if (isReceiver!(A[i]) && !isSomeString!(A[i-1]))
|
||||||
|
{
|
||||||
|
msg = format(fmt, "a receiver can not be preceeded by a receiver", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else static if (i > 1 && isSomeString!(A[i]) && isSomeString!(A[i-1])
|
||||||
|
&& isSomeString!(A[i-2]))
|
||||||
|
{
|
||||||
|
msg = format(fmt, "a string can not be preceeded by two strings", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static if (!isReceiver!(A[$-1]) && !is(A[$-1] == config))
|
||||||
|
{
|
||||||
|
msg = format(fmt, "last argument must be a receiver or a config",
|
||||||
|
A.length -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
enum message = validator;
|
||||||
|
alias optionValidator = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe pure unittest
|
||||||
|
{
|
||||||
|
alias P = void*;
|
||||||
|
alias S = string;
|
||||||
|
alias C = config;
|
||||||
|
alias F = void function();
|
||||||
|
|
||||||
|
static assert(optionValidator!(C,S,S,P) == "");
|
||||||
|
static assert(optionValidator!(C,S,S,P,C,S,F) == "");
|
||||||
|
static assert(optionValidator!(C,S,S,P,C,S,F) == "");
|
||||||
|
|
||||||
|
static assert(optionValidator!(P,S,S) != "");
|
||||||
|
static assert(optionValidator!(P,P,S) != "");
|
||||||
|
static assert(optionValidator!(P,F,S,P) != "");
|
||||||
|
static assert(optionValidator!(C,C,S) != "");
|
||||||
|
static assert(optionValidator!(S,S,P,S,S,P,S) != "");
|
||||||
|
static assert(optionValidator!(S,S,P,P) != "");
|
||||||
|
static assert(optionValidator!(S,S,S,P) != "");
|
||||||
|
}
|
||||||
|
|
||||||
private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
|
private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
|
||||||
ref GetoptResult rslt, ref GetOptException excep, T opts)
|
ref GetoptResult rslt, ref GetOptException excep, T opts)
|
||||||
{
|
{
|
||||||
|
enum validationMessage = optionValidator!T;
|
||||||
|
static assert(validationMessage == "", validationMessage);
|
||||||
|
|
||||||
import std.algorithm : remove;
|
import std.algorithm : remove;
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
static if (opts.length)
|
static if (opts.length)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue