github remkop/picocli v4.2.0
Picocli 4.2.0

latest releases: v4.7.5, v4.7.4, v4.7.3...
4 years ago

Picocli 4.2.0

The picocli community is pleased to announce picocli 4.2.0.

This release adds support for Repeatable Subcommands: when a command is marked as @Command(subcommandsRepeatable = true) it becomes possible to specify that command's subcommands multiple times on the command line.

The picocli-codegen module can now generate AsciiDoc documentation for picocli-based applications. AsciiDoc is a lightweight markup language that can easily can be converted to unix man pages, HTML and PDF with the wonderful asciidoctor tool.

From this release, subcommands are not instantiated until they are matched on the command line. This should improve the startup time for applications with subcommands that do a lot of initialization when they are instantiated.

Autocompletion improvements: from this release the generated bash completions scripts support completing positional parameters, and are implemented without the use of associative arrays (so they should work on MacOS or other systems that use older versions of bash). Additionally there are now automated tests using Expect to verify that the generated completion scripts work as expected.

GraalVM configuration generation improvement: added --factory option to ReflectionConfigGenerator, ResourceConfigGenerator and DynamicProxyConfigGenerator. This makes it possible to generate configurations for command classes without a default no-arg constructor.

From this release it is possible to inject the CommandSpec into a IVersionProvider, making it easier to write version provider implementations that are reusable across multiple commands or even applications.

Similarly, from this release it is possible to inject the parent command object into mixins via a @ParentCommand-annotated field.

This release adds programmatic API to allow the long options column to grow larger than 20 characters in the usage help message via the CommandLine::setLongOptionsMaxWidth and UsageMessageSpec::longOptionsMaxWidth methods.

Finally, it is now possible let the usage help show that @-files are supported by listing a @<filename> entry above the list of positional parameters in the usage help.

This is the sixty-seventh public release.
Picocli follows semantic versioning.

Table of Contents

  • New and noteworthy
    • Generate AsciiDoc Documentation for Your Application
    • Repeatable Subcommands
    • Inject CommandSpec into a IVersionProvider
    • Subcommands are now lazily instantiated
    • Mixins with @ParentCommand-annotated fields
    • Showing @filename in usage help
    • Configurable long options column width
  • Fixed issues
  • Deprecations
  • Potential breaking changes

New and Noteworthy

Generate AsciiDoc Documentation for Your Application (convertable to unix man pages, HTML and PDF)

This release adds a new class picocli.codegen.docgen.manpage.ManPageGenerator to the picocli-codegen module that generates AsciiDoc documentation for picocli-based applications using the manpage doctype and manpage document structure.

The generated AsciiDoc files can be converted to HTML, PDF and unix man pages with the asciidoctor tool.

The picocli-codegen README has more details.

Repeatable Subcommands

From picocli 4.2, it is possible to specify that a command's subcommands can be specified multiple times by marking it with @Command(subcommandsRepeatable = true).

Example

Below is an example where the top-level command myapp is marked as subcommandsRepeatable = true.
This command has three subcommands, add, list and send-report:

@Command(name = "myapp", subcommandsRepeatable = true)
class MyApp implements Runnable {

    @Command
    void add(@Option(names = "-x") String x, @Option(names = "-w") double w) { ... }

    @Command
    void list(@Option(names = "--where") String where) { ... }

    @Command(name = "send-report")
    void sendReport(@Option(names = "--to", split = ",") String[] recipients) { ... }

    // ...
}

The above example command allows users to specify one or more of its subcommands multiple time. For example, this would be a valid invocation:

myapp add -x=item1 -w=0.2 \
      add -x=item2 -w=0.5 \
      add -x=item3 -w=0.7 \
      list --where "w>0.2" \
      send-report --to=recipient@myorg.com

In the above command line invocation, the myapp top-level command is followed by its subcommand add. Next, this is followed by another two occurences of add, followed by list and send-report. These are all "sibling" commands, that share the same parent command myapp. This invocation is valid because myapp is marked with subcommandsRepeatable = true.

