ddn.util.docopt¶
This page provides runnable, everyday examples for parsing command lines with the ddn.util.docopt module.
All examples are designed to be copied into a single .d file and run via:
1) Parse flags and arguments¶
This example shows basic parsing of positional arguments and options.
#!/usr/bin/env dub
/+ dub.sdl:
name "docopt-basic"
dependency "ddn" version="*"
+/
module examples.docopt_basic;
import std.stdio : writeln, writefln;
import ddn.util.docopt;
enum DOC = q{
Basic demo.
Usage:
basic greet <name> [--shout]
basic (-h | --help)
Options:
-h --help Show this help.
--shout Uppercase the greeting.
};
void main(string[] args) {
// Drop program name.
auto argv = args.length > 1 ? args[1 .. $] : cast(string[])[];
try {
auto m = docopt(DOC, argv);
auto name = m["<name>"].asString;
auto shout = m["--shout"].isTrue;
auto msg = "Hello, " ~ name ~ "!";
if (shout) {
import std.string : toUpper;
msg = msg.toUpper;
}
writeln(msg);
} catch (DocoptExitHelp e) {
// Triggered by -h/--help.
writeln(e.msg);
} catch (DocoptArgumentError e) {
// Friendly user-facing parse errors.
writefln("Error: %s", e.msg);
}
}
Run:
dub run --single example.d -- greet Alice
dub run --single example.d -- greet Alice --shout
dub run --single example.d -- --help
2) Subcommands + defaults (including env var defaults)¶
This example demonstrates:
- Multiple subcommands
- A numeric option with a default
- An option defaulted from an environment variable
#!/usr/bin/env dub
/+ dub.sdl:
name "docopt-subcommands"
dependency "ddn" version="*"
+/
module examples.docopt_subcommands;
import std.stdio : writeln, writefln;
import std.conv : to;
import ddn.util.docopt;
enum VERSION = "subcommands-demo 1.0.0";
enum DOC = q{
subcommands-demo.
Usage:
tool greet <name> [--times=<n>] [--config=<file>]
tool sum <n>...
tool (--help | --version)
Options:
--help Show this help.
--version Show version.
-t --times=<n> Repeat times [default: 1]
-c --config=<file> Config file [default: $CONFIG_FILE or config.json]
};
void main(string[] args) {
auto argv = args.length > 1 ? args[1 .. $] : cast(string[])[];
try {
auto m = docopt(DOC, argv, true, VERSION, false);
if (m["greet"].isTrue) {
const name = m["<name>"].asString;
const times = m["--times"].as!long;
const config = m["--config"].asString;
foreach (_; 0 .. times)
writeln("Hello, " ~ name ~ "!");
writefln("(config: %s)", config);
} else if (m["sum"].isTrue) {
const(string[]) nums = m["<n>"].as!(const(string[]));
long total = 0;
foreach (s; nums)
total += s.to!long;
writefln("sum = %s", total);
}
} catch (DocoptExitHelp e) {
writeln(e.msg);
} catch (DocoptArgumentError e) {
writefln("Error: %s", e.msg);
}
}
Run:
dub run --single example.d -- greet Bob
CONFIG_FILE=custom.json dub run --single example.d -- greet Bob --times=2
dub run --single example.d -- sum 10 20 30
dub run --single example.d -- --version
3) CTFE pre-parsing of the doc string¶
If your tool parses the same doc string many times, you can pre-parse at compile time.
#!/usr/bin/env dub
/+ dub.sdl:
name "docopt-ctfe"
dependency "ddn" version="*"
+/
module examples.docopt_ctfe;
import std.stdio : writeln;
import ddn.util.docopt;
enum DOC = q{
ctfe-demo.
Usage:
ctfe <name>
};
// Parse at compile-time.
enum PRE = parseDocopt!DOC;
void main(string[] args) {
auto argv = args.length > 1 ? args[1 .. $] : cast(string[])[];
auto m = docopt(PRE, argv);
writeln("name = ", m["<name>"].asString);
}
Run: