Picocli 4.0.0-alpha-2
Picocli 4.0.0-alpha-2
The picocli community is pleased to announce picocli 4.0.0-alpha-2.
Thanks to great feedback from the picocli community on the 4.0.0-alpha-1 release, this release contains many argument group-related bugfixes.
See the 4.0.0-alpha-1 New and Noteworthy section below for more details on argument groups.
Please try this and provide feedback. We can still make changes.
What do you think of the annotations API? What about the programmatic API? Does it work as expected? Are the input validation error messages correct and clear? Is the documentation clear and complete? Anything you want to change or improve? Any other feedback?
This release also has support for variable expansion and improved support for Chinese, Japanese and Korean.
Many thanks to the picocli community for the contributions!
This is the fifty-third public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Argument Groups
Many bugfixes for argument groups.
Variable Interpolation
From this release, picocli supports variable interpolation (variable expansion) in annotation attributes as well as in text attributes of the programmatic API.
Variable Interpolation Example
@Command(name = "status", description = "This command logs the status for ${PARENT-COMMAND-NAME}.")
class Status {
@Option(names = {"${dirOptionName1:--d}", "${dirOptionName2:---directories}"}, // -d or --directories
description = {"Specify one or more directories, separated by '${sys:path.separator}'.",
"The default is the user home directory (${DEFAULT-VALUE})."},
arity = "${sys:dirOptionArity:-1..*}",
defaultValue = "${sys:user.home}",
split = "${sys:path.separator}")
String[] directories;
}
Predefined Variables
The following variables are predefined:
${DEFAULT-VALUE}
: (since 3.2) - can be used in the description for an option or positional parameter, replaced with the default value for that option or positional parameter${COMPLETION-CANDIDATES}
: (since 3.2) - can be used in the description for an option or positional parameter, replaced with the completion candidates for that option or positional parameter${COMMAND-NAME}
: (since 4.0) - can be used in any section of the usage help message for a command, replaced with the name of the command${COMMAND-FULL-NAME}
: (since 4.0) - can be used in any section of the usage help message for a command, replaced with the fully qualified name of the command (that is, preceded by its parent fully qualified name)${PARENT-COMMAND-NAME}
: (since 4.0) - can be used in any section of the usage help message for a command, replaced with the name of its parent command${PARENT-COMMAND-FULL-NAME}
: (since 4.0) - can be used in any section of the usage help message for a command, replaced with the fully qualified name of its parent command (that is, preceded by the name(s) of the parent command's ancestor commands)
Custom Variables
In addition, you can define your own variables. Currently the following syntaxes are supported:
${sys:key}
: system property lookup, replaced by the value ofSystem.getProperty("key")
${env:key}
: environment variable lookup, replaced by the value ofSystem.getEnv("key")
${bundle:key}
: look up the value ofkey
in the resource bundle of the command${key}
: search all of the above, first system properties, then environment variables, and finally the resource bundle of the command
Default Values for Custom Variables
You can specify a default value to use when no value is found for a custom variable. The syntax for specifying a default is ${a:-b}
, where a
is the variable name and b
is the default value to use if a
is not found.
So, for the individual lookups, this looks like this:
${key:-defaultValue}
${sys:key:-defaultValue}
${env:key:-defaultValue}
${bundle:key:-defaultValue}
The default value may contain other custom variables. For example:
${bundle:a:-${env:b:-${sys:c:-X}}}
The above variable is expanded as follows. First, try to find key a
in the command's resource bundle. If a
is not found in the resource bundle, get the value of environment variable b
. If no environment variable b
exists, get the value of system property c
. Finally, no system property c
exists, the value of the expression becomes X
.
Escaping Variables
Sometimes you want to show a string like "${VAR}"
in a description.
A $
character can be escaped with another $
character. Therefore, $${VAR}
will not be interpreted as a VAR
variable, but will be replaced by ${VAR}
instead.
Switching Off Variable Interpolation
Variable interpolation can be switched off for the full command hierarchy by calling CommandLine.setInterpolateVariables(false)
, or for a particular command by calling CommandSpec.interpolateVariables(false)
.
Limitations of Variable Interpolation
Some attribute values need to be resolved early, when the model is constructed from the annotation values.
Specifically:
- command names and aliases, option names, mixin names
arity
(for options and positional parameters)index
(for positional parameters)separator
(for commands)
It is possible for these attributes to contain variables, but be aware of the limitations.
If these attributes have variables, and the variables get a different value after the model is constructed, the change will not be reflected in the model.
Improved Support for Chinese, Japanese and Korean
Picocli will align the usage help message to fit within some user-defined width (80 columns by default).
A number of characters in Chinese, Japanese and Korean (CJK) are wider than others.
If those characters are treated to have the same width as other characters, the usage help message may extend past the right margin.
From this release, picocli will use 2 columns for these wide characters when calculating where to put line breaks, resulting in better usage help message text.
This can be switched off with CommandLine.setAdjustLineBreaksForWideCJKCharacters(false)
.
Fixed issues
- [#495] Publish picocli as a JPMS module in a new artifact
picocli-core-module
. Thanks to Warkdev for the pull request. - [#21] Count double-width Asian characters as two characters for line-breaking purposes.
- [#526] Add support for variable interpolation in message strings. Thanks to Bob Tiernay for the suggestion.
- [#660] Added
@java.lang.annotation.Inherited
to the@picocli.CommandLine.Command
annotation. Thanks to Devin Smith for the suggestion. - [#661] Bugfix for stack overflow when option in an argument group had a default value. Thanks to Andreas Deininger for reporting this.
- [#656] Bugfix for issue where synopsis for composite argument groups did not expand for n..* (n > 1). Thanks to Arno Tuomainen for finding this issue.
- [#654] Bugfix: argument group heading text was not retrieved from ResourceBundle. Thanks to Andreas Deininger for raising this.
- [#635] Bugfix in argument group validation: did not show an error if some but not all parts of a co-occurring group were specified. Thanks to Philipp Hanslovsky for the pull request.
- [#653] Bugfix: argument group validation should be skipped if help was requested. Thanks to Andreas Deininger for raising this.
- [#655] Bugfix: argument group validation silently accepts missing subgroup with multiplicity=1.
- [#652] Documentation: fixes in user manual. Thanks to Andreas Deininger for the pull request.
- [#651] Documentation: fixes in user manual. Thanks to Andreas Deininger for the pull request.
Deprecations
No features were deprecated in this release.
Potential breaking changes
The following classes and methods introduced in 4.0.0-alpha-1 have been renamed:
Classes:
picocli.CommandLine.ParseResult.MatchedGroup
->picocli.CommandLine.ParseResult.GroupMatchContainer
picocli.CommandLine.ParseResult.MatchedGroupMultiple
->picocli.CommandLine.ParseResult.GroupMatch
Methods:
ParseResult::getMatchedGroupMultiples
has been renamed toParseResult::getGroupMatches
ParseResult::findMatchedGroup(ArgGroupSpec)
has been renamed toParseResult::findMatches(ArgGroupSpec)
Removed:
These may be implemented in a future version.
picocli.CommandLine.Option.excludes()
andpicocli.CommandLine.Parameters.excludes()
picocli.CommandLine.Option.needs(()
andpicocli.CommandLine.Parameters.needs(()