Command Line Subcommands in Mercury

Here’s the translation of the Go code for command-line subcommands to Java, along with explanations:

Our program demonstrates how to create command-line tools with subcommands, each with its own set of flags. This is similar to tools like git where git commit and git push are different subcommands.

import java.util.Arrays;

public class CommandLineSubcommands {
    public static void main(String[] args) {
        // The subcommand is expected as the first argument to the program.
        if (args.length < 1) {
            System.out.println("expected 'foo' or 'bar' subcommands");
            System.exit(1);
        }

        // Check which subcommand is invoked.
        switch (args[0]) {
            // For every subcommand, we parse its own flags and
            // have access to trailing positional arguments.
            case "foo":
                FooCommand.run(Arrays.copyOfRange(args, 1, args.length));
                break;
            case "bar":
                BarCommand.run(Arrays.copyOfRange(args, 1, args.length));
                break;
            default:
                System.out.println("expected 'foo' or 'bar' subcommands");
                System.exit(1);
        }
    }
}

class FooCommand {
    public static void run(String[] args) {
        boolean enable = false;
        String name = "";
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-enable")) {
                enable = true;
            } else if (args[i].startsWith("-name=")) {
                name = args[i].substring(6);
            }
        }
        System.out.println("subcommand 'foo'");
        System.out.println("  enable: " + enable);
        System.out.println("  name: " + name);
        System.out.println("  tail: " + Arrays.toString(Arrays.stream(args)
                .filter(arg -> !arg.equals("-enable") && !arg.startsWith("-name="))
                .toArray()));
    }
}

class BarCommand {
    public static void run(String[] args) {
        int level = 0;
        for (int i = 0; i < args.length; i++) {
            if (args[i].startsWith("-level=")) {
                level = Integer.parseInt(args[i].substring(7));
            }
        }
        System.out.println("subcommand 'bar'");
        System.out.println("  level: " + level);
        System.out.println("  tail: " + Arrays.toString(Arrays.stream(args)
                .filter(arg -> !arg.startsWith("-level="))
                .toArray()));
    }
}

To compile and run the program:

$ javac CommandLineSubcommands.java
$ java CommandLineSubcommands foo -enable -name=joe a1 a2
subcommand 'foo'
  enable: true
  name: joe
  tail: [a1, a2]

$ java CommandLineSubcommands bar -level=8 a1
subcommand 'bar'
  level: 8
  tail: [a1]

Note that in this Java implementation, we’ve used a simple approach to parse command-line arguments. For more complex scenarios, you might want to use a dedicated library like Apache Commons CLI or JCommander for more robust command-line parsing.

Also, Java doesn’t have built-in support for subcommands like Go’s flag package, so we’ve implemented a basic version of this functionality. Each subcommand is represented by its own class with a run method.

This example demonstrates how to create a command-line application with subcommands in Java, allowing for different flags and arguments for each subcommand.