Picocli 4.0.0-beta-2
The picocli community is pleased to announce picocli 4.0.0-beta-2.
Bugfixes and improvements.
This release introduces two new attributes on the Option
annotation:
fallbackValue
parameterConsumer
fallbackValue
is for options with optional parameter: assign this value when the option was specified on the command line without parameter. parameterConsumer
and the associated IParameterConsumer
interface allows for options to bypass picocli's parsing logic and replace it with custom logic. One use case is collecting arguments to pass them through to another command.
This release introduces a new synopsisSubcommandLabel
attribute on the @Command
annotation to allow customization of the subcommands part of the synopsis. This is useful for applications that have required subcommands.
Also, this release adds the ability to dynamically detect the terminal width.
From this release, the picocli JAR is an OSGi bundle with Bundle-Name: picocli
and other appropriate metadata in the manifest.
Please try this and provide feedback. We can still make changes.
What do you think of the @ArgGroup
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?
Many thanks to the picocli community for the contributions!
This is the fifty-sixth public release.
Picocli follows semantic versioning.
Table of Contents
- New and noteworthy
- Fixed issues
- Deprecations
- Potential breaking changes
New and Noteworthy
Fallback Value API
This release introduces a new attribute on the Option
annotation: fallbackValue
for options with optional parameter: assign this value when the option was specified on the command line without parameter.
This is different from the defaultValue
, which is assigned if the option is not specified at all on the command line.
Using a fallbackValue
allows applications to distinguish between cases where
- the option was not specified on the command line (default value assigned)
- the option was specified without parameter on the command line (fallback value assigned)
- the option was specified with parameter on the command line (command line argument value assigned)
This is useful to define options that can function as a boolean "switch" and optionally allow users to provide a (strongly typed) extra parameter value.
The option description may contain the ${FALLBACK-VALUE}
variable which will be replaced with the actual fallback value when the usage help is shown.
Synopsis Subcommand Label
For commands with subcommands, the string [COMMAND]
is appended to the end of the synopsis (whether the synopsis is abbreviated or not). This looks something like this:
<cmd> [OPTIONS] FILES [COMMAND]
From picocli 4.0, this can be customized with the synopsisSubcommandLabel
attribute.
For example, to clarify that a subcommand is mandatory, an application may specify COMMAND
, without the [
and ]
brackets:
@Command(name = "git", synopsisSubcommandLabel = "COMMAND")
class Git implements Runnable {
@Spec CommandSpec spec;
public void run() {
throw new ParameterException(spec.commandLine(), "Missing required subcommand");
}
}
An application with a limited number of subcommands may want to show them all in the synopsis, for example:
@Command(name = "fs", synopsisSubcommandLabel = "(list | add | delete)",
subcommands = {List.class, Add.class, Delete.class})
class Fs { ... }
Dynamically Detect Terminal Size
From this release, commands defined with @Command(usageHelpAutoWidth = true)
will try to adjust the usage message help layout to the terminal width.
There is also programmatic API to control this via the CommandLine::setUsageHelpAutoWidth
and UsageMessageSpec::autoWidth
methods.
End users may enable this by setting system property picocli.usage.width
to AUTO
, and may disable this by setting this system property to a numeric value.
This feature requires Java 7.
Custom Parameter Processing
Options or positional parameters can be assigned a IParameterConsumer
that implements custom logic to process the parameters for this option or this position. When an option or positional parameter with a custom IParameterConsumer
is matched on the command line, picocli's internal parser is temporarily suspended, and the custom parameter consumer becomes responsible for consuming and processing as many command line arguments as needed.
This can be useful when passing options through to another command.
For example, the unix find
command has a -exec
option to execute some action for each file found. Any arguments following the -exec
option until a ;
or +
argument are not options for the find
command itself, but are interpreted as a separate command and its options.
The example below demonstrates how to implement find -exec
using this API:
@Command(name = "find")
class Find {
@Option(names = "-exec", parameterConsumer = ExecParameterConsumer.class)
List<String> list = new ArrayList<String>();
}
class ExecParameterConsumer implements IParameterConsumer {
public void consumeParameters(Stack<String> args, ArgSpec argSpec, CommandSpec commandSpec) {
List<String> list = argSpec.getValue();
while (!args.isEmpty()) {
String arg = args.pop();
list.add(arg);
// `find -exec` semantics: stop processing after a ';' or '+' argument
if (";".equals(arg) || "+".equals(arg)) {
break;
}
}
}
}
Fixed issues
- [#280] API:
@Option(fallbackValue = "...")
for options with optional parameter: assign this value when the option was specified on the command line without parameter. Thanks to Paolo Di Tommaso and marinier for the suggestion and in-depth discussion. - [#625] API:
@Command(synopsisSubcommandLabel = "...")
to allow customization of the subcommands part of the synopsis: by default this is[COMMAND]
. Thanks to Sebastian Thomschke and AlcaYezz for the feature request and subsequent discussion. - [#718] API: Add
IParameterConsumer
and@Option(parameterConsumer = Xxx.class)
for passing arguments through to another command, likefind -exec
. Thanks to Reinhard Pointner for the suggestion. - [#721] API: Add public method Text.getCJKAdjustedLength().
- [#634] API: Dynamically detect terminal size. Requires Java 7. Thanks to my colleague Takuya Ishibashi for the suggestion.
- [#737] Deprecate the
parse
method in favor ofparseArgs
. - [#717] Negatable options change: avoid unmappable character
±
for synopsis: it renders as scrambled characters in encoding ASCII and in some terminals. - [#734][#735] Make the picocli jar OSGi friendly. Thanks to Radu Cotescu for the pull request.
- [#733] Improve error message for unmatched arguments. Thanks to my colleague Takuya Ishibashi for raising this.
- [#719] Bugfix: options with variable arity should stop consuming arguments on custom end-of-options delimiter.
- [#720] Bugfix:
@Unmatched
list should be cleared prior to subsequent invocations. - [#723] Bugfix: variables in
defaultValue
were not expanded in usage help option description line forshowDefaultValues = true
. Thanks to Mikaël Barbero for raising this. - [#722] Bugfix: synopsis of deeply nested
@ArgGroup
shows@Options
duplicate on outer level of command. Thanks to Shane Rowatt for raising this. - [#724] Bugfix: Usage message exceeds width.
- [#731] Doc: Add Zero Bugs Commitment to README.
Deprecations
From this release, the parse
method is deprecated in favor of parseArgs
.
Potential breaking changes
The error message for unmatched arguments now shows the index in the command line arguments where the unmatched argument was found,
and shows the unmatched value in single quotes. This is useful when the unmatched value is whitespace or an empty String.
For example:
Previously: Unmatched arguments: B, C
New : Unmatched arguments from index 1: 'B', 'C'
This may break tests that rely on the exact error message.