1 /**
2  * This generative method creates a getopt call based on the
3  * attributes assign to  a structure.
4  *
5  * ```
6 import structopt;
7 
8 // Specify The Parameter Structure
9 struct Options
10 {
11     @Option("threads", "t")
12     @Help("Number of threads to use.")
13     size_t threads;
14 
15     @Option("file")
16     @Help("Input files")
17     string[] files;
18 }
19 
20 void main(string[] args) {
21     Options props;
22 
23     // Pass in the struct to generate UDA for
24     auto helpInfo = mixin(GenerateGetopt!(props, args));
25 
26         defaultGetoptPrinter("Options: ",
27           helpInfo.options);
28         // Output to console:
29 
30         //Options:
31         //-t --threads Number of threads to use.
32         //      --file Input files
33         //-h    --help This help information./
34 }
35  * ```
36  */
37 module structopt;
38 
39 public import structopt.attributes;
40 public import std.getopt;
41 public import std.traits;
42 
43 @safe:
44 
45 /// Rename the Option struct of getopt
46 alias GetOption = std.getopt.Option;
47 /// Reastablish the name for the struct attributes
48 alias Option = structopt.attributes.Option;
49 
50 /**
51  * Generate the std.getopt method call.
52  */
53 string GenerateGetopt(alias Options, alias args)() pure nothrow {
54     import std.meta;
55     import std.typecons;
56     import std.format;
57     import std.conv;
58     auto ans = text("getopt(", args.stringof, ", ");
59     static foreach(opt; FieldNameTuple!(typeof(Options))) {
60         ans ~= text("getUDAs!(", Options.stringof, ".", opt, ", ");
61         ans ~= text(Option.stringof, ")", "[0].cononical(),");
62         ans ~= text(" getUDAs!(", Options.stringof, ".", opt, ", ");
63         ans ~= text(Help.stringof, ")[0].msg,");
64         ans ~= text(" &", Options.stringof, ".", opt, ",");
65     }
66 
67     return ans ~ ")";
68 }
69 ///
70 unittest {
71     // Specify The Parameter Structure
72     struct Options
73     {
74         @Option("threads", "t")
75         @Help("Number of threads to use.")
76         size_t threads;
77 
78         @Option("file")
79         @Help("Input files")
80         string[] files;
81     }
82 
83     Options props;
84     string[] arg = ["./structopt", "t", "24"];
85 
86     // Pass in the struct to generate UDA for
87     auto helpInfo = mixin(GenerateGetopt!(props, arg));
88     auto expected = [
89         GetOption("-t", "--threads", "Number of threads to use.", false),
90         GetOption("", "--file", "Input files", false),
91         GetOption("-h", "--help", "This help information.", false)
92     ];
93 
94     import std.algorithm;
95     assert(helpInfo.options.equal(expected));
96 
97 }