[Groovy] Class CliBuilder

  • groovy.cli.picocli.CliBuilder

Provides a builder to assist the processing of command line arguments. Two styles are supported: dynamic api style (declarative method calls provide a mini DSL for describing options) and annotation style (annotations on an interface or class describe options).

Dynamic api style

Typical usage (emulate partial arg processing of unix command: ls -alt *.groovy):

 def cli = new CliBuilder(name:'ls')
 cli.a('display all files')
 cli.l('use a long listing format')
 cli.t('sort by modification time')
 def options = cli.parse(args)
 assert options // would be null (false) on failure
 assert options.arguments() == ['*.groovy']
 assert options.a && options.l && options.t
 
The usage message for this example (obtained using cli.usage()) is shown below:
 Usage: ls [-alt]
   -a     display all files
   -l     use a long listing format
   -t     sort by modification time
 
An underlying parser that supports what is called argument 'bursting' is used by default. Bursting would convert '-alt' into '-a -l -t' provided no long option exists with value 'alt' and provided that none of 'a', 'l' or 't' takes an argument (in fact the last one is allowed to take an argument). The bursting behavior can be turned off by configuring the underlying parser. The simplest way to achieve this is by setting the posix property on the CliBuilder to false, i.e. include posix: false in the constructor call.

Another example (partial emulation of arg processing for 'ant' command line):

 def cli = new CliBuilder(usage:'ant [options] [targets]',
                          header:'Options:')
 cli.help('print this message')
 cli.logfile(type:File, argName:'file', 'use given file for log')
 cli.D(type:Map, argName:'property=value', 'use value for given property')
 cli.lib(argName:'path', valueSeparator:',', args: '3',
      'comma-separated list of 3 paths to search for jars and classes')
 def options = cli.parse(args)
 ...
 
Usage message would be:
 Usage: ant [options] [targets]
 Options:
   -D= <property=value>   use value for given property
       -help              print this message
       -lib=<path>,<path>,<path>
                          comma-separated list of 3 paths to search for jars and
                            classes
       -logfile=<file>    use given file for log
 
And if called with the following arguments '-logfile foo -Dbar=baz -lib=/tmp,/usr/lib,~/libs target' then the following assertions would be true:
 assert options // would be null (false) on failure
 assert options.arguments() == ['target']
 assert options.D == ['bar': 'baz']
 assert options.libs == ['/tmp', '/usr/lib', '~/libs']
 assert options.lib == '/tmp'
 assert options.logfile == new File('foo')
 
Note the use of some special notation. By adding 's' onto an option that may appear multiple times and has an argument or as in this case uses a valueSeparator to separate multiple argument values causes the list of associated argument values to be returned.

Another example showing long options (partial emulation of arg processing for 'curl' command line):

 def cli = new CliBuilder(name:'curl')
 cli._(longOpt:'basic', 'Use HTTP Basic Authentication')
 cli.d(longOpt:'data', args:1, argName:'data', 'HTTP POST data')
 cli.G(longOpt:'get', 'Send the -d data with a HTTP GET')
 cli.q('If used as the first parameter disables .curlrc')
 cli._(longOpt:'url', type:URL, argName:'URL', 'Set URL to work with')
 
Which has the following usage message:
 Usage: curl [-Gq] [--basic] [--url=<URL>] [-d=<data>]
       --basic         Use HTTP Basic Authentication
   -d, --data=<data>   HTTP POST data
   -G, --get           Send the -d data with a HTTP GET
   -q                  If used as the first parameter disables .curlrc
       --url=<URL>     Set URL to work with
 
This example shows a common convention. When mixing short and long names, the short names are often one character in size. One character options with arguments don't require a space between the option and the argument, e.g. -Ddebug=true. The example also shows the use of '_' when no short option is applicable.

Also note that '_' was used multiple times. This is supported but if any other shortOpt or any longOpt is repeated, then the underlying library throws an exception.

Short option names may not contain a hyphen. If a long option name contains a hyphen, e.g. '--max-wait' then you can either use the long hand method call options.hasOption('max-wait') or surround the option name in quotes, e.g. options.'max-wait'.