Repeatable Subcommands Specification

Normally, subcommandsRepeatable is false, so for each command, only one of its subcommands can be specified, potentially followed by only one sub-subcommand of that subcommand, etc.

In mathematical terms, a valid sequence of commands and subcommands can be represented by a directed rooted tree that starts at the top-level command. This is illustrated by the diagram below.

subcommands not repeatable

When subcommandsRepeatable is set to true on a command, the subcommands of this command may appear multiple times.
Also, a subcommand can be followed by a "sibling" command (another command with the same parent command).

In mathematical terms, when a parent command has this property, the additional valid sequences of its subcommands form a fully connected subgraph (a complete digraph).

The blue and green dotted arrows in the diagram below illustrate the additional sequences that are allowed when a command has repeatable subcommands.

subcommands-repeatable

Note that it is not valid to specify a subcommand followed by its parent command:

# invalid: cannot move _up_ the hierarchy
myapp add -x=item1 -w=0.2 myapp

Subcommands are now lazily instantiated

From this release, subcommands are not instantiated until they are matched on the command line,
unless the user object has a @Spec or @ParentObject-annotated field; these are instantiated during initialization.

Injecting CommandSpec Into a IVersionProvider

From this release, IVersionProvider implementations can have @Spec-annotated fields. If such a field
exists, picocli will inject the CommandSpec of the command that uses this version provider. This gives the version provider access to the full command hierarchy, and may make it easier to implement version providers that can be reused among multiple commands.

For example:

class MyVersionProvider implements IVersionProvider {
    @Spec CommandSpec spec;

    public String[] getVersion() {
        return new String[] { "Version info for " + spec.qualifiedName() };
    }
}

Showing @filename in usage help

From picocli 4.2, an entry for @<filename> can be shown in the options and parameters list of the usage help message of a command with the @Command(showAtFileInUsageHelp = true) annotation.

Example:

@Command(name = "myapp", showAtFileInUsageHelp = true,
        mixinStandardHelpOptions = true, description = "Example command.")
class MyApp {
    @Parameters(description = "A file.") File file;
}

The usage help message for this command looks like this:

Usage: myapp [-hV] [@<filename>...] <file>
Example command.
      [@<filename>...]   One or more argument files containing options.
      <file>             A file.
  -h, --help             Show this help message and exit.
  -V, --version          Print version information and exit.

By default, the @<filename> entry is shown before the positional parameters in the synopsis as well as in the parameters list. This can be changed with the Help API for reordering sections.

Both the label and the description of the @<filename> entry have been defined with custom variables, to allow applications to change the text. The variables are:

  • picocli.atfile.label
  • picocli.atfile.description

By setting the above variables in either system properties, environment variables or the resource bundle for a command, the text can be customized.

See the user manual for examples.

Mixins with @ParentCommand-annotated fields

A common use case is sharing options between different levels of the command hierarchy, so that "global" options from the top-level command are also available on subcommands.

Since picocli 4.2, @ParentCommand-annotated fields can be used in mixins, which makes this easier. See the Use Case: Sharing Options section of the user manual for a full example.

For mixins that need to be reusable across more than two levels in the command hierarchy, injecting a @Spec-annotated field gives the mixin access to the full command hierarchy.

Configurable long options column width

The default layout shows short options and long options in separate columns, followed by the description column. The width of the long options column shrinks automatically if all long options are very short, but by default this column does not grow larger than 20 characters.

If the long option with its option parameter is longer than 20 characters (for example: --output=<outputFolder>), the long option overflows into the description column, and the option description is shown on the next line.

This (the default) looks like this:

Usage: myapp [-hV] [-o=<outputFolder>]
  -h, --help      Show this help message and exit.
  -o, --output=<outputFolder>
                  Output location full path.
  -V, --version   Print version information and exit.

