ddn.util.docopt¶
The ddn.util.docopt module provides an idiomatic D implementation of the docopt command-line interface description language parser. It allows you to define your program's CLI by simply writing a help message.
Overview¶
Docopt is a language for describing command-line interfaces. Instead of writing code to parse arguments, you write a help message that describes your interface, and docopt parses the arguments accordingly. This approach ensures your help text and argument parsing are always in sync.
This module is based on the Python docopt package and provides full support for commands, options, arguments, and complex usage patterns.
Key Features¶
- Help Message as Interface Definition: Define your CLI by writing a human-readable help message
- CTFE Pre-Parsing: Parse the docstring at compile time for zero runtime overhead
- Short and Long Options: Support for
-v,--verbose, and combined forms like-v --verbose - Option Arguments: Options with values like
--speed=<kn>or-s <kn> - Default Values: Specify defaults in the options section with
[default: value] - Environment Variable Defaults: Use
[default: $VAR or fallback]syntax - Commands and Subcommands: Support for command-based interfaces like
git commit - Positional Arguments: Required arguments like
<file>and optional ones like[<file>] - Repeating Elements: Support for
...to indicate repeating arguments - Mutually Exclusive Groups: Use
(a | b)for alternatives - Optional Groups: Use
[options]for optional elements
Basic Usage¶
import ddn.util.docopt;
import std.stdio;
enum DOC = `
Naval Fate.
Usage:
naval_fate ship new <name>...
naval_fate ship <name> move <x> <y> [--speed=<kn>]
naval_fate ship shoot <x> <y>
naval_fate mine (set|remove) <x> <y> [--moored | --drifting]
naval_fate (-h | --help)
naval_fate --version
Options:
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--moored Moored (anchored) mine.
--drifting Drifting mine.
`;
void main(string[] args) {
auto arguments = docopt(DOC, args[1..$], true, "Naval Fate 2.0");
if (arguments["ship"].isTrue) {
if (arguments["new"].isTrue) {
writeln("Creating new ship(s): ", arguments["<name>"]);
} else if (arguments["move"].isTrue) {
writefln("Moving %s to (%s, %s) at %s knots",
arguments["<name>"], arguments["<x>"], arguments["<y>"],
arguments["--speed"]);
}
}
}
CTFE Pre-Parsing¶
For better performance, you can pre-parse the docstring at compile time:
import ddn.util.docopt;
enum DOC = `
Usage:
prog greet <name> [--times=<n>] [--shout]
prog sum <nums>...
prog (-h | --help)
Options:
-h --help Show this help.
-t --times=<n> Repeat times [default: 1]
-s --shout Uppercase output.
`;
// Pre-parse at compile time
enum PRE = parseDocopt!DOC;
void main(string[] args) {
// Use pre-parsed descriptor at runtime
auto arguments = docopt(PRE, args[1..$], true, "1.0.0", false);
if (arguments["greet"].isTrue) {
auto name = arguments["<name>"].asString;
auto times = arguments["--times"].as!long;
// ...
}
}
Environment Variable Defaults¶
You can specify environment variables as default values:
enum DOC = `
Usage:
prog [--config=<file>]
Options:
--config=<file> Config file [default: $CONFIG_FILE or config.json]
`;
If CONFIG_FILE environment variable is set, its value is used; otherwise, config.json is the default.
Working with Parsed Arguments¶
The docopt function returns an ArgMap containing all parsed values:
auto args = docopt(DOC, argv);
// Check if a flag/command is set
if (args["--verbose"].isTrue) { ... }
// Get string value
string filename = args["<file>"].asString;
// Get typed value
long count = args["--count"].as!long;
// Get array of values (for repeating arguments)
const(string[]) files = args["<files>"].as!(const(string[]));
// Check if value is null/not provided
if (args["--optional"].isNull) { ... }
Exception Handling¶
The module provides three exception types:
DocoptLanguageError: Thrown when the docstring itself is malformedDocoptArgumentError: Thrown when user provides invalid argumentsDocoptExitHelp: Thrown when--helpor--versionis requested
try {
auto args = docopt(DOC, argv, true, "1.0.0");
} catch (DocoptExitHelp e) {
writeln(e.msg); // Print help or version
} catch (DocoptArgumentError e) {
writeln("Error: ", e.msg);
}
Usage Pattern Syntax¶
| Pattern | Description |
|---|---|
<argument> |
Positional argument |
--option |
Long option (flag) |
-o |
Short option |
--option=<value> |
Option with required value |
[optional] |
Optional element |
(required) |
Required element (grouping) |
element... |
Repeating element |
a \| b |
Mutually exclusive alternatives |
[options] |
All defined options |
command |
Command/subcommand |
When to Use¶
Use this module when you need to:
- Build command-line applications with complex argument patterns
- Keep help text and argument parsing synchronized
- Support subcommands, options with defaults, and repeating arguments
- Provide user-friendly error messages for invalid input