Although CliBuilder on the whole hides away the underlying library used for processing the arguments, it does provide some hooks which let you make use of the underlying library directly should the need arise. For example, the last two lines of the 'curl' example above could be replaced with the following:

 import picocli.CommandLine.Model.*
 ... as before ...
 cli << OptionSpec.builder('-q').
                      description('If used as the first parameter disables .curlrc').build()
 cli << OptionSpec.builder('--url').type(URL.class).paramLabel('<URL>').
                      description('Set URL to work with').build()
 ...
 
As another example, the usageMessage property gives fine-grained control over the usage help message (see the picocli user manual for details):
 def cli = new CliBuilder()
 cli.name = "myapp"
 cli.usageMessage.with {
     headerHeading("@|bold,underline Header heading:|@%n")
     header("Header 1", "Header 2")                     // before the synopsis
     synopsisHeading("%n@|bold,underline Usage:|@ ")
     descriptionHeading("%n@|bold,underline Description heading:|@%n")
     description("Description 1", "Description 2")      // after the synopsis
     optionListHeading("%n@|bold,underline Options heading:|@%n")
     footerHeading("%n@|bold,underline Footer heading:|@%n")
     footer("Footer 1", "Footer 2")
 }

Supported Option Properties:

Property Type Picocli equivalent Description
argName String names Short name for the option, will be prefixed with a single hyphen.
longOpt String names Long name for the option, will be prefixed with two hyphens unless acceptLongOptionsWithSingleHyphen is true. An option must have either a long name or a short name (or both).
args int or String arity args indicates the number of parameters for this option. A String value of '+' indicates at least one up to any number of parameters. The minimum number of parameters depends on the type (booleans require no parameters) and the optionalArg setting. args can often be omitted if a type is specified.
optionalArg boolean arity If optionalArg=true, then args=3 is the equivalent of arity="0..3" in picocli. When optionalArg=true, args='+' is equivalent to arity="0..*".
required boolean required If true, this option must be specified on the command line, or an exception is thrown.
type Class type Option parameters are converted to this type. The underlying library has built-in converters for many types. A custom converter can be specified with the convert property.
convert Closure converter A closure that takes a single String parameter and returns an object converted to the type of this option. The picocli equivalent is the ITypeConverter interface.
valueSeparator char splitRegex The character used to split a single command line argument into parts.
defaultValue String defaultValue The value the option should have if it did not appear on the command line. The specified String value will be split into parts with the valueSeparator and converted to the option type before it is set.
See groovy.cli.picocli.CliBuilderTest for further examples.

@-files

CliBuilder also supports Argument File processing. If an argument starts with an '@' character followed by a filename, then the contents of the file with name filename are placed into the command line. The feature can be turned off by setting expandArgumentFiles to false. If turned on, you can still pass a real parameter with an initial '@' character by escaping it with an additional '@' symbol, e.g. '@@foo' will become '@foo' and not be subject to expansion. As an example, if the file temp.args contains the content:

 -arg1
 paramA
 paramB paramC
 
Then calling the command line with:
 someCommand
temp.args:
-arg2 paramD Is the same as calling this:
 someCommand -arg1 paramA paramB paramC -arg2 paramD
 
This feature is particularly useful on operating systems which place limitations on the size of the command line (e.g. Windows). The feature is similar to the 'Command Line Argument File' processing supported by javadoc and javac. Consult the corresponding documentation for those tools if you wish to see further examples.

Annotation style with an interface

With this style an interface is defined containing an annotated method for each option. It might look like this (following roughly the earlier 'ls' example):

 import groovy.cli.Option
 import groovy.cli.Unparsed

 interface OptionInterface {
@Option(shortName='a', description='display all files') boolean all() @Option(shortName='l', description='use a long listing format') boolean longFormat() @Option(shortName='t', description='sort by modification time') boolean time() @Unparsed List remaining() } Then this description is supplied to CliBuilder during parsing, e.g.:
 def args = '-alt *.groovy'.split() // normally from commandline itself
 def cli = new CliBuilder(usage:'ls')
 def options = cli.parseFromSpec(OptionInterface, args)
 assert options.remaining() == ['*.groovy']
 assert options.all() && options.longFormat() && options.time()
 

Annotation style with a class

With this style a user-supplied instance is used. Annotations on that instance's class members (properties and setter methods) indicate how to set options and provide the option details using annotation attributes. It might look like this (again using the earlier 'ls' example):

 import groovy.cli.Option
 import groovy.cli.Unparsed

 class OptionClass {
     @Option(shortName='a', description='display all files') boolean all
     @Option(shortName='l', description='use a long listing format') boolean longFormat
     @Option(shortName='t', description='sort by modification time') boolean time
     @Unparsed List remaining
 }
 
