ae.utils.funopt is a std.getopt enhancer:
import std.stdio, ae.utils.funopt; int run(bool verbose, string input, string output) { // ... return 0; } int main(string[] args) { try return funopt!run(args); catch (Exception e) { stderr.writeln("Error: ", e.msg); return 1; } }
Running program --verbose input.txt output.txt will cause run to be called with the appropriate arguments.
Additionally, funopt will generate and print a usage text if a mandatory parameter was not specified, or when --help is present:
$ program Usage: program [--verbose] INPUT OUTPUT Error: No input specified.
The usage text is generated from the function signature as a string constant during compilation. Optional arguments and arrays are handled appropriately.
If naked types are not sufficiently expressive, ae.utils.funopt provides some wrapper templates which allow specifying additional properties, such as a single-letter shorthand variant, --help descriptions, or non-boolean switches:
int run( Switch!("Enable verbose logging", 'v') verbose, Option!(int, "Number of tries") tries, Option!(int, "Seconds to wait each try", "SECS") timeout, string filename, string output = "default", string[] extraFiles = null, )
The automatically-generated usage for the above function signature will be:
Usage: program [OPTION]... FILENAME [OUTPUT] [EXTRA-FILES]... Options: -v, --verbose Enable verbose logging --tries=N Number of tries --timeout=SECS Seconds to wait each try
If your program has multiple sub-commands (as do e.g. git/hg/svn), ae.utils.funopt has a funoptDispatch function which can call an appropriate static method, as well as generate a list of actions for --help text:
import ae.utils.funopt; struct Actions { static: @(`Creates a new repository at this location.`) void init() { /* ... */ } @(`Pulls in changes from an existing repository at the given URL.`) void pull(bool shallow, bool recursive, string url) { /* ... */ } @(`Pushes changes to the repository at specified URL.`) void push(bool force, string url) { /* ... */ } } void main(string[] args) { return funoptDispatch!Actions(args); }
Method descriptions are currently specified using a string UDA, however it should be possible to move to documentation comments if/when DMD pull request #3531 is merged.
Example output:
$ scm --help Usage: scm ACTION [ACTION-ARGUMENTS]... Actions: init Creates a new repository at this location. pull Pulls in changes from an existing repository at the given URL. push Pushes changes to the repository at specified URL. $ scm pull --help Usage: scm pull [--shallow] [--recursive] URL
Code: ae.utils.funopt