Command Line Subcommands in D Programming Language

Here’s the translation of the Go code to D programming language, formatted in Markdown suitable for Hugo:

Our first program demonstrates how to create command-line subcommands with their own set of flags. This is similar to tools like git where different subcommands (git commit, git push) have their own specific flags.

import std.stdio;
import std.getopt;
import std.algorithm : among;

void main(string[] args)
{
    if (args.length < 2)
    {
        writeln("expected 'foo' or 'bar' subcommands");
        return;
    }

    switch (args[1])
    {
    case "foo":
        bool enable = false;
        string name = "";
        auto fooArgs = args[2 .. $];
        auto fooOpts = getopt(fooArgs,
            "enable", &enable,
            "name", &name);

        if (fooOpts.helpWanted)
        {
            defaultGetoptPrinter("Usage: foo [options]", fooOpts.options);
            return;
        }

        writeln("subcommand 'foo'");
        writeln("  enable:", enable);
        writeln("  name:", name);
        writeln("  tail:", fooArgs);
        break;

    case "bar":
        int level = 0;
        auto barArgs = args[2 .. $];
        auto barOpts = getopt(barArgs,
            "level", &level);

        if (barOpts.helpWanted)
        {
            defaultGetoptPrinter("Usage: bar [options]", barOpts.options);
            return;
        }

        writeln("subcommand 'bar'");
        writeln("  level:", level);
        writeln("  tail:", barArgs);
        break;

    default:
        writeln("expected 'foo' or 'bar' subcommands");
        return;
    }
}

To compile and run the program:

$ dmd command_line_subcommands.d
$ ./command_line_subcommands foo --enable --name=joe a1 a2
subcommand 'foo'
  enable:true
  name:joe
  tail:["a1", "a2"]

$ ./command_line_subcommands bar --level=8 a1
subcommand 'bar'
  level:8
  tail:["a1"]

$ ./command_line_subcommands bar --enable a1
bar: unrecognized option '--enable'
Usage: bar [options]
 --level The level option
 -h --help This help information.

In this D version, we use the std.getopt module to handle command-line argument parsing. The getopt function is used to define and parse flags for each subcommand.

The program structure is similar to the original, with a main switch statement to handle different subcommands. Each subcommand has its own set of flags defined using getopt.

Note that D’s getopt automatically provides a --help flag, which we handle by checking the helpWanted property of the GetoptResult returned by getopt.

The D version doesn’t require explicit type declarations for the flag variables (enable, name, level) as the types are inferred from the default values or usage.

This example demonstrates how to create a command-line tool with subcommands in D, each with its own set of flags, similar to tools like git or dub (D’s package manager).