Then this description is supplied to CliBuilder during parsing, e.g.:
 def args = '-alt *.groovy'.split() // normally from commandline itself
 def cli = new CliBuilder(usage:'ls')
 def options = new OptionClass()
 cli.parseFromInstance(options, args)
 assert options.remaining == ['*.groovy']
 assert options.all && options.longFormat && options.time
 

Properties Summary

Properties
Type Name and description
boolean acceptLongOptionsWithSingleHyphen
For backwards compatibility with Apache Commons CLI, set this property to true if the parser should recognize long options with both a single hyphen and a double hyphen prefix.
PrintWriter errorWriter
The PrintWriter to write to when invalid user input was provided to the parse(java.lang.String[]) method.
boolean expandArgumentFiles
Whether arguments of the form '@filename' will be expanded into the arguments contained within the file named filename (default true).
String footer
Optional additional message for usage; displayed after the options.
String header
Optional additional message for usage; displayed after the usage summary but before the options are displayed.
String name
This property allows customizing the program name displayed in the synopsis when cli.usage() is called.
ParserSpec parser
Not normally accessed directly but allows fine-grained control over the parser behaviour via the API of the underlying library if needed.
Boolean posix
To disallow clustered POSIX short options, set this to false.
Map<String, TypedOption> savedTypeOptions
Internal data structure mapping option names to their associated TypedOption object.
boolean stopAtNonOption
Configures what the parser should do when arguments not recognized as options are encountered: when true (the default), the remaining arguments are all treated as positional parameters.
String usage
The command synopsis displayed as the first line in the usage help message, e.g., when cli.usage() is called.
UsageMessageSpec usageMessage
Not normally accessed directly but allows fine-grained control over the usage help message via the API of the underlying library if needed.
int width
Allows customisation of the usage message width.
PrintWriter writer
The PrintWriter to write the usage help message to when cli.usage() is called.

Methods Summary

Methods
Type Params Return Type Name and description
def invokeMethod(String name, Object args)
Internal method: Detect option specification method calls.
<T> TypedOption<T> option(Map args, Class<T> type, String description)
OptionSpec option(def shortname, Map details, def description)
Internal method: How to create an OptionSpec from the specification.
OptionAccessor parse(def args)
Make options accessible from command line args with parser.
<T> T parseFromInstance(T optionInstance, def args)
Given an instance containing members with annotations, derive the options specification.
<T> T parseFromSpec(Class<T> optionsClass, String[] args)
Given an interface containing members with annotations, derive the options specification.
void setExpandArgumentFiles(boolean expand)
Sets the expandArgumentFiles property on this CliBuilder and on the parser used by the underlying library.
void setFooter(String footer)
Sets the footer property on this CliBuilder and on the usageMessage used by the underlying library.
void setHeader(String header)
Sets the header property on this CliBuilder and the description on the usageMessage used by the underlying library.
void setPosix(Boolean posix)
Sets the posix property on this CliBuilder and the posixClusteredShortOptionsAllowed property on the parser used by the underlying library.
void setStopAtNonOption(boolean stopAtNonOption)
Sets the stopAtNonOption property on this CliBuilder and the stopAtPositional property on the parser used by the underlying library.
void setUsage(String usage)
Sets the usage property on this CliBuilder and the customSynopsis on the usageMessage used by the underlying library.
void setWidth(int width)
Sets the width property on this CliBuilder and on the usageMessage used by the underlying library.
void setWriter(PrintWriter writer)
For backwards compatibility reasons, if a custom writer is set, this sets both the writer and the errorWriter to the specified writer.
void usage()
Prints the usage message with the specified header, footer and width to the specified writer (default: System.out).

Inherited Methods Summary

Inherited Methods
Methods inherited from class Name
class Object wait, wait, wait, equals, toString, hashCode, getClass, notify, notifyAll

Property Detail

boolean acceptLongOptionsWithSingleHyphen

For backwards compatibility with Apache Commons CLI, set this property to true if the parser should recognize long options with both a single hyphen and a double hyphen prefix. The default is false, so only long options with a double hypen prefix (--option) are recognized.

Since:
2.5

PrintWriter errorWriter

