Command Line Subcommands in Squirrel

Here’s the translation of the Go code to Java, with explanations in Markdown format suitable for Hugo:

Our first program will demonstrate how to create command-line subcommands with their own set of flags. This is similar to how tools like git have subcommands like git commit and git push, each with their own flags.

import java.util.Arrays;

public class CommandLineSubcommands {
    public static void main(String[] args) {
        // We declare subcommands and their flags using separate classes
        FooCommand fooCmd = new FooCommand();
        BarCommand barCmd = new BarCommand();

        // 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":
                fooCmd.parse(Arrays.copyOfRange(args, 1, args.length));
                System.out.println("subcommand 'foo'");
                System.out.println("  enable: " + fooCmd.enable);
                System.out.println("  name: " + fooCmd.name);
                System.out.println("  tail: " + Arrays.toString(fooCmd.remainingArgs));
                break;
            case "bar":
                barCmd.parse(Arrays.copyOfRange(args, 1, args.length));
                System.out.println("subcommand 'bar'");
                System.out.println("  level: " + barCmd.level);
                System.out.println("  tail: " + Arrays.toString(barCmd.remainingArgs));
                break;
            default:
                System.out.println("expected 'foo' or 'bar' subcommands");
                System.exit(1);
        }
    }
}

class FooCommand {
    boolean enable = false;
    String name = "";
    String[] remainingArgs;

    void parse(String[] args) {
        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);
            } else {
                remainingArgs = Arrays.copyOfRange(args, i, args.length);
                break;
            }
        }
    }
}

class BarCommand {
    int level = 0;
    String[] remainingArgs;

    void parse(String[] args) {
        for (int i = 0; i < args.length; i++) {
            if (args[i].startsWith("-level=")) {
                level = Integer.parseInt(args[i].substring(7));
            } else {
                remainingArgs = Arrays.copyOfRange(args, i, args.length);
                break;
            }
        }
    }
}

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]

Now try the bar subcommand:

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

But bar won’t accept foo’s flags:

$ java CommandLineSubcommands bar -enable a1
subcommand 'bar'
  level: 0
  tail: [-enable, a1]

In this Java implementation, we’ve created separate classes for each subcommand to handle their specific flags. The main class checks the first argument to determine which subcommand to execute, then delegates to the appropriate subcommand class for parsing the remaining arguments.

This approach allows for easy extension with new subcommands and provides a clean separation of concerns for handling different sets of flags.