How to Use Groovy's CliBuilder
Let’s use Groovy’s CliBuilder to create CLI programs that can take flags.
Intro
I write quite some scripts at work, either for myself or for my team. I
used to write these scripts in Bash, but since we are using Windows at
work, it made sense to switch to a more general scripting language.
Because we’re a Java shop, Groovy seemed like a natural choice. Now,
it’s often very convenient to have named command-line arguments (e.g.
tool --output out.ext --input in.ext) as opposed to positional
arguments (e.g. tool out.ext in.ext): named arguments allow for
putting the arguments in any order you want, and you can leave out
optional arguments and use the defaults. Groovy’s CliBuilder makes
things especially easy.
A sample program
weather.groovy
@Grab(group='commons-cli', module='commons-cli', version='1.4')
class Main {
    static main(args) {
        CommandLineInterface cli = CommandLineInterface.INSTANCE
        cli.parse(args)
    }
}
enum CommandLineInterface {
    INSTANCE
    CliBuilder cliBuilder
    CommandLineInterface() {
        cliBuilder = new CliBuilder(
                usage: 'weather [<options>]',
                header: 'Options:',
                footer: 'And here we put footer text.'
        )
        // set the amount of columns the usage message will be wide
        cliBuilder.width = 80  // default is 74
        cliBuilder.with {
            h longOpt: 'help', 'Print this help text and exit.'
            n(longOpt: 'max-count', args: 1, argName: 'number',
                    'Limit the number of days shown')
            '1' longOpt: 'one', "Show today's forecast"
            '2' longOpt: 'two', "Show today's and tomorrow's forecast"
            _(longOpt: 'url', args: 1, argName: 'URL',
                    'Use given URL to query for weather.')
            D(args: 2, valueSeparator: '=', argName: 'property=value',
                    'Use value for given property.')
        }
    }
    void parse(args) {
        OptionAccessor options = cliBuilder.parse(args)
        if (!options) {
            System.err << 'Error while parsing command-line options.\n'
            System.exit 1
        }
        if (options.h) {
            cliBuilder.usage()
            System.exit 0
        }
        if (options.n) {
            // handle user's input
        }
        if (options.'1') {
            // show weather for one day
        }
        if (options.url) {
            URI uri = new URI(options.url)
        }
        if (options.Ds) {
            assert options.Ds.class == ArrayList.class
        }
    }
}
When invoked with groovy weather.groovy --help, the program will
output:
usage: weather []
Options:
 -1,--one           Show today's forecast
 -2,--two           Show today's and tomorrow's forecast
 -D                 Use value for given property.
 -h,--help          Print this help text and exit.
 -n,--max-count     Limit the number of days shown
    --url           Use given URL to query for weather.
And here can put footer text.
You can specify short and long names: cliBuilder.n specifies that the
program will accept an argument -n. To also specify a long name, we
add longOpt: max-count. To use only a long name, we can replace the
short name by _: cliBuilder._(longName: 'wow-such-long'). Note that
cliBuilder._ can be reused several times (in contrast to other short
names).
The number of arguments can be indicated by using the args parameter.
If you use more than one parameter, a valueSeparator must be
indicated, which is used to split up the argument. I found that the
number assigned to args is not very strict: when called with argument
-Dmyprop, the following is valid.
assert options.Ds == ['myprop']
Note how we append an s to the option name (options.Ds) to get a
list of properties and values. A normal invocation groovy weather.groovy -Dpancakes=yesplease would result in:
assert options.Ds == ['pancakes', 'yesplease']
When required: true is set, the program will shout at you if the
argument is not used. For example, if we specify cliBuilder.q(required: true) but fail to provide the -q argument on the command line, the
program will exit with error: Missing required option: q.
One thing to remember is that, if you want to use digits as argument
names, you have to stringify them first by putting quotation marks
around them: cliBuilder.'1'.
More on CliBuilder
Check the Groovy documentation on CliBuilder for more information.
Dependencies
Groovy’s CliBuilder depends on cli-commons:
build.gradle
dependencies {
    compile group: 'commons-cli', name: 'commons-cli', version: '1.4'
}