The PrintWriter to write to when invalid user input was provided to the parse(java.lang.String[]) method. Defaults to stderr but you can provide your own PrintWriter if desired.

Since:
2.5

boolean expandArgumentFiles

Whether arguments of the form '@filename' will be expanded into the arguments contained within the file named filename (default true).

Optional additional message for usage; displayed after the options.

Optional additional message for usage; displayed after the usage summary but before the options are displayed.

String name

This property allows customizing the program name displayed in the synopsis when cli.usage() is called. Ignored if the usage property is set.

Since:
2.5

final ParserSpec parser

Not normally accessed directly but allows fine-grained control over the parser behaviour via the API of the underlying library if needed.

Since:
2.5

Boolean posix

To disallow clustered POSIX short options, set this to false.

Map<String, TypedOption> savedTypeOptions

Internal data structure mapping option names to their associated TypedOption object.

boolean stopAtNonOption

Configures what the parser should do when arguments not recognized as options are encountered: when true (the default), the remaining arguments are all treated as positional parameters. When false, the parser will continue to look for options, and only the unrecognized arguments are treated as positional parameters.

String usage

The command synopsis displayed as the first line in the usage help message, e.g., when cli.usage() is called. When not set, a default synopsis is generated that shows the supported options and parameters.

See Also:
name

final UsageMessageSpec usageMessage

Not normally accessed directly but allows fine-grained control over the usage help message via the API of the underlying library if needed.

Since:
2.5

int width

Allows customisation of the usage message width.

PrintWriter writer

The PrintWriter to write the usage help message to when cli.usage() is called. Defaults to stdout but you can provide your own PrintWriter if desired.

Method Detail

def invokeMethod(String name, Object args)

Internal method: Detect option specification method calls.

<T> TypedOption<T> option(Map args, Class<T> type, String description)

OptionSpec option(def shortname, Map details, def description)

Internal method: How to create an OptionSpec from the specification.

OptionAccessor parse(def args)

Make options accessible from command line args with parser. Returns null on bad command lines after displaying usage message.

<T> T parseFromInstance(T optionInstance, def args)

Given an instance containing members with annotations, derive the options specification.

Parameters:
optionInstance
args
Returns:
the options instance populated with the processed options

<T> T parseFromSpec(Class<T> optionsClass, String[] args)

Given an interface containing members with annotations, derive the options specification.

Parameters:
optionsClass
args
Returns:
an instance containing the processed options

void setExpandArgumentFiles(boolean expand)

Sets the expandArgumentFiles property on this CliBuilder and on the parser used by the underlying library. @-files

Parameters:
expand - whether to expand argument

void setFooter(String footer)

Sets the footer property on this CliBuilder and on the usageMessage used by the underlying library.

Parameters:
footer - the footer of the usage help message

void setHeader(String header)

Sets the header property on this CliBuilder and the description on the usageMessage used by the underlying library.

Parameters:
header - the description text of the usage help message

void setPosix(Boolean posix)

Sets the posix property on this CliBuilder and the posixClusteredShortOptionsAllowed property on the parser used by the underlying library.

Parameters:
posix - whether to allow clustered short options

void setStopAtNonOption(boolean stopAtNonOption)

Sets the stopAtNonOption property on this CliBuilder and the stopAtPositional property on the parser used by the underlying library.

Parameters:
stopAtNonOption - when true (the default), the remaining arguments are all treated as positional parameters. When false, the parser will continue to look for options, and only the unrecognized arguments are treated as positional parameters.

void setUsage(String usage)

Sets the usage property on this CliBuilder and the customSynopsis on the usageMessage used by the underlying library.

Parameters:
usage - the custom synopsis of the usage help message

void setWidth(int width)

Sets the width property on this CliBuilder and on the usageMessage used by the underlying library.

Parameters:
width - the width of the usage help message

void setWriter(PrintWriter writer)

For backwards compatibility reasons, if a custom writer is set, this sets both the writer and the errorWriter to the specified writer.

Parameters:
writer - the writer to initialize both the writer and the errorWriter to

void usage()

Prints the usage message with the specified header, footer and width to the specified writer (default: System.out).

© 2003-2020 The Apache Software Foundation
Licensed under the Apache license.
https://docs.groovy-lang.org/2.5.14/html/gapi/groovy/cli/picocli/CliBuilder.html