1 module simpleconfig.args;
2 
3 import simpleconfig.attributes;
4 
5 /// See `simpleconfig.readConfiguration`
6 public void readConfiguration (S) (ref S dst)
7 {
8     static assert (is(S == struct), "Only structs are supported as configuration target");
9 
10     import core.runtime;
11 
12     readConfigurationImpl(dst, Runtime.args());
13 }
14 
15 private template resolveName (alias Field)
16 {
17     import std.traits;
18 
19     enum resolveName = getUDAs!(Field, CLI)[0].full.length
20         ? getUDAs!(Field, CLI)[0]
21         : CLI(__traits(identifier, Field));
22 }
23 
24 unittest
25 {
26     struct S
27     {
28         @cli
29         string field1;
30         @cli("renamed|r")
31         string field2;
32     }
33 
34     static assert (resolveName!(S.field1).full == "field1");
35     static assert (resolveName!(S.field1).single == dchar.init);
36     static assert (resolveName!(S.field2).full == "renamed");
37     static assert (resolveName!(S.field2).single == 'r');
38 }
39 
40 private void readConfigurationImpl (S) (ref S dst, string[] src)
41 {
42     import std.traits;
43     import std.algorithm;
44     import std.range.primitives;
45     import std.conv;
46 
47     rt: foreach (idx, arg; src)
48     {
49         bool assign = false;
50 
51         static foreach (Field; getSymbolsByUDA!(S, CLI))
52         {
53             if (arg.startsWith("--"))
54                 assign = resolveName!Field.full == arg[2 .. $];
55             else if (arg.startsWith("-"))
56                 assign = resolveName!Field.single == arg[1 .. $].front;
57 
58             if (assign)
59             {
60                 auto pfield = &__traits(getMember, dst, __traits(identifier, Field));
61                 *pfield = to!(typeof(*pfield))(src[idx + 1]);
62                 continue rt;
63             }
64         }
65     }
66 }
67 
68 unittest
69 {
70     struct Config
71     {
72         @cli
73         string field1;
74         @cli("alias")
75         int field2;
76         @cli("long|l")
77         string field3;
78         string field4;
79     }
80 
81     Config config;
82 
83     readConfigurationImpl(config, [
84         "--field1", "value1",
85         "--alias", "42",
86         "-l", "value3",
87         "--field4", "ignored"
88     ]);
89 
90     assert(config.field1 == "value1");
91     assert(config.field2 == 42);
92     assert(config.field3 == "value3");
93     assert(config.field4 == "");
94 }