dcli.program_options

Handles program options which are arguments passed with a leading - or -- and followed by a value

Features:

<li> Input validation <li> Customize seperators for associative array args <li> Supports environment variables <li> Supports default values <li> Supports custom types that have a constructor that is called with a string <li> You can supply custom types and they will be called with a string that you can parse

Enhancements_over_std.getopt:

<li> getopt(args) is destructive on args. <li> You cannot create your getopts and the parse later, which in combination with try/catch leads to awkward code <li> getopt doesn't accept $ ./program -p 3. For short opts, you have to do $ ./program -p3. <li> getopt doesn't allow case-sensitive short name and a case-insensitive long name <li> getopt will initialize an array type with the default values AND what the program arg was. <li> You cannot assign values to bundled short args, they are only incrementable <li> There is no way to handle what happens with duplicate arguments

Members

Classes

DuplicateProgramArgument
class DuplicateProgramArgument

Occurs if there's a duplicate argument

InvalidProgramArgument
class InvalidProgramArgument

Occurs when an argument does not validate

MalformedProgramArgument
class MalformedProgramArgument

Occurs when an argument is incorrectly formatted

MissingProgramArgument
class MissingProgramArgument

Occurs when a program argument is missing

ProgramOptionException
class ProgramOptionException

Thrown when an error occurs in parsing

Enums

OptionDuplicatePolicy
enum OptionDuplicatePolicy

The duplication policy can be passed to a ProgramOptions Option.duplicatePolicy

Structs

ProgramOptions
struct ProgramOptions(Options...)

You can configure a ProgramOptions object with a number of Options and then use it to parse and array of command line arguments.

Templates

Option
template Option(string varName, T)

Represents one program options. One of more of these can be given to a ProgramOptions object as template arguments.

Examples

1     import std.file: thisExePath;
2     import std.process: environment;
3 
4     environment["OPT_4"] = "22";
5 
6     auto args = [
7         thisExePath,            // Program name should be ignored
8         "program_name",         // Unknown argument, there's a handler for stray arguments
9         "--opt1", "value1",     // "--arg value" format
10         "-b", "1",              // "-a 1" format, case sensitive short name by default
11         "--Opt3=2",             // "--arg=value" format, case insesitive long name by default
12         // "--opt4",            // Set by an envaronment variable
13         "--OPT5", "4",          // first value of an int array
14         "--opt5", "5",          // second value of an int array
15         // "--opt6",            // Not set, will be give default value of int array
16         "--opt7", "9",          // Also an array
17         "--unknown", "ha",      // Unknown option and value
18         "--opt8=two",           // An enum vaue
19         "-i", "-j", "--incremental", "--opt9", // Option aliasing
20         "--opt10", "11",        // A validated, must be greater than 10
21         "--opt11", "3,4,5",     // Array format "--arg=v0,v1,v2"
22         "--opt12", "1=2::3=4::5=6", // Associative array with custom seperator (Default is ",")
23         "--opt13", "verbose",   // A custom parsed value - opt13 is an int
24         "-xyz=-7",              // Setting multiple, bundleable options at once
25         "--opt1", "value2",     // Uses duplication policy to be ignored
26         "--opt14", "1,2",       // Parses to a Custom type
27         "--opt15",              // Boolean, no value
28         "--",                   // Args after this are ignored
29         "extra",
30     ];
31 
32     enum Enum { one, two, }
33     static struct Custom {
34         int x;
35         int y;
36         this(int a, int b) {
37             x = a;
38             y = b;
39         }
40         this(string str) {
41             import std.string: split;
42             import std.conv: to;
43             auto parts = str.split(",");
44             x = parts[0].to!int;
45             y = parts[1].to!int;
46         }
47     }
48 
49     auto options = ProgramOptions!(
50         Option!("opt1", string)
51             .shortName!"a"
52             .description!"This is the description for option 1"
53             .duplicatePolicy!(OptionDuplicatePolicy.firstOneWins),
54         Option!("opt2", int)
55             .shortName!"b"
56             .description!"This is the description for option 2",
57         Option!("opt3", int)
58             .shortName!"B"
59             .description!(
60 `There are three kinds of comments:
61     1. Something rather sinister
62     2. And something else that's not so sinister`
63         ),
64         Option!("opt4", int)
65             .defaultValue!3
66             .environmentVar!"OPT_4"
67             .description!"THis is one that takes an env var",
68         Option!("opt5", int[])
69             .environmentVar!"OPT_5"
70             .description!"THis is one that takes an env var as well",
71         Option!("opt6", int[])
72             .defaultValue!([6, 7, 8]),
73         Option!("opt7", float[])
74             .defaultValue!([1, 2]),
75         Option!("opt8", Enum),
76         Option!("opt9", int)
77             .shortName!"i|j"
78             .longName!"incremental|opt9"
79             .incremental!true
80             .description!"sets some level incremental thingy",
81         Option!("opt10", int)
82             .validator!(a => a > 10),
83         Option!("opt11", int[]),
84         Option!("opt12", int[int])
85             .separator!"::",
86         Option!("opt13", int)
87             .parser!((value) {
88                 if (value == "verbose") return 7;
89                 return -1;
90             }),
91         Option!("b0", int)
92             .shortName!"x",
93         Option!("b1", int)
94             .shortName!"y",
95         Option!("b2", int)
96             .shortName!"z",
97         Option!("opt14", Custom),
98         Option!("opt15", bool),
99         Option!("opt16", bool)
100             .longName!""
101             .environmentVar!"OPT_16"
102             .description!"THis one only takes and envornment variable and cant be set with any flags",
103     )();
104 
105     string[] unknownArgs;
106     options.unknownArgHandler = (string name) {
107         unknownArgs ~= name;
108         return false;
109     };
110 
111     assert(options.parse(args) == ["extra"]);
112     assert(unknownArgs == ["program_name", "--unknown", "ha"]);
113 
114     assert(options.opt1 == "value1");
115     assert(options.opt2 == 1);
116     assert(options.opt3 == 2);
117     assert(options.opt4 == 22);
118     assert(options.opt5 == [4, 5]);
119     assert(options.opt6 == [6, 7, 8]);
120     assert(options.opt7 == [9]);
121     assert(options.opt8 == Enum.two);
122     assert(options.opt9 == 4);
123     assert(options.opt10 > 10);
124     assert(options.opt11 == [3, 4, 5]);
125     assert(options.opt12 == [1: 2, 3: 4, 5: 6]);
126     assert(options.opt13 == 7);
127     assert(options.b0 == -7);
128     assert(options.b1 == -7);
129     assert(options.b2 == -7);
130     assert(options.opt14 == Custom(1, 2));
131     assert(options.opt15 == true);
132 
133     assert(options.helpText ==
134 `Options:
135   -a  --opt1          This is the description for option 1
136   -b  --opt2          This is the description for option 2
137   -B  --opt3          There are three kinds of comments:
138                           1. Something rather sinister
139                           2. And something else that's not so sinister
140       --opt4          THis is one that takes an env var
141       --opt5          THis is one that takes an env var as well
142       --opt6
143       --opt7
144       --opt8
145   -i  --incremental   sets some level incremental thingy
146       --opt10
147       --opt11
148       --opt12
149       --opt13
150   -x  --b0
151   -y  --b1
152   -z  --b2
153       --opt14
154       --opt15
155 
156 Environment Vars:
157   OPT_4    See: --opt4
158   OPT_5    See: --opt5
159   OPT_16   THis one only takes and envornment variable and cant be set with any flags`
160   );

Meta