Package: groovy.cli.commons

## [Groovy] Class CliBuilder

- groovy.cli.commons.CliBuilder

-     class CliBuilder
      extends Object

  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(usage:'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
        -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 using an alternate underlying parser. The simplest way to achieve this is by using the deprecated GnuParser from Commons CLI with the parser property on the CliBuilder, i.e. include `parser: new GnuParser()` 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(args:1, argName:'file', 'use given file for log')
       cli.D(args:2, valueSeparator:'=', argName:'property=value',
             'use value for given property')
       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
        -logfile <file>       use given file for log

  And if called with the following arguments '-logfile foo -Dbar=baz target' then the following assertions would be true:

       assert options // would be null (false) on failure
       assert options.arguments() == ['target']
       assert options.Ds == ['bar', 'baz']
       assert options.logfile == '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(usage:'curl [options] <url>')
       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', args:1, argName:'URL', 'Set URL to work with')

  Which has the following usage message:

       usage: curl [options] <url>
           --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 behavior is undefined.

  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 org.apache.commons.cli.*
       ... as before ...
       cli << new Option('q', false, 'If used as the first parameter disables .curlrc')
       cli << Option.builder().longOpt('url').hasArg().argName('URL').
                            desc('Set URL to work with').build()
       ...

  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:

       someCommandtemp.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.

  Supported Option Properties:

         argName:        String
         longOpt:        String
         args:           int or String
         optionalArg:    boolean
         required:       boolean
         type:           Class
         valueSeparator: char
         convert:        Closure
         defaultValue:   String

  See Option for the meaning of most of these properties and CliBuilderTest for 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` | `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 are displayed.
    `HelpFormatter` | `formatter` Normally set internally but can be overridden if you want to customise how the usage message is displayed.
    `String` | `header` Optional additional message for usage; displayed after the usage summary but before the options are displayed.
    `Options` | `options` Not normally accessed directly but full access to underlying options if needed.
    `CommandLineParser` | `parser` Normally set internally but allows you full customisation of the underlying processing engine.
    `Boolean` | `posix` To change from the default PosixParser to the GnuParser, set this to false.
    `Map<String, TypedOption>` | `savedTypeOptions` Typed option metadata keyed by long name or short name.
    `boolean` | `stopAtNonOption` Indicates that option processing should continue for all arguments even if arguments not recognized as options are encountered (default true).
    `String` | `usage` Usage summary displayed as the first line when `cli.usage()` is called.
    `int` | `width` Allows customisation of the usage message width.
    `PrintWriter` | `writer` Defaults to stdout but you can provide your own PrintWriter if desired.

  - ### Constructor Summary

    Constructors
    Constructor and description
    `CliBuilder()`

  - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `` | `void` | `addOptionsFromAnnotations(Class optionClass, boolean namesAreSetters)` Adds options declared with Option annotations to this builder.
    `` | `static Map` | `adjustDetails(Map m)` Normalizes DSL option details into Commons CLI-compatible values.
    `` | `static Object` | `expandArgumentFiles(Object args)` Expands `@file` arguments using command argument file semantics.
    `` | `Object` | `invokeMethod(String name, Object args)` Internal method: Detect option specification method calls.
    `<T>` | `TypedOption<T>` | `option(Map args, Class<T> type, String description)` Creates and registers a typed option definition.
    `` | `Option` | `option(Object shortname, Map details, Object info)` Internal method: How to create an option from the specification.
    `` | `OptionAccessor` | `parse(Object args)` Make options accessible from command line args with parser.
    `<T>` | `T` | `parseFromInstance(T optionInstance, Object 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.
    `` | `Object` | `setOptionsFromAnnotations(Object cli, Class optionClass, Object t, boolean namesAreSetters)` Applies parsed option values to an annotated target object or map.
    `` | `void` | `usage()` Print the usage message with writer (default: System.out) and formatter (default: HelpFormatter)

  - ### Inherited Methods Summary

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

- - ### Property Detail

    - #### 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 are displayed.

    - #### HelpFormatter formatter

      Normally set internally but can be overridden if you want to customise how the usage message is displayed.

    - #### String header

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

    - #### Options options

      Not normally accessed directly but full access to underlying options if needed.

    - #### CommandLineParser parser

      Normally set internally but allows you full customisation of the underlying processing engine.

    - #### @Deprecated
      Boolean posix

      To change from the default PosixParser to the GnuParser, set this to false. Ignored if the parser is explicitly set.

      deprecated:
        use the parser option instead with an instance of your preferred parser

    - #### Map<String, TypedOption> savedTypeOptions

      Typed option metadata keyed by long name or short name.

    - #### boolean stopAtNonOption

      Indicates that option processing should continue for all arguments even if arguments not recognized as options are encountered (default true).

    - #### String usage

      Usage summary displayed as the first line when `cli.usage()` is called.

    - #### int width

      Allows customisation of the usage message width.

    - #### PrintWriter writer

      Defaults to stdout but you can provide your own PrintWriter if desired.

  - ### Constructor Detail

    - #### CliBuilder()

  - ### Method Detail

    - #### void addOptionsFromAnnotations(Class optionClass, boolean namesAreSetters)

      Adds options declared with Option annotations to this builder.

      Parameters:
        `optionClass` - the annotated class or interface
        `namesAreSetters` - whether annotated methods should be treated as setters

    - #### static Map adjustDetails(Map m)

      Normalizes DSL option details into Commons CLI-compatible values.

      Parameters:
        `m` - the raw option details
      Returns:
        the normalized option details

    - #### static Object expandArgumentFiles(Object args)

      Expands `@file` arguments using command argument file semantics.

      throws:
        IOException if an argument file cannot be read
      Parameters:
        `args` - the original command-line arguments
      Returns:
        the arguments with any argument files expanded

    - #### Object invokeMethod(String name, Object args)

      Internal method: Detect option specification method calls.

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

      Creates and registers a typed option definition.

      Parameters:
        `args` - option attributes using the standard DSL keys
        `type` - the target type for the option value
        `description` - the option description
      Returns:
        the created typed option

    - #### Option option(Object shortname, Map details, Object info)

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

    - #### OptionAccessor parse(Object 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, Object 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

    - #### Object setOptionsFromAnnotations(Object cli, Class optionClass, Object t, boolean namesAreSetters)

      Applies parsed option values to an annotated target object or map.

      Parameters:
        `cli` - the parsed options accessor
        `optionClass` - the annotated class or interface
        `t` - the target object or backing map
        `namesAreSetters` - whether annotated methods should be treated as setters

    - #### void usage()

      Print the usage message with writer (default: System.out) and formatter (default: HelpFormatter)