Skip to content

Commit 51dd8de

Browse files
Add support of custom types (#77)
1 parent 3bfd461 commit 51dd8de

File tree

5 files changed

+83
-8
lines changed

5 files changed

+83
-8
lines changed

README.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ considered arguments with the same name as the name of member:
5151
```d
5252
import argparse;
5353
54-
static struct Basic
54+
struct Basic
5555
{
5656
// Basic data types are supported:
5757
// --name argument
@@ -127,7 +127,7 @@ Optional arguments:
127127
For more sophisticated CLI usage, `argparse` provides few UDAs:
128128

129129
```d
130-
static struct Advanced
130+
struct Advanced
131131
{
132132
// Positional arguments are required by default
133133
@PositionalArgument(0)
@@ -1081,7 +1081,7 @@ If you want to determine whether `--color` argument was specified in command lin
10811081
data member:
10821082

10831083
```d
1084-
static struct Arguments
1084+
struct Arguments
10851085
{
10861086
static auto color = ansiStylingArgument;
10871087
}
@@ -1323,7 +1323,7 @@ An argument can be bound to a function with one of the following signatures
13231323
command line and the set of values specified in command line is provided into parameter.
13241324

13251325
```d
1326-
static struct T
1326+
struct T
13271327
{
13281328
int a;
13291329
@@ -1333,6 +1333,25 @@ static struct T
13331333
assert(CLI!T.parseArgs!((T t) { assert(t == T(4)); })(["-a","-a","-a","-a"]) == 0);
13341334
```
13351335

1336+
### Custom types
1337+
1338+
Any arbitrary type can be used to receive command line argument values. `argparse` supports this use case - you just need
1339+
to provide parsing function:
1340+
1341+
```d
1342+
struct Value
1343+
{
1344+
string a;
1345+
}
1346+
struct T
1347+
{
1348+
@(NamedArgument.Parse!((string s) { return Value(s); }))
1349+
Value s;
1350+
}
1351+
1352+
assert(CLI!T.parseArgs!((T t) { assert(t == T(Value("foo"))); return 12345; })(["-s","foo"]) == 12345);
1353+
```
1354+
13361355
## Argument parsing customization
13371356

13381357
Some time the functionality provided out of the box is not enough and it needs to be tuned.

examples/getting_started/advanced/app.d

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import argparse;
22
import argparse.ansi;
33

4-
static struct Advanced
4+
struct Advanced
55
{
66
// Positional arguments are required by default
77
@PositionalArgument(0)
@@ -22,6 +22,13 @@ static struct Advanced
2222
@NamedArgument(["b","banana","ban"])
2323
int banana;
2424

25+
// Custom types can also be used with custon parsing function
26+
struct CustomType {
27+
double d;
28+
}
29+
@(NamedArgument.Parse!((string value) { import std.conv: to; return CustomType(value.to!double); }))
30+
CustomType custom;
31+
2532
@(NamedArgument.Description(green.bold.underline("Colorize")~" the output. If value is omitted then '"~red("always")~"' is used."))
2633
static auto color = ansiStylingArgument;
2734
}

examples/getting_started/basic/app.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import argparse;
22

33
// If struct has no UDA then all members are named arguments
4-
static struct Basic
4+
struct Basic
55
{
66
// Basic data types are supported:
77
// --name argument

source/argparse/internal.d

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,16 @@ if(!is(T == void))
11951195
);
11961196
}
11971197
else
1198-
static assert(false, "Type is not supported: " ~ T.stringof);
1198+
{
1199+
alias DefaultValueParseFunctions = ValueParseFunctions!(
1200+
void, // pre process
1201+
void, // pre validate
1202+
void, // parse
1203+
void, // validate
1204+
void, // action
1205+
void // no-value action
1206+
);
1207+
}
11991208
}
12001209

12011210
unittest

source/argparse/package.d

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,17 @@ public auto PreValidation(alias func, T)(auto ref ArgumentUDA!T uda)
12511251

12521252
public auto Parse(alias func, T)(auto ref ArgumentUDA!T uda)
12531253
{
1254-
return ArgumentUDA!(uda.parsingFunc.changeParse!func)(uda.tupleof);
1254+
auto desc = ArgumentUDA!(uda.parsingFunc.changeParse!func)(uda.tupleof);
1255+
1256+
static if(__traits(compiles, { func(string.init); }))
1257+
desc.info.minValuesCount = desc.info.maxValuesCount = 1;
1258+
else
1259+
{
1260+
desc.info.minValuesCount = 0;
1261+
desc.info.maxValuesCount = ulong.max;
1262+
}
1263+
1264+
return desc;
12551265
}
12561266

12571267
public auto Validation(alias func, T)(auto ref ArgumentUDA!T uda)
@@ -1286,6 +1296,24 @@ unittest
12861296
assert(!is(FUNC == void));
12871297
}
12881298

1299+
unittest
1300+
{
1301+
auto uda = NamedArgument().Parse!((string _) => _);
1302+
assert(is(typeof(uda) : ArgumentUDA!(ValueParseFunctions!(void, void, FUNC, void, void, void)), alias FUNC));
1303+
assert(!is(FUNC == void));
1304+
assert(uda.info.minValuesCount == 1);
1305+
assert(uda.info.maxValuesCount == 1);
1306+
}
1307+
1308+
unittest
1309+
{
1310+
auto uda = NamedArgument().Parse!((string[] _) => _);
1311+
assert(is(typeof(uda) : ArgumentUDA!(ValueParseFunctions!(void, void, FUNC, void, void, void)), alias FUNC));
1312+
assert(!is(FUNC == void));
1313+
assert(uda.info.minValuesCount == 0);
1314+
assert(uda.info.maxValuesCount == ulong.max);
1315+
}
1316+
12891317
unittest
12901318
{
12911319
auto uda = NamedArgument().Validation!({});
@@ -1577,6 +1605,18 @@ unittest
15771605
assert(CLI!T.parseArgs!((T t) { assert(t == T(4)); return 12345; })(["-a","-a","-a","-a"]) == 12345);
15781606
}
15791607

1608+
unittest
1609+
{
1610+
struct Value { string a; }
1611+
struct T
1612+
{
1613+
@(NamedArgument.Parse!((string s) { return Value(s); }))
1614+
Value s;
1615+
}
1616+
1617+
assert(CLI!T.parseArgs!((T t) { assert(t == T(Value("foo"))); return 12345; })(["-s","foo"]) == 12345);
1618+
}
1619+
15801620

15811621
auto Command(string[] name...)
15821622
{

0 commit comments

Comments
 (0)