Releases: remkop/picocli
Picocli 4.6.0
Picocli 4.6.0
The picocli community is pleased to announce picocli 4.6.0.
This release contains new features, bug fixes and other enhancements.
Community Contributions
This release contains many, many community contributions, for which I am extremely grateful. Let's give the contributors some credit!
- Andreas Deininger has been contributing to the documentation and other areas for a long time, but recently went into overdrive :-) and contributed many, many new pull requests to improve the documentation. The user manual and Quick Guide now have a "foldable" table of contents, and examples in tabs, with many additional examples in Kotlin, Scala and Groovy. A lot of work went into this! Many thanks, Andreas!
- Marko Mackic contributed a pull request to add
IModelTransformer
API for user-defined model transformations after initialization and before parsing. - Sualeh Fatehi contributed a pull request to the
picocli-shell-jline3
module that adds a built-inclear
command and improves thehelp
command. - H.Sakata contributed a pull request that adds support for
echo
andprompt
for interactive options and positional parameters. - Daniel Gray contributed a bug fix to prevent incorrectly defaulting inherited positional params after a subcommand.
- nveeser-google contributed a fix for compiler warnings about
Annotation::getClass
and assignment inif
condition. - Petr Hála contributed a pull request to add a section on Mocking to user manual.
- Max Rydahl Andersen contributed a pull request to include jbang in the Build Tools section of the user manual.
- David Phillips contributed a section to the user manual on Really Executable JARs.
- Laurent Almeras contributed a pull request to fix the user manual:
@ParentObject
should be@ParentCommand
. - Mattias Andersson raised the idea of supporting subcommand methods in Groovy scripts.
- Adrian A. raised the idea of using closures in the picocli annotations in Groovy programs instead of specifying a class.
- Nick Cross raised the idea of inheriting
@Command
attributes withscope=INHERIT
. - Marko Mackic raised the idea of adding a
CommandSpec::removeSubcommand
method. - Max Rydahl Andersen raised the idea of supporting
Optional<T>
type for options and positional parameters. - Max Rydahl Andersen and David Walluck raised the idea of supporting key-only Map options (to support
-Dkey
as well as-Dkey=value
). - David Walluck raised the idea of a "preprocessor" parser plugin.
- Jannick Hemelhof raised the idea of supporting
@Spec
-annotated members inArgGroup
classes. - Vitaly Shukela raised a bug report: the error message for unmatched positional argument reports an incorrect index when value equals a previously matched argument.
- drkilikil raised a bug report:
MissingParameterException
should not be thrown when subcommand has required options and help option is specified on parent command. - Sebastian Thomschke raised a bug report:
ReflectionConfigGenerator
should not generate method section in subclass config for private superclass methods inreflect-config.json
. - Lukas Heumos added the picocli-based cli-java template to CookieTemple.
- Sualeh Fatehi raised the idea of adding add
CommandLine::getFactory
accessor method. - David Walluck contributed a test improvement that allows the tests to run reliably in more environments.
- Sabrina (link witheld) pointed out various typos in the documentation.
What is in this release
Improved Groovy support: this release introduces a new @PicocliScript2
annotation that adds support for exit codes and @Command
-annotated methods to define subcommands. Also, from this release, Groovy programs can use closures in the picocli annotations instead of specifying a class.
From this release, Map options accept key-only parameters, so end users can specify -Dkey
as well as -Dkey=value
.
There is a new mapFallbackValue
attribute that enables this, which can be used to control the value that is put into the map when only a key was specified on the command line.
Also, this release adds support for java.util.Optional<T>
: single-value types can be wrapped in an Optional
container object when running on Java 8 or higher.
If the option or positional parameter was not specified on the command line, picocli assigns the value Optional.empty()
instead of null
.
This release also adds support for commands with scope = ScopeType.INHERIT
. Commands with this scope have their attributes copied to all subcommands (and sub-subcommands).
New parser plugin: IParameterPreprocessor
and new configuration plugin: IModelTransformer
.
From this release, @Spec
-annotated elements can be used in ArgGroup
classes, which can be convenient for validation.
Interactive options and positional parameters can now set echo = true
(for non-security sensitive data) so that user input is echoed to the console, and control the prompt
text that is shown before asking the user for input.
Help API: this release adds public methods Help.Layout::colorScheme
, Help.Layout::textTable
, Help.Layout::optionRenderer
, Help.Layout::parameterRenderer
, and Help::calcLongOptionColumnWidth
, making it easier to customize the table format used to lay out options and positional parameters in the usage help message.
CommandSpec API: added method CommandSpec::removeSubcommand
.
This is the seventy-fifth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
New @PicocliScript2
annotation
The older @picocli.groovy.PicocliScript
annotation is deprecated from picocli 4.6.
New scripts should use the @picocli.groovy.PicocliScript2
annotation (and associated picocli.groovy.PicocliBaseScript2
base class) instead.
The table below lists the differences between the PicocliBaseScript2
and PicocliBaseScript
script base classes.
PicocliBaseScript2 |
PicocliBaseScript |
---|---|
Subcommands can be defined as @Command -annotated methods in the script. |
No support for @Command -annotated methods. |
Support for help subcommands (both the built-in one and custom ones). |
No support for help subcommands. |
Exit code support: scripts can override afterExecution(CommandLine, int, Exception) to call System.exit . |
No support for exit code. |
Invokes CommandLine::execute . Scripts can override beforeParseArgs(CommandLine) to install a custom IExecutionStrategy . |
Execution after parsing is defined in PicocliBaseScript::run and is not easy to customize. Any subcommand and the main script are both executed. |
Scripts can override beforeParseArgs(CommandLine) to install a custom IParameterExceptionHandler . |
Invalid input handling can be customized by overriding PicocliBaseScript::handleParameterException . |
Scripts can override beforeParseArgs(CommandLine) to install a custom IExecutionExceptionHandler . |
Runtime exception handling can be customized by overriding PicocliBaseScript::handleExecutionException . |
Implements Callable<Object> , script body is transformed to the call method. |
Script body is transformed to the runScriptBody method. |
Groovy Closures in Annotations
From picocli 4.6, Groovy programs can use closures in the picocli annotations instead of specifying a class.
This can be especially useful in Groovy scripts, where one cannot define a static inner class.
Example:
@Command(name = "ClosureDemo",
versionProvider = {
{ -> ["line1" , "line2"] as String[] } as IVersionProvider // <1>
},
defaultValueProvider = {
{ argSpec -> "some default" } as IDefaultValueProvider // <2>
})
class ClosureDemo {
@Option(names = '-x', completionCandidates = {["A", "B", "C"]}) // <3>
String x
@Option(names = '-y',
parameterConsumer = {
{ args, argSpec, commandSpec -> // <4>
argSpec.setValue(args.toString() + commandSpec.name())
args.clear()
} as IParameterCon...
Picocli 4.5.2
Picocli 4.5.2
The picocli community is pleased to announce picocli 4.5.2.
This release contains bug fixes and enhancements:
- Auto-enable ANSI colors on MSYS2 terminals.
- Abbreviated options are now matched correctly even when value attached with '=' separator.
- The built-in
HelpCommand
now respects subcommands case-sensitivity and abbreviations. - Required parameters no longer consume negated options.
- Positional parameters in Argument Groups no longer result in
ArithmeticException: / by zero
exceptions. - The user manual now has tabs showing examples in languages other than Java.
This is a work in progress: many examples still only have a Java version.
Contributions welcome! - Many, many documentation enhancements, most of which contributed by the community.
Many thanks to the picocli community who contributed 28 pull requests in this release!
Please see the Fixed Issues section below for the individual contributors. Great work!
This is the seventy-fourth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
The user manual now has tabs showing examples in languages other than Java.
This is a work in progress: many examples still only have a Java version.
Contributions welcome!
Fixed issues
- [#1186] Enhancement: Auto-enable ANSI colors on MSYS2 (Git for Windows, MSYS2-based Windows Terminal shells, etc.). Thanks to Sysmat for raising this.
- [#1162] Bugfix: Abbreviated options are not matched if value attached with '=' separator (like
-x=3
). Thanks to Chris Laprun for raising this. - [#1156][#1172] Bugfix: the built-in
HelpCommand
now respects subcommands case-sensitivity and abbreviations. Thanks to NewbieOrange for the pull request. - [#1197] Bugfix: required parameters should not consume negated options. Thanks to Kevin Turner for raising this.
- [#1213] Bugfix:
@Parameters
in@ArgGroup
should not result inArithmeticException: / by zero
. Thanks to Loren Keagle for raising this. - [#1158] DOC: Fix broken links to GraalVM repo. Thanks to Andreas Deininger for the pull request.
- [#1155] DOC: Fix sample code in chapter "Validation". Thanks to Andreas Deininger for the pull request.
- [#1157] DOC: Fix typo "a argument group" in user manual. Thanks to sabrina for raising this.
- [#1160] DOC: Added section Was a Value Defaulted? to the user manual.
- [#1161] DOC: Fix typo "4,2" (should be 4.2) in user manual. Thanks to sabrina for raising this.
- [#1165] DOC: Fix jline3 example: add
AnsiConsole::systemUninstall
infinally
clause. Thanks to David Walluck for raising this. - [#1168][#1169] DOC: Ensure
org.jline.terminal.Terminal
is closed when done. Thanks to David Walluck for the pull request. - [#1167] DOC: Fix broken links in Quick Guide. Thanks to Andreas Deininger for the pull request.
- [#1171] DOC: Various documentation improvements. Thanks to Andreas Deininger for the pull request.
- [#1173] DOC: Improve example applications for the user manual and Quick Guide. Thanks to Andreas Deininger for the pull request.
- [#1175] DOC: section on compatible versions to
picocli-shell-jline3/README.md
. Thanks to Nick Cross for raising this. - [#1176] DOC: Update JLine
picocli-shell-jline3
example to 3.16.0. Thanks to Nick Cross for the pull request. - [#890][#1187] DOC: Extend and improve subcommands documentation. Thanks to Andreas Deininger for the pull request.
- [#1190] DOC: Improve InetSocketAddressConverter demo. Thanks to Andreas Deininger for the pull request.
- [#1192] DOC: Fix broken links in documentation. Thanks to Andreas Deininger for the pull request.
- [#1196] DOC: Quick Guide examples can now be executed on the documentation page via JDoodle.com. Thanks to Andreas Deininger for the pull request.
- [#1200] DOC: User manual
checksum
example can now be executed on the documentation page via JDoodle.com. Thanks to Andreas Deininger for the pull request. - [#1199] DOC: Fix
paramLabel
in examples. Thanks to Andreas Deininger for the pull request. - [#1198] DOC: Add copy button to code blocks. Thanks to Andreas Deininger for the pull request.
- [#1201] DOC: User manual
checksum
example: add Kotlin source code on second tab. Thanks to Andreas Deininger for the pull request. - [#1202] DOC: Update to latest Asciidoctor gradle plugin. Thanks to Andreas Deininger for the pull request.
- [#1203] DOC: Replace 'coderay' source code highlighter with 'rouge' to support Kotlin, Scala and Groovy. Thanks to Andreas Deininger for the pull request.
- [#1205] DOC: User manual
checksum
example: add more tabs for Groovy, Groovy script and Scala. Thanks to Andreas Deininger for the pull request. - [#1208] DOC: Fix: Show copy buttons in code blocks with latest Asciidoctor gradle plugin. Thanks to Andreas Deininger for the pull request.
- [#1209] DOC: Show Maven coordinates in JLine2/3 README. Thanks to Jiří Holuša for the pull request.
- [#1210] DOC: User manual
subcommands
example: add tab with Kotlin source code. Thanks to Andreas Deininger for the pull request. - [#1211] DOC: User manual
subcommands
section: add several tabs with Kotlin source code. Thanks to Andreas Deininger for the pull request. - [#1170] TEST: Ensure ANSI is disabled in
ManPageGeneratorTest
regardless of environment. Thanks to David Walluck for the pull request. - [#1166][#1103] TEST: Ensure ANSI is disabled in
TracerTest
regardless of environment. Thanks to David Walluck for the pull request. - [#1179] TEST: Use
.invalid
domain name forInetAddress
test. Thanks to David Phillips for the pull request. - [#1178] BUILD: Run Travis build on macOS. Thanks to David Phillips for the pull request.
- [#1192] Dependency Upgrade: Bump AsciiDoctor to 2.1.0 from 1.6.2. Thanks to Andreas Deininger for the pull request.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 4.5.1
Picocli 4.5.1
The picocli community is pleased to announce picocli 4.5.1.
This release contains bug fixes and enhancements.
Fixed bug in the picocli-codegen
annotation processor that resulted in errors in native images that used ManPageGenerator
as subcommand.
Suppress generation of Gradle Module Metadata, to fix Gradle build failures for projects using picocli 4.4.0 or 4.5.0.
Fixed terminal width detection on macOS.
The user manual now has a new section on Validation. Various other documentation improvements.
This is the seventy-third public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#1151] Bugfix:
ManPageGenerator
as subcommand with native-image throws exception. Thanks to Sebastian Hoß for raising this. - [#1152] Bugfix: Gradle build fail when using picocli 4.4.0 or 4.5.0: Gradle Module Metadata for picocli 4.4.0+ missing from Maven Central. Thanks to Frank Pavageau for reporting this.
- [#1150] Bugfix: Fix terminal width detection on macOS. Thanks to David Phillips for the pull request.
- [#1142] DOC: Update Kotlin GraalVM native image example - Update native image gradle plugin. Now supports jdk 11. Thanks to OndrejMalek for the pull request.
- [#1153] DOC: Fix documentation leading code quote. Thanks to sabrina for raising this.
- [#1147] DOC: Add documentation on how to do custom parameter validation. Thanks to Loren Keagle for raising this.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 4.5.0
Picocli 4.5.0
The picocli community is pleased to announce picocli 4.5.0.
This release contains bug fixes and enhancements.
The ColorScheme
class now has new methods stackTraceText
and richStackTraceString
, which can be convenient when creating custom error handlers with colors.
Various bugfixes in the picocli-codegen
annotation processor.
The user manual now has anchor links before all section titles.
This is the seventy-second public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#1129] API: Add methods
ColorScheme::stackTraceText(Throwable)
andColorScheme::richStackTraceString(Throwable)
. - [#1124] Enhancement: automatically generate a better summary in the
AutoComplete.GenerateCompletion
generated man page. - [#1126] Enhancement: Make picocli trace levels case-insensitive.
- [#1128] Enhancement:
ParameterException
caused byTypeConversionException
now have their cause exception set. - [#1137] Bugfix: The
picocli-codegen
annotation processor causes the build to fail with aClassCastException
when an option hascompletionCandidates
defined. - [#1134] Bugfix: The
picocli-codegen
annotation processor should allow@Spec
-annotated field in classes implementingIVersionProvider
. - [#1138] Bugfix: The
picocli-codegen
annotation processor no longer givesFATAL ERROR: picocli.CommandLine$InitializationException: ArgGroup has no options or positional parameters, and no subgroups
during incremental compilation in Intelli/J IDEA. - [#1127] DOC: Custom ShortErrorMessageHandler manual example should use bold red for error message.
- [#1130] DOC: Clarify how to run picocli-based applications.
- [#1131] DOC: Add anchor links before section titles in user manual.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 4.4.0
Picocli 4.4.0
The picocli community is pleased to announce picocli 4.4.0.
This release contains over 45 bugfixes, enhancements, and new features.
A major new feature in this release is support for abbreviated options and subcommands. When abbreviations are enabled, users can specify the initial letter(s) of the first "component" and optionally of one or more subsequent components of an option or subcommand name. "Components" are parts of a name, separated by -
dash characters or by upper/lower case. So for example, both --CamelCase
and --kebab-case
have two components. For details see the New and Noteworthy section below.
Another important change are parser fixes and improvements: the parser will no longer assign values that match an option name to options that take a parameter, unless the value is in quotes. Also, values that resemble, but not exactly match, option names are now treated more consistently and parser behaviour for such values is configurable.
Also worth hightlighting: from this release, the ManPageGenerator
tool can be used as a subcommand in your application.
There are many more improvements in this release: it is now easier to customize the usage help message, there are JANSI fixes, and other bugfixes and enhancements. See the Fixed Issues list for details.
This is the seventy-first public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Abbreviated Options and Subcommands
Since picocli 4.4, the parser can recognize abbreviated options and subcommands.
This needs to be enabled explicitly with CommandLine::setAbbreviatedOptionsAllowed
and CommandLine::setAbbreviatedSubcommandsAllowed
.
Recognized Abbreviations
When abbreviations are enabled, users can specify the initial letter(s) of the first component and optionally of one or more subsequent components of an option or subcommand name.
"Components" are separated by -
dash characters or by case, so for example, both --CamelCase
and --kebab-case
have two components.
NOTE: When case sensitivity is disabled, only the -
dash character can be used to separate components.
Examples of valid abbreviations:
Option or Subcommand | Recognized Abbreviations
-------------------- | ------------------------
--veryLongCamelCase | --very, --vLCC --vCase
--super-long-option | --sup, --sLO, --s-l-o, --s-lon, --s-opt, --sOpt
some-long-command | so, sLC, s-l-c, soLoCo, someCom
Ambiguous Abbreviations
When the user specifies input that can match multiple options or subcommands, the parser throws a ParameterException
. When applications use the execute
method, a short error message and the usage help is displayed to the user.
For example, given a command with subcommands help
and hello
, then ambiguous user input like hel
will show this error message:
Error: 'hel' is not unique: it matches 'hello', 'help'
Abbreviated Long Options and POSIX Clustered Short Options
When an argument can match both a long option and a set of clustered short options, picocli matches the long option.
For example:
class AbbreviationsAndPosix {
@Option(names = "-A") boolean a;
@Option(names = "-B") boolean b;
@Option(names = "-AaaBbb") boolean aaaBbb;
}
AbbreviationsAndPosix app = new AbbreviationsAndPosix();
new CommandLine(app).setAbbreviatedOptionsAllowed(true).parseArgs("-AB");
assertTrue(app.aaaBbb);
assertFalse(app.a);
assertFalse(app.b);
When abbreviated options are enabled, user input -AB
will match the long -AaaBbb
option, but not the -A
and -B
options.
Parser Fixes and Improvements
Option Names as Option Values
Options that take a parameter previously were able to take option names as the parameter value. From this release, this is no longer possible. The parser will no longer assign values that match an option name to an option, unless the value is in quotes. For example:
class App {
@Option(names = "-x") String x;
@Option(names = "-y") String y;
public static void main(String... args) {
App app = new App();
new CommandLine(app).setTrimQuotes(true).parseArgs(args);
System.out.printf("x='%s', y='%s'%n", app.x, app.y);
}
}
In previous versions of picocli, the above command would accept input -x -y
, and the value -y
would be assigned to the x
String field. From this release, the above input will be rejected with an error message indicating that the -x
option requires a parameter.
If it is necessary to accept values that match option names, these values need to be quoted. For example:
java App -x="-y"
This will print the following output:
x='-y', y='null'
Vararg Positional Parameters No Longer Consume Unmatched Options
Vararg positional arguments no longer consume unmatched options unless configured to do so. For example:
class App {
@Parameters(arity = "*") String[] positionals;
}
In previous versions of picocli, the parser behaviour was not consistent:
- input
-z 123
would be rejected with error"Unmatched argument: '-z'
- input
123 -z
would be accepted and thepositionals
String array would contain two values,123
and-z
(Note that this problem only occurred with multi-value positional parameters defined with variable arity: arity = "*"
.)
From this release, both of the above input sequences will be rejected with an error message indicating that -z
is an unknown option. As before, to accept such values as positional parameters, call CommandLine::setUnmatchedOptionsArePositionalParams
with true
.
Configure Whether Options Should Consume Unknown Options
By default, options accept parameter values that "resemble" (but don't exactly match) an option.
This release introduces a CommandLine::setUnmatchedOptionsAllowedAsOptionParameters
method that makes it possible to configure the parser to reject values that resemble options as option parameters. Setting it to false
will result in values resembling option names being rejected as option values.
For example:
class App {
@Option(names = "-x") String x;
}
By default, a value like -z
, which resembles an option, is accepted as the parameter for -x
:
App app = new App();
new CommandLine(app).parseArgs("-x", "-z");
assertEquals("-z", app.x);
After setting the unmatchedOptionsAllowedAsOptionParameters
parser option to false
, values resembling an option are rejected as parameter for -x
:
new CommandLine(new App())
.setUnmatchedOptionsAllowedAsOptionParameters(false)
.parseArgs("-x", "-z");
This will throw an UnmatchedArgumentException
with message:
"Unknown option '-z'; Expected parameter for option '-x' but found '-z'"
NOTE: Negative numbers are not considered to be unknown options, so even when unmatchedOptionsAllowedAsOptionParameters
is set to false
, option parameters like -123
, -NaN
, -Infinity
, -#ABC
and -0xCAFEBABE
will not be rejected for resembling but not matching an option name.
ManPageGenerator as Subcommand in Your App
From picocli 4.4, the ManPageGenerator
tool can be used as a subcommand in your application, with the usual syntax:
import picocli.codegen.docgen.manpage.ManPageGenerator;
@Command(subcommands = ManPageGenerator.class)
...
To use the ManPageGenerator
tool as a subcommand, you will need the picocli-codegen
jar in your classpath.
Fixed issues
- [#10][#732][#1047] API: Support abbreviated options and commands. Thanks to NewbieOrange for the pull request.
- [#639] API: Add method
CommandLine::is/setUnmatchedOptionsAllowedAsOptionParameters
to disallow option parameter values resembling option names. Thanks to Peter Murray-Rust for raising this. - [#1074][#1075] API: Added method
ParseResult::expandedArgs
to return the list of arguments after@-file
expansion. Thanks to Kevin Bedi for the pull request. - [#1052] API: Show/Hide commands in usage help on specific conditions. Thanks to Philippe Charles for raising this.
- [#1088] API: Add method
Help::allSubcommands
to return all subcommands, including hidden ones. Clarify the semantics ofHelp::subcommands
. - [#1090] API: Add methods
Help::optionListExcludingGroups
to return a String with the rendered section of the usage help containing only the specified options, including hidden ones. - [#1092] API: Add method
Help::parameterList(List<PositionalParamSpec>)
to return a String with the rendered section of the usage help containing only the specified positional parameters, including hidden ones. - [#1093] API: Add method
Help::commandList(Map<String, Help>)
to return a String with the rendered section of the usage help containing only the specified subcommands, including hidden ones. - [#1091] API: Add method
Help::optionListGroupSections
to return a String with the rendered section of the usage help containing only the option groups. - [#1089] API: Add method `Help::cr...
Picocli 4.3.2
Picocli 4.3.2
The picocli community is pleased to announce picocli 4.3.2.
This release fixes a bug where the stack trace of an exception in the business logic would omit nested cause exceptions.
This is the seventieth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
[#1048][#1049] Bugfix: Cause exception not printed by default execution exception handler. Thanks to Neko Null for the pull request.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 4.3.1
Picocli 4.3.1
The picocli community is slightly embarrassed to announce picocli 4.3.1. :-)
This release fixes some critical bugs:
- an
IllegalArgumentException: wrong number of arguments
was thrown when the@Option(scope = INHERIT)
feature is used in a command that has subcommands defined in@Command
-annotated methods - a
NullPointerException
was thrown inDefaultParamLabelRenderer.renderParameterLabel
for programmatically built models that have a non-null
split
regex and do not have asplitSynopsisLabel
- removed a call to the
String.isEmpty
method, which prevented picocli from running on Java 5: this method was introduced in Java 6
See Fixed issues for the full list of changes.
This is the sixty-nineth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
[#1042] Bugfix: "wrong number of arguments" exception when using inherited options with @Command
-annotated methods. Thanks to Garret Wilson for raising this.
[#1043] Bugfix: NullPointerException thrown in DefaultParamLabelRenderer.renderParameterLabel
for programmatically built models that have a non-null
split
regex and do not have a splitSynopsisLabel
.
[#1044] Bugfix: only display splitSynopsisLabel
in usage help message if the option has a split
regex. Thanks to Andreas Deininger for raising this.
[#1045] Bugfix: replace use of Java 6 API String.isEmpty
with picocli-internal Java 5 equivalent.
[#1046] DOC: mention picocli's programmatic API and link to the programmatic API documentation from the user manual.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 4.3.0
Picocli 4.3.0
The picocli community is pleased to announce picocli 4.3.0.
This is a fairly big release with 70 tickets closed, and over 50 bugfixes and enhancements. Many thanks to the picocli community who contributed 21 pull requests!
A major theme of this release is sharing options between commands:
- New feature: "inherited" options. Options defined with
scope = ScopeType.INHERIT
are shared with all subcommands (and sub-subcommands, to any level of depth). Applications can define an inherited option on the top-level command, in one place, to allow end users to specify this option anywhere: not only on the top-level command, but also on any of the subcommands and nested sub-subcommands. - More powerful mixins. Mixin classes can declare a
@Spec(MIXEE)
-annotated field, and picocli will inject theCommandSpec
of the command receiving this mixin (the "mixee") into this field. This is useful for mixins containing shared logic, in addition to shared options and parameters.
Another major theme is improved support for positional parameters:
- Automatic indexes for positional parameters. Single-value positional parameters without an explicit
index = "..."
attribute are now automatically assigned an index based on the other positional parameters in the command. One use case is mixins with positional parameters. - Repeatable ArgGroups can now define positional parameters.
Other improvements:
- The parser now supports case-insensitive mode for options and subcommands.
- Error handlers now use ANSI colors and styles. The default styles are bold red for the error message, and italic for stack traces. Applications can customize with the new
Help.ColorScheme
methodserrors
andstackTraces
. - The usage help message can now show an entry for
--
in the options list with the@Command(showEndOfOptionsDelimiterInUsageHelp = true)
annotation. - Easily make subcommands mandatory by making the top-level command a class that does not implement
Runnable
orCallable
.
This is the sixty-eighth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Inherited Options
This release adds support for "inherited" options. Options defined with scope = ScopeType.INHERIT
are shared with all subcommands (and sub-subcommands, to any level of depth). Applications can define an inherited option on the top-level command, in one place, to allow end users to specify this option anywhere: not only on the top-level command, but also on any of the subcommands and nested sub-subcommands.
Below is an example where an inherited option is used to configure logging.
@Command(name = "app", subcommands = Sub.class)
class App implements Runnable {
private static Logger logger = LogManager.getLogger(App.class);
@Option(names = "-x", scope = ScopeType.LOCAL) // option is not shared: this is the default
int x;
@Option(names = "-v", scope = ScopeType.INHERIT) // option is shared with subcommands, sub-subcommands, etc
public void setVerbose(boolean verbose) {
// Configure log4j.
// This is a simplistic example: you probably only want to modify the ConsoleAppender level.
Configurator.setRootLevel(verbose ? Level.DEBUG : Level.INFO);
}
public void run() {
logger.debug("-x={}", x);
}
}
@Command(name = "sub")
class Sub implements Runnable {
private static Logger logger = LogManager.getLogger(Sub.class);
@Option(names = "-y")
int y;
public void run() {
logger.debug("-y={}", y);
}
}
Users can specify the -v
option on either the top-level command or on the subcommand, and it will have the same effect.
# the -v option can be specified on the top-level command
java App -x=3 -v sub -y=4
Specifying the -v
option on the subcommand will have the same effect. For example:
# specifying the -v option on the subcommand also changes the log level
java App -x=3 sub -y=4 -v
NOTE: Subcommands don't need to do anything to receive inherited options, but a potential drawback is that subcommands do not get a reference to inherited options.
Subcommands that need to inspect the value of an inherited option can use the @ParentCommand
annotation to get a reference to their parent command, and access the inherited option via the parent reference.
Alternatively, for such subcommands, sharing options via mixins may be a more suitable mechanism.
Case-insensitive mode
By default, all options and subcommands are case sensitive. Case sensitivity can be switched off globally, as well as on a per-command basis.
To toggle case sensitivity for all commands, use the CommandLine::setSubcommandsCaseInsensitive
and CommandLine::setOptionsCaseInsensitive
methods. Use the CommandSpec::subcommandsCaseInsensitive
and CommandSpec::optionsCaseInsensitive
methods to give some commands a different case sensitivity than others.
Automatic Indexes for Positional Parameters
From this release, when the index = "..."
attribute is omitted, the default index is index = "0+"
, which tells picocli to assign an index automatically, starting from zero, based on the other positional parameters defined in the same command.
A simple example can look like this:
class AutomaticIndex {
@Parameters(hidden = true) // "hidden": don't show this parameter in usage help message
List<String> allParameters; // no "index" attribute: captures _all_ arguments
@Parameters String group; // assigned index = "0"
@Parameters String artifact; // assigned index = "1"
@Parameters String version; // assigned index = "2"
}
Picocli initializes fields with the values at the specified index in the arguments array.
String[] args = { "info.picocli", "picocli", "4.3.0" };
AutomaticIndex auto = CommandLine.populateCommand(new AutomaticIndex(), args);
assert auto.group.equals("info.picocli");
assert auto.artifact.equals("picocli");
assert auto.version.equals("4.3.0");
assert auto.allParameters.equals(Arrays.asList(args));
The default automatic index (index = "0+"
) for single-value positional parameters is "anchored at zero": it starts at zero, and is increased with each additional positional parameter.
Sometimes you want to have indexes assigned automatically from a different starting point than zero. This can be useful when defining Mixins with positional parameters.
To accomplish this, specify an index with the anchor point and a +
character to indicate that picocli should start to automatically assign indexes from that anchor point. For example:
class Anchored {
@Parameters(index = "1+") String p1; // assigned index = "1" or higher
@Parameters(index = "1+") String p2; // assigned index = "2" or higher
}
Finally, sometimes you want to have indexes assigned automatically to come at the end. Again, this can be useful when defining Mixins with positional parameters.
To accomplish this, specify an index with a +
character to indicate that picocli should automatically assign indexes that come at the end. For example:
class Unanchored {
@Parameters(index = "+") String penultimate; // assigned the penultimate index in the command
@Parameters(index = "+") String last; // assigned the last index in the command
}
Repeatable ArgGroups with Positional Parameters
From this release, positional parameters can be used in repeating Argument Groups.
When a @Parameters
positional parameter is part of a group, its index
is the index within the group, not within the command.
Below is an example of an application that uses a repeating group of positional parameters:
@Command(name = "grades", mixinStandardHelpOptions = true, version = "grades 1.0")
public class Grades implements Runnable {
static class StudentGrade {
@Parameters(index = "0") String name;
@Parameters(index = "1") BigDecimal grade;
}
@ArgGroup(exclusive = false, multiplicity = "1..*")
List<StudentGrade> gradeList;
@Override
public void run() {
gradeList.forEach(e -> System.out.println(e.name + ": " + e.grade));
}
public static void main(String[] args) {
System.exit(new CommandLine(new Grades()).execute(args));
}
}
Running the above program with this input:
Alice 3.1 Betty 4.0 "X Æ A-12" 3.5 Zaphod 3.4
Produces the following output:
Alice: 3.1
Betty: 4.0
X Æ A-12: 3.5
Zaphod: 3.4
@Spec(MIXEE)
Annotation
From this release, mixins are more powerful. Mixin classes can declare a @Spec(MIXEE)
-annotated field, and picocli will inject the CommandSpec
of the command receiving this mixin (the "mixee") into this field. This is useful for mixins containing shared logic, in addition to shared options and parameters.
Since picocli 4....
Picocli 4.2.0
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 (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.
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.
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...
Picocli 4.1.4
Picocli 4.1.4
The picocli community is pleased to announce picocli 4.1.4.
This release contains a bugfix for GraalVM users, and minor documentation enhancements.
This release fixes a bug in the picocli-codegen
annotation processor that generates an incorrect reflect-config.json
file with invalid entries for inner classes of commands in the unnamed package, that are unnecessarily prefixed with a dot. This makes the GraalVM native-image
generator fail with an error like "Class .Outer$Inner not found".
This is the sixty-sixth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#903] Bugfix:
picocli-codegen
generates invalid reflect-config.json for classes in unnamed package. - [#902] DOC: replace deprecated
CommandLine.invoke()
function. Thanks to Andreas Deininger for the pull request.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.