From picocli 4.2, there is programmatic API to change this via the CommandLine::setLongOptionsMaxWidth and UsageMessageSpec::longOptionsMaxWidth methods.

In the above example, if we call commandLine.setLongOptionsMaxWidth(23) before printing the usage help, we get this result:

Usage: myapp [-hV] [-o=<outputFolder>]
  -h, --help                    Show this help message and exit.
  -o, --output=<outputFolder>   Output location full path.
  -V, --version                 Print version information and exit.

Fixed issues

  • [#454] API: Added support for repeatable subcommands. Thanks to Idan Arye, Miroslav Kravec, Philipp Hanslovsky and Jay for raising this and the subsequent discussion.
  • [#629] API: Support injecting @Spec CommandSpec spec into IVersionProvider implementations. Thanks to Garret Wilson for raising this.
  • [#795] API: Added @Command(showAtFileInUsageHelp=true) attribute to show @filename in usage help.
  • [#925] API: Support @ParentCommand-annotated fields in mixin classes.
  • [#936] API: Change visibility of Help.subcommands() method from protected to public.
  • [#459] API: Generate manpage documentation. Thanks to Miroslav Kravec for raising this. The picocli-codegen module can now generate AsciiDoc documentation that uses the manpage doctype and adheres to the manpage document structure so it can be converted to unix man pages in troff format with the asciidoctor tool.
  • [#299] API: Generate AsciiDoc documentation. Thanks to Philippe Charles for raising this.
    Added a new class picocli.codegen.docgen.manpage.ManPageGenerator to the picocli-codegen module that generates AsciiDoc documentation using the manpage doctype and manpage document structure.
    Custom markup like @|bold mytext|@, @|italic mytext|@ etc., originally intended to be converted to ANSI escape codes, can from this release also be converted to custom markup like <b>mytext</b> and <i>mytext</i> in HTML, or *mytext* and _mytext_ in lightweight markup languages like AsciiDoc.
    Applications can control this by setting a ColorScheme with a custom markup map.
    This ticket resulted in the following additional methods: ColorScheme::text, ColorScheme::string, ColorScheme::customMarkupMap, ColorScheme::parse, ColorScheme::resetStyle, ColorScheme::apply, ColorScheme.Builder::customMarkupMap (getter and setter) and a new picocli.CommandLine.Help.Ansi.Text(String, ColorScheme) constructor.
    The picocli.CommandLine.Help.Ansi::apply method is now deprecated in favor of ColorScheme::apply.
  • [#906] Auto-completion: Added automated tests for picocli-generated bash/zsh completion scripts.
  • [#468][#505][#852] Auto-completion: added support for positional parameter completion. Thanks to Serhii Avsheniuk for the pull request.
  • [#644][#671] Auto-completion: fix shellcheck warnings in generated autocompletion scripts. Thanks to Dylan Cali for raising this, and thanks to AlcaYezz for the pull request.
  • [#396] Auto-completion: completion scripts no longer use associative arrays, and should now work on OSX.
  • [#934] Enhancement: Make long options column width configurable. Thanks to tomerz90 for raising this.
  • [#930] Enhancement: Add --factory option to ReflectionConfigGenerator, ResourceConfigGenerator and DynamicProxyConfigGenerator. Thanks to Santiago Acosta for raising this.
  • [#690] Enhancement: Postpone instantiating subcommands until they are matched on the command line. Thanks to Daniel Breitlauch for raising this.
  • [#942] Enhancement: Show at files in usage help for picocli built-in commands.
  • [#941] Enhancement: Allow default values for predefined variables.
  • [#926] Enhancement: Clarify debug trace output when adding aliases.
  • [#928] Enhancement: Improve debug tracing: show command user object identity hashcode and prefix "Processing argument..." with argument index.
  • [#920] Enhancement: Reduce DEBUG tracing noise if no resource bundle is set.
  • [#946] Enhancement: Add --exit option to picocli codegen utilities.
  • [#940] Bugfix: ArgGroups with a negatable option no longer cause a NullPointerException during initialization.
  • [#938] Bugfix: ArgGroups validation now correctly reports an error when a required option is missing, while an optional subgroup is present. Thanks to Trent Mohay for raising this.
  • [#933] Bugfix: Incorrect error message when multiple exclusive groups are used. Thanks to Mikaël Barbero for raising this.
  • [#905] Bugfix: non-public @Command-annotated methods without arguments caused a IllegalAccessException. From this release such methods no longer need to be public. Thanks to David Connelly for raising this.
  • [#924] Bugfix: CommandSpec.mixinAnnotatedElements map should be initialized when discovering @Mixin-annotated fields and methods via reflection.
  • [#937] Bugfix: Text.getStyledChars no longer incorrectly inserts ANSI escape chars into the next line prefix when lines are broken.
  • [#945] Bugfix: Text.substring now leaves out StyledSection instances that do not apply.
  • [#944] DOC: Fix typo in picocli user manual - remove unnecessary semicolon. Thanks to ztbx for raising this.
  • [#943] DOC: Create man pages for built-in picocli commands.
  • [#929] DOC: Add jbang under packaging in the user manual.
  • [#927] DOC: Show current picocli version in the Spring Boot section of the user manual. Thanks to Christian Grobmeier for the pull request.
  • [#919] DOC: Added example Gradle project with Kotlin and Graal Native Image. Thanks to OndrejMalek for the pull request.
  • [#918] DOC: Added more Scala examples. Thanks to Andreas Deininger for the pull request.
  • [#916] DOC: Added Scala examples. Thanks to Andreas Deininger for the pull request.
  • [#914] DOC: Added Java and Kotlin examples for using ResourceBundle to internationalize and localize your CLI app. Thanks to Andreas Deininger for the pull request.
  • [#915] DOC: Ensure Kotlin examples compile correctly. Thanks to Andreas Deininger for the suggestion.
  • [#913] DOC: Added more Java and Kotlin examples. Thanks to Andreas Deininger for the pull request.
  • [#912] DOC: Fixed broken links in javadoc. Thanks to Andreas Deininger for the pull request.
  • [#911] DOC: Fixed syntax error in javadoc. Thanks to Andreas Deininger for the pull request.
  • [#909] DOC: User manual: minor fixes. Thanks to Andreas Deininger for the pull request.
  • [#908] DOC: Fix typo in user manual: Add missing closing curly bracket. Thanks to Piotrek Żygieło for the pull request.
  • [#907] DOC: Updated and added Kotlin examples. Thanks to Andreas Deininger for the pull request.
  • [#910] Dependency Upgrade: Bump Spring Boot dependency to 2.2.2 to allow it to work under Java 13. Thanks to Stéphane Vanacker for raising this.

Deprecations

  • The picocli.CommandLine.Help.Ansi#apply method has been deprecated in favor of the picocli.CommandLine.Help.ColorScheme#apply method.
  • The picocli.CommandLine.Help.TextTable forDefaultColumns(Ansi, int, int) method has been deprecated in favor of the new TextTable.forDefaultColumns(ColorScheme, int, int) method.
  • The picocli.CommandLine.Help.TextTable forColumnWidths(Ansi, int...) method has been deprecated in favor of the new TextTable.forColumnWidths(ColorScheme, int...) method.
  • The picocli.CommandLine.Help.TextTable forColumns(Ansi, Column...) method has been deprecated in favor of the new TextTable.forColumns(ColorScheme, Column...) method.
  • The picocli.CommandLine.Help.TextTable constructor (Ansi, Column[]) has been deprecated in favor of the new TextTable(ColorScheme, Column...) constructor.

Potential breaking changes

Annotated command objects are now not instantiated until the command is matched on the command line.
Previously all subcommands were instantiated when the top-level command's CommandLine was constructed.

Don't miss a new picocli release

NewReleases is sending notifications on new releases.