Releases: remkop/picocli
Picocli 4.0.0-beta-1b
Picocli 4.0.0-beta-1b
The picocli community is pleased to announce picocli 4.0.0-beta-1b. (That should have been 4.0.0-beta-1, :-) there were a few hiccups along the way...)
Annotation Processor
This release includes the first cut of an annotation processor that can build a model from the picocli annotations at compile time rather than at runtime.
Use this if you’re interested in:
- Compile time error checking. The annotation processor shows errors for invalid annotations and attributes immediately when you compile, instead of during testing at runtime, resulting in shorter feedback cycles.
- Graal native images. The annotation processor generates Graal configuration
files underMETA-INF/native-image/picocli-generated/$project
during compilation, to be included in the application jar. By embedding these configuration files, your jar is instantly Graal-enabled. In most cases no further configuration is needed when generating a native image.
Modular
The main picocli-4.x.jar
is now an explicit JPMS module, with a module-info.class
located in META-INF/versions/9
. The picocli-jpms-module
subproject has been removed.
Also, from this release the main picocli-4.x
artifact no longer contains the picocli.groovy
classes: these have been split off into a separate picocli-groovy-4.x
artifact.
Negatable Options
From picocli 4.0, options can be negatable
. When an option is negatable, picocli will recognize negative aliases of the option on the command line. See the New and Noteworthy section below for more details.
Feedback Welcome
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-fifth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Annotation Processor
This release includes the first cut of an annotation processor that can build a model from the picocli annotations at compile time rather than at runtime.
Use this if you’re interested in:
- Compile time error checking. The annotation processor shows errors for invalid annotations and attributes immediately when you compile, instead of during testing at runtime, resulting in shorter feedback cycles.
- Graal native images. The annotation processor generates and updates Graal configuration files under
META-INF/native-image/picocli-generated/$project
during compilation, to be included in the application jar.
This includes configuration files for reflection, resources and dynamic proxies.
By embedding these configuration files, your jar is instantly Graal-enabled.
The$project
location is configurable, see processor options below.
In most cases no further configuration is needed when generating a native image.
Enabling the Annotation Processor
Since Java 6, annotation processing is part of the standard javac
compiler, but many IDEs and build tools require something extra to enable annotation processing.
IDE
This page shows the steps to configure Eclipse and IntelliJ IDEA to enable annotation processing.
Maven
In Maven, use annotationProcessorPaths
in the configuration
of the maven-compiler-plugin
.
This requires maven-compiler-plugin
plugin version 3.5 or higher.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- annotationProcessorPaths requires maven-compiler-plugin version 3.5 or higher -->
<version>${maven-compiler-plugin-version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.0.0-beta-1b</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
An alternative that works with older versions of the maven-compiler-plugin
is to specify the picocli-codegen
module on the classpath as a provided
dependency. This also prevents the picocli-codegen
module from being included in the artifact the module produces as a transitive dependency.
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.0.0-beta-1b</version>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.0.0-beta-1b</version>
<provided>true</provided>
</dependency>
See Processor Options below.
Gradle
Use the annotationProcessor
path in Gradle 4.6 and higher:
dependencies {
compile 'info.picocli:picocli:4.0.0-beta-1b'
annotationProcessor 'info.picocli:picocli-codegen:4.0.0-beta-1b'
}
For Gradle versions prior to 4.6, use compileOnly
, to prevent the picocli-codegen
jar from being a transitive dependency included in the artifact the module produces.
dependencies {
compile 'info.picocli:picocli:4.0.0-beta-1b'
compileOnly 'info.picocli:picocli-codegen:4.0.0-beta-1b'
}
Picocli Processor Options
The picocli annotation processor supports the options below.
Recommended Options
project
- output subdirectory
The generated files are written to META-INF/native-image/picocli-generated/${project}
.
The project
option can be omitted, but it is a good idea to specify the project
option with a unique value for your project (e.g. ${groupId}/${artifactId}
) if your jar may be shaded with other jars into an uberjar.
Other Options
other.resource.patterns
- comma-separated list of regular expressions matching additional resources to include in the imageother.resource.bundles
- comma-separated list of the base names of additional resource bundles to include in the imageother.proxy.interfaces
- comma-separated list of the fully qualified class names of additional interfaces for which to generate proxy classes when building the imagedisable.proxy.config
- don’t generateproxy-config.json
disable.reflect.config
- don’t generatereflect-config.json
disable.resource.config
- don’t generateresources-config.json
Javac
To pass an annotation processor option with javac
, specify the -A
command line option:
javac -Aproject=org.myorg.myproject/myapp -cp ...
The -A
option lets you pass options to annotation processors. See the javac documentation for details.
Maven
To set an annotation processor option in Maven, you need to use the maven-compiler-plugin
and configure the compilerArgs
section.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- annotationProcessorPaths requires maven-compiler-plugin version 3.5 or higher -->
<version>${maven-compiler-plugin-version}</version>
<configuration>
<compilerArgs>
<arg>-Aproject=${groupId}/${artifactId}</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
See https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html for details.
Gradle Example
To set an annotation processor option in Gradle, add these options to the options.compilerArgs
list in the compileJava
block.
compileJava {
// minimum 1.6
sourceCompatibility = ${java-version}
targetCompatibility = ${java-version}
options.compilerArgs += ["-Aproject=${project.group}/${project.name}"]
}
See the Gradle documentation for details.
Negatable Options
From picocli 4.0, options can be negatable
.
class App {
@Option(names = "--verbose", negatable = true) boolean verbose;
@Option(names = "-XX:+PrintGCDetails", negatable = true) boolean printGCDetails;
@Option(names = "-XX:-UseG1GC", negatable = true) boolean useG1GC = true;
}
When an option is negatable, picocli will recognize negative aliases of the option on the command line.
For *nix-style long options, aliases have the prefix 'no-' to the given names.
For Java JVM-style options, the :+
is turned into :-
and vice versa. (This can be changed by customizing the INegatableOptionTransformer
.)
If the negated form of the option is found, for example --no-verbose
, the value is set to the provided default. Otherwise, with a regular call, for example --verbose
, it is set to the opposite of the default.
<a name="...
Picocli 4.0.0-alpha-3
Picocli 4.0.0-alpha-3
The picocli community is pleased to announce picocli 4.0.0-alpha-3.
This release adds improved support for command execution via the new execute
method.
This method returns an exit code that applications can use to call System.exit
.
The older run
, call
, invoke
and parseWithHandlers
convenience methods that were similar to execute
but had limited support for parser configuration and and limited support for exit codes are deprecated from this release.
This release also improves the picocli tools for configuring GraalVM native image builds: there is now support for commands with resource bundles and jewelcli-style @Command
-annotated interfaces for which picocli generates a dynamic proxy.
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-fourth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Executing Commands
Picocli 4.0 introduces new API to execute commands. Let’s take a quick look at what changed.
Exit Code
Many command line applications return an exit code to signify success or failure. Zero often means success, a non-zero exit code is often used for errors, but other than that, meanings differ per application.
The new CommandLine.execute
method introduced in picocli 4.0 returns an int
, and applications can use this return value to call System.exit
if desired. For example:
public static void main(String... args) {
CommandLine cmd = new CommandLine(new App());
int exitCode = cmd.execute(args);
System.exit(exitCode);
}
Older versions of picocli had some limited exit code support where picocli would call System.exit
, but this is now deprecated.
Generating an Exit Code
@Command
-annotated classes that implement Callable
and @Command
-annotated methods can simply return an int
or Integer
, and this value will be returned from CommandLine.execute
. For example:
@Command(name = "greet")
class Greet implements Callable<Integer> {
public Integer call() {
System.out.println("hi");
return 1;
}
@Command
int shout() {
System.out.println("HI!");
return 2;
}
}
assert 1 == new CommandLine(new Greet()).execute();
assert 2 == new CommandLine(new Greet()).execute("shout");
Commands with a user object that implements Runnable
can implement the IExitCodeGenerator
interface to generate an exit code. For example:
@Command(name = "wave")
class Gesture implements Runnable, IExitCodeGenerator {
public void run() {
System.out.println("wave");
}
public int getExitCode() {
return 3;
}
}
assert 3 == new CommandLine(new Gesture()).execute();
Exception Exit Codes
By default, the execute
method returns CommandLine.ExitCode.USAGE
(64
) for invalid input, and CommandLine.ExitCode.SOFTWARE
(70
) when an exception occurred in the Runnable, Callable or command method. (For reference, these values are EX_USAGE
and EX_SOFTWARE
, respectively, from Unix and Linux sysexits.h). This can be customized with the @Command
annotation. For example:
@Command(exitCodeOnInvalidInput = 123,
exitCodeOnExecutionException = 456)
Additionally, applications can configure a IExitCodeExceptionMapper
to map a specific exception to an exit code:
class MyMapper implements IExitCodeExceptionMapper {
public int getExitCode(Throwable t) {
if (t instance of FileNotFoundException) {
return 74;
}
return 1;
}
}
When the end user specified invalid input, the execute
method prints an error message followed by the usage help message of the command, and returns an exit code. This can be customized by configuring a IParameterExceptionHandler
.
If the business logic of the command throws an exception, the execute
method prints the stack trace of the exception and returns an exit code. This can be customized by configuring a IExecutionExceptionHandler
.
Configuration
The new CommandLine.execute
method is an instance method. The older run
, call
and invoke
methods are static methods. Static methods don’t allow configuration. The new API lets applications configure the parser or other aspects before execution. For example:
public static void main(String... args) {
CommandLine cmd = new CommandLine(new App());
cmd.setCaseInsensitiveEnumValuesAllowed(true);
cmd.setUnmarchedArgumentsAllowed(true);
cmd.setStopAtPositional(true);
cmd.setExpandAtFiles(false);
cmd.execute(args);
}
Execution Configuration
The following configuration methods are new and are only applicable with the execute
method (and executeHelpRequest
):
- get/setOut
- get/setErr
- get/setColorScheme
- get/setExecutionStrategy
- get/setParameterExceptionHandler
- get/setExecutionExceptionHandler
- get/setExitCodeExceptionMapper
The above methods are not applicable (and ignored) with other entry points like parse
, parseArgs
, populateCommand
, run
, call
, invoke
, parseWithHandler
and parseWithHandlers
.
API Evolution and Trade-offs
Previous versions of picocli offered the run
, call
and invoke
methods to execute a Runnable
, Callable
or Method
command. Here are some trade-offs versus the new execute
method:
- Static - These are static methods, with the drawback that they don't allow configuration, as mentioned above.
- Type Safety - It is a compile-time error when an application tries to pass anything else than a
Runnable
to therun
method, and aCallable
to thecall
method. Theexecute
method does not have this type safety, since theCommandLine
constructor allows anyObject
as a parameter. - Return Value - The
call
andinvoke
static methods allow commands to return any value, while theexecute
method only returns anint
exit code. From 4.0 the result object will be available from theCommandLine.getExecutionResult
method.
Feedback Requested
With the new execute API the ColorScheme
class will start to play a more central role. I decided to make the ColorScheme
class immutable from this release. This is a breaking API change.
Should it be deprecated first, or not changed at all, or is the 4.0 release a good time to make breaking changes? Your feedback is very welcome on #675.
Tools for Configuring GraalVM Native Image Builds
The picocli-codegen
module now has two new tools, in addition to the existing ReflectionConfigGenerator
:
- ResourceConfigGenerator
- DynamicProxyConfigGenerator
ResourceConfigGenerator
The GraalVM native-image builder by default will not integrate any of the
classpath resources into the image it creates.
ResourceConfigGenerator
generates a JSON String with the resource bundles and other classpath resources
that should be included in the Substrate VM native image.
The output of ResourceConfigGenerator
is intended to be passed to the -H:ResourceConfigurationFiles=/path/to/reflect-config.json
option of the native-image
GraalVM utility,
or placed in a META-INF/native-image/
subdirectory of the JAR.
This allows picocli-based native image applications to access these resources.
DynamicProxyConfigGenerator
Substrate VM doesn't provide machinery for generating and interpreting bytecodes at run time. Therefore all dynamic proxy classes
need to be generated at native image build time.
DynamicProxyConfigGenerator
generates a JSON String with the fully qualified interface names for which
dynamic proxy classes should be generated at native image build time.
The output of DynamicProxyConfigGenerator
is intended to be passed to the -H:DynamicProxyConfigurationFiles=/path/to/proxy-config.json
option of the native-image
GraalVM utility,
or placed in a META-INF/native-image/
subdirectory of the JAR.
This allows picocli-based native image applications that use @Command
-annotated interfaces with
@Option
and @Parameters
-annotated methods.
Fixed issues
- [#516] API: Add support for color schemes in the convenience methods and associated classes and interfaces. Thanks to Bob Tiernay for the suggestion.
- [#561] API: Parser configuration for convenience methods.
- [#650] API: Global parser configuration if using Runnable. Thanks to gitfineon for raising this.
- [#424] API: Exit on help, version or invalid arguments. Thanks to Gerard Bosch for raising this.
- [#541] API: Improved exception handling for Runnable/Callable.
- [#680] API: Add annotation API for exitCodeList and exitCodeListHeading.
- [#611] API: Add
CommandLine.addSubcommand
overloaded method without name or alias....
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(()
Picocli 3.9.6
Picocli 3.9.6
The picocli community is pleased to announce picocli 3.9.6.
This release improves support for interactive (password) options:
- interactive options can now use type
char[]
instead of String, to allow applications to null out the array after use so that sensitive information is no longer resident in memory - interactive options can be optionally interactive if configured with
arity = "0..1"
This is the fifty-second public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
This release improves support for interactive (password) options:
- interactive options can now use type
char[]
instead of String, to allow applications to null out the array after use so that sensitive information is no longer resident in memory - interactive options can be optionally interactive if configured with
arity = "0..1"
For example, if an application has these options:
@Option(names = "--user")
String user;
@Option(names = "--password", arity = "0..1", interactive = true)
char[] password;
With the following input, the password
field will be initialized to "123"
without prompting the user for input:
--password 123 --user Joe
However, if the password is not specified, the user will be prompted to enter a value. In the following example, the password option has no parameter, so the user will be prompted to type in a value on the console:
--password --user Joe
Fixed issues
- [#657] Support type
char[]
for interactive options. Thanks to Lukáš Petrovický for raising this issue. - [#536] Support optionally interactive options. Thanks to Lukas Heumos for raising this issue.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 4.0.0-alpha-1
Picocli 4.0.0-alpha-1
The picocli community is pleased to announce picocli 4.0.0-alpha-1.
This release adds support for argument groups (incubating). Argument groups enable the following:
- mutually exclusive options
- options that must co-occur (dependent options)
- option sections in the usage help message
- repeating composite arguments
See the New and Noteworthy section below for more details.
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?
Many thanks to the picocli community members who contributed!
This is the fifty-first public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Argument Groups (Incubating)
This release introduces a new @ArgGroup
annotation and its ArgGroupSpec
programmatic equivalent.
Argument Groups can be used to define:
- mutually exclusive options
- options that must co-occur (dependent options)
- option sections in the usage help message
- repeating composite arguments
To create a group using the annotations API, annotate a field or method with @ArgGroup
.
The field's type refers to the class containing the options and positional parameters in the group.
(For annotated interface methods this would be the return type, for annotated setter methods in a concrete class this would be the setter's parameter type.)
Picocli will instantiate this class as necessary to capture command line argument values in the @Option
and @Parameters
-annotated fields and methods of this class.
Mutually Exclusive Options
Annotate a field or method with @ArgGroup(exclusive = true)
to create a group of mutually exclusive options and positional parameters. For example:
@Command(name = "exclusivedemo")
public class MutuallyExclusiveOptionsDemo {
@ArgGroup(exclusive = true, multiplicity = "1")
Exclusive exclusive;
static class Exclusive {
@Option(names = "-a", required = true) int a;
@Option(names = "-b", required = true) int b;
@Option(names = "-c", required = true) int c;
}
}
The above example defines a command with mutually exclusive options -a
, -b
and -c
.
The group itself has a multiplicity
attribute that defines how many times the group may be specified within the command.
The default is multiplicity = "0..1"
, meaning that by default a group may be omitted or specified once.
In this example the group has multiplicity = "1"
, so the group must occur once: one of the exclusive options must occur on the command line.
The synopsis of this command is exclusivedemo (-a=<a> | -b=<b> | -c=<c>)
.
Note that the options are defined as required = true
; this means required within the group, not required within the command.
Picocli will validate the arguments and throw a MutuallyExclusiveArgsException
if multiple mutually exclusive arguments were specified. For example:
MutuallyExclusiveOptionsDemo example = new MutuallyExclusiveOptionsDemo();
CommandLine cmd = new CommandLine(example);
try {
cmd.parseArgs("-a=1", "-b=2");
} catch (MutuallyExclusiveArgsException ex) {
assert "Error: -a=<a>, -b=<b> are mutually exclusive (specify only one)"
.equals(ex.getMessage());
}
For the above group, only one of the options can be specified. Any other combination of options, or the absence of options, is invalid.
Co-occurring (Dependent) Options
Annotate a field or method with @ArgGroup(exclusive = false)
to create a group of dependent options and positional parameters that must co-occur. For example:
@Command(name = "co-occur")
public class DependentOptionsDemo {
@ArgGroup(exclusive = false)
Dependent dependent;
static class Dependent {
@Option(names = "-a", required = true) int a;
@Option(names = "-b", required = true) int b;
@Option(names = "-c", required = true) int c;
}
}
The above example defines a command with dependent options -a
, -b
and -c
that must co-occur.
The group itself has a multiplicity
attribute that defines how many times the group may be specified within the command.
In this example the group uses the default multiplicity, multiplicity = "0..1"
, meaning that the group may be omitted or specified once.
The synopsis of this command is co-occur [-a=<a> -b=<b> -c=<c>]
.
Note that the options are defined as required = true
; this means required within the group, not required within the command.
Picocli will validate the arguments and throw a MissingParameterException
if not all dependent arguments were specified. For example:
DependentOptionsDemo example = new DependentOptionsDemo();
CommandLine cmd = new CommandLine(example);
try {
cmd.parseArgs("-a=1", "-b=2");
} catch (MissingParameterException ex) {
assert "Error: Missing required argument(s): -c=<c>".equals(ex.getMessage());
}
Option Sections in Usage Help
The example below uses groups to define options sections in the usage help.
When a group has a non-null heading
(or headingKey
), the options in the group are given the specified heading in the usage help message.
The headingKey
attribute can be used to get the heading text from the command's resource bundle.
This works for mutually exclusive or co-occurring groups, but it is also possible to define a group that does no validation but only creates an option section in the usage help.
Annotate a field or method with @ArgGroup(validate = false)
to create a group for display purposes only. For example:
@Command(name = "sectiondemo", description = "Section demo")
public class OptionSectionDemo {
@ArgGroup(validate = false, heading = "This is the first section%n")
Section1 section1;
static class Section1 {
@Option(names = "-a", description = "Option A") int a;
@Option(names = "-b", description = "Option B") int b;
@Option(names = "-c", description = "Option C") int c;
}
@ArgGroup(validate = false, heading = "This is the second section%n")
Section2 section2;
static class Section2 {
@Option(names = "-x", description = "Option X") int x;
@Option(names = "-y", description = "Option Y") int y;
@Option(names = "-z", description = "Option X") int z;
}
public static void main(String[] args) {
new CommandLine(new OptionSectionDemo()).usage(System.out);
}
}
This prints the following usage help message:
Usage: sectiondemo [-a=<a>] [-b=<b>] [-c=<c>] [-x=<x>] [-y=<y>] [-z=<z>]
Section demo
This is the first section
-a=<a> Option A
-b=<b> Option B
-c=<c> Option C
This is the second section
-x=<x> Option X
-y=<y> Option Y
-z=<z> Option X
Note that the heading text must end with %n
to insert a newline between the heading text and the first option.
This is for consistency with other headings in the usage help, like @Command(headerHeading = "Usage:%n", optionListHeading = "%nOptions:%n")
.
Repeating Composite Argument Groups
The below example shows how groups can be composed of other groups, and how arrays and collections can be used to capture repeating groups (with a multiplicity
greater than one):
public class CompositeGroupDemo {
@ArgGroup(exclusive = false, multiplicity = "1..*")
List<Composite> composites;
static class Composite {
@ArgGroup(exclusive = false, multiplicity = "1")
Dependent dependent;
@ArgGroup(exclusive = true, multiplicity = "1")
Exclusive exclusive;
}
static class Dependent {
@Option(names = "-a", required = true) int a;
@Option(names = "-b", required = true) int b;
@Option(names = "-c", required = true) int c;
}
static class Exclusive {
@Option(names = "-x", required = true) boolean x;
@Option(names = "-y", required = true) boolean y;
@Option(names = "-z", required = true) boolean z;
}
}
In the above example, the annotated composites
field defines a composite group that must be specified at least once, and may be specified many times, on the command line.
Each time the group is matched, picocli creates an instance of the Composite
class and adds it to the composites
list.
The Composite
class itself contains two groups: a group of dependent options that must co-occur, and another group of mutually exclusive options.
Both of these subgroups have multiplicity = "1"
, so they can occur exactly once for each multiple of the Composite
group. The below example illustrates:
CompositeGroupDemo example = new CompositeGroupDemo();
CommandLine cmd = new CommandLine(example);
cmd.parseArgs("-x", "-a=1", "-b=1", "-c=1", "-a=2", "-b=2", "-c=2", "-y");
assert example.composites.size() == 2;
Composite c1 = example.composites.get(0);
assert c1.exclusive.x;
assert c1.dependent.a == 1;
assert c1.dependent.b == 1;
assert c1.dependent.c == 1;
Composite c2 = example.composites.get(1);
assert c2.exclusive.y;
assert c2.dependent.a == 2;
assert c2.dependent.b == 2;
assert c2.dependent.c == 2;
Positional Parameters
When a...
Picocli 3.9.5
Picocli 3.9.5
The picocli community is pleased to announce picocli 3.9.5.
This release contains a critical workaround to protect against JVM crashes when running on RedHat Linux 3.10.0-327.44.2.el7.x86_64.
Picocli 3.9.0 introduced a change in the heuristics for detecting when to emit ANSI escape sequences. As part of this change, picocli may load the org.fusesource.jansi.AnsiConsole
class from the JAnsi library when not running on Windows. This may crash the JVM.
The underlying problem may be a bug in the native library in jansi 1.14, see fusesource/jansi-native#17 for details.
The workaround in this release is to only load the AnsiConsole
class when running on Windows.
Users using 3.9.0 and higher are strongly recommended to upgrade to 3.9.5 or later.
Note that this issue can manifest itself when running in Gradle (e.g. continuous integration tests) even if the application itself does not have the jansi library in the classpath, since the jansi classes can be loaded from the jansi-1.14 jar included in Gradle 4.5.x.
This is the fiftieth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#630] Avoid loading
org.fusesource.jansi.AnsiConsole
when not running on Windows to avoid JVM crashes on non-Windows platforms. - [#632] For generating GraalVM native images,
ReflectionConfigGenerator
inpicocli-codegen
now specifies theallowWrite = true
attribute for final fields.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 3.9.4
Picocli 3.9.4
The picocli community is pleased to announce picocli 3.9.4.
This release contains bugfixes and enhancements.
From this release, enum
-typed options and positional parameters that are multi-value can be stored in EnumSet
collections (in addition to other Collections, arrays and Maps).
Also, a better error message is now shown when unknown options are encountered while processing clustered short options. The new error message includes both the failing part and the original command line argument.
Bugfixes:
ReflectionConfigGenerator
incorrectly listed superclass fields as fields of the concrete subclass, causing "GraalVM error: Error parsing reflection configuration in json" when creating a native image.- Method subcommands in commands that subclass another command caused
InitializationException
.
This is the forty-nineth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#628] Add support for collecting
enum
multi-value options and positional parameters inEnumSet<>
collections. Thanks to Lee Atkinson for raising this. - [#619] Bugfix: Method subcommands in commands that subclass another command caused
InitializationException
: "Another subcommand named 'method' already exists...". Thanks to PorygonZRocks for the bug report. - [#622] Bugfix:
ReflectionConfigGenerator
incorrectly listed superclass fields as fields of the concrete subclass, causing "GraalVM error: Error parsing reflection configuration in json". Thanks to Sebastian Thomschke for the bug report. - [#623]
ReflectionConfigGenerator
now generates json in alphabetic order. - [#627] Improve error message for unknown options when processing clustered short options.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 3.9.3
Picocli 3.9.3
The picocli community is pleased to announce picocli 3.9.3.
This release contains bugfixes and enhancements.
This is the forty-eight public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#613] Enhancement: Improve picocli heuristics for unmatched options: single-character arguments that don't exactly match options (like
-
) should be considered positional parameters. Thanks to Oliver Weiler for the bug report. - [#615] Bugfix: Opaque stacktrace for "%" in Option description. Thanks to petermr for the bug report.
- [#616] Bugfix: showDefaultValues=true with defaultValueProvider did not render defaultValues in usage help. Thanks to Sebastian Thomschke for the bug report.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 3.9.2
Picocli 3.9.2
The picocli community is pleased to announce picocli 3.9.2.
This release contains bugfixes and enhancements.
Picocli now has a mailing list picocli at googlegroups dot com
. Alternatively visit the picocli Google group web interface.
The user manual has improved documentation for internationalization and localization, and the section on Dependency Injection now has a Spring Boot example and link to the Micronaut user manual.
Bugfixes: AutoComplete
now uses the specified IFactory
correctly for CommandLine
; defaulting usageHelp
or versionHelp
options no longer prevents validation of required options; and usage help for booleans options with arity = "1"
now correctly show the option parameter in the synopsis.
Many thanks to the many members of the picocli community who contributed pull requests, bug reports and participated in discussions!
This is the forty-seventh public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Picocli now has a mailing list picocli at googlegroups dot com
. Alternatively visit the picocli Google group web interface.
The user manual has improved documentation for internationalization and localization. Dependency Injection is now a top-level section and now has a Spring Boot example and link to the Micronaut user manual.
Fixed issues
- [#602] Make
CommandLine
inAutoComplete
use correctIFactory
implementation. Thanks to Mikołaj Krzyżanowski for the pull request. - [#608] Bugfix: defaulting
usageHelp
orversionHelp
options incorrectly prevented validation of required options and positional parameters. Thanks to Pietro Braione for the bug report. - [#612] Bugfix: Usage help for booleans options with
arity = "1"
now correctly show the option parameter in synopsis. Thanks to prewersk for the bug report. - [#606] Doc: Added subcommand example. Thanks to Andreas Deininger for the pull request.
- [#605] Doc: Improved documentation for internationalization and localization. Thanks to Andreas Deininger for raising this.
- [#604] Doc: Improve user manual section on Dependency Injection: add Spring Boot example. Thanks to Alistair Rutherford for the example code.
- [#610] Build: add JDKs to Travis CI build.
- [#609] Created mailing list
picocli at googlegroups dot com
: picocli Google group.
Deprecations
No features were deprecated in this release.
Potential breaking changes
This release has no breaking changes.
Picocli 3.9.1
Picocli 3.9.1
The picocli community is pleased to announce picocli 3.9.1.
The picocli.AutoComplete
application no longer calls System.exit()
unless requested by setting system property picocli.autocomplete.systemExitOnError
or picocli.autocomplete.systemExitOnSuccess
to any value other than false
. Applications that rely on the exit codes introduced in picocli 3.9.0 need to set these system properties.
This release adds support for quoted map keys with embedded '=' characters.
This release contains bugfixes and enhancements.
This is the forty-sixth public release.
Picocli follows semantic versioning.
Table of Contents
New and Noteworthy
Fixed issues
- [#592] Error message now shows
enum
constant names, nottoString()
values, after value mismatch. Thanks to startewho for the bug report. - [#591] Replace some String concatenation in
picocli.AutoComplete
with StringBuilder. Thanks to Sergio Escalante for the pull request. - [#594] Add support for quoted map keys with embedded '=' characters. Thanks to Pubudu Fernando for the suggestion.
- [#596]
picocli.AutoComplete
should not callSystem.exit()
unless requested. Thanks to Markus Heiden, Bob Tiernay and RobertZenz for analysis and ideas contributing to the solution. - [#593] Use Gradle Bintray Plugin to publish artifacts to Bintray.
Deprecations
No features were deprecated in this release.
Potential breaking changes
The picocli.AutoComplete
application no longer calls System.exit()
unless requested by setting system property picocli.autocomplete.systemExitOnError
or picocli.autocomplete.systemExitOnSuccess
to any value other than false
.
Applications that rely on the exit codes introduced in picocli 3.9.0 need to set these system properties.
The new support for quoted map keys with embedded '=' characters [#594] may inpact some existing applications.
If CommandLine::setTrimQuotes()
is set to true
, quotes are now removed from map keys and map values. This did not use to be the case.
For example:
class App {
@Option(names = "-p") Map<String, String> map;
}
When CommandLine::setTrimQuotes()
was set to true
, given input like the below:
-p AppOptions="-Da=b -Dx=y"
The above used to result in a map with key AppOptions
and value "-Da=b -Dx=y"
(including the quotes), but the same program and input now results in a map with key AppOptions
and value -Da=b -Dx=y
(without quotes).
Also, when CommandLine::setTrimQuotes()
is false
(the default), input like the below will now cause a ParameterException
("value should be in KEY=VALUE format"):
-p "AppOptions=-Da=b -Dx=y"
Prior to this release, the above was silently ignored (no errors but also no key-value pairs in the resulting map).