Skip to content

Releases: remkop/picocli

Picocli 4.0.0-beta-1b

05 Jun 12:25
Compare
Choose a tag to compare

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 under META-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 image
  • other.resource.bundles - comma-separated list of the base names of additional resource bundles to include in the image
  • other.proxy.interfaces - comma-separated list of the fully qualified class names of additional interfaces for which to generate proxy classes when building the image
  • disable.proxy.config - don’t generate proxy-config.json
  • disable.reflect.config - don’t generate reflect-config.json
  • disable.resource.config - don’t generate resources-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="...

Read more

Picocli 4.0.0-alpha-3

13 May 12:39
Compare
Choose a tag to compare

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 the run method, and a Callable to the call method. The execute method does not have this type safety, since the CommandLine constructor allows any Object as a parameter.
  • Return Value - The call and invoke static methods allow commands to return any value, while the execute method only returns an int exit code. From 4.0 the result object will be available from the CommandLine.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....
Read more

Picocli 4.0.0-alpha-2

18 Apr 11:24
Compare
Choose a tag to compare

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 of System.getProperty("key")
  • ${env:key}: environment variable lookup, replaced by the value of System.getEnv("key")
  • ${bundle:key}: look up the value of key 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 to ParseResult::getGroupMatches
  • ParseResult::findMatchedGroup(ArgGroupSpec) has been renamed to ParseResult::findMatches(ArgGroupSpec)

Removed:

These may be implemented in a future version.

  • picocli.CommandLine.Option.excludes() and picocli.CommandLine.Parameters.excludes()
  • picocli.CommandLine.Option.needs(() and picocli.CommandLine.Parameters.needs(()

Picocli 3.9.6

06 Apr 10:54
Compare
Choose a tag to compare

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

30 Mar 10:47
Compare
Choose a tag to compare

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...

Read more

Picocli 3.9.5

18 Feb 13:47
Compare
Choose a tag to compare

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 in picocli-codegen now specifies the allowWrite = 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

17 Feb 11:49
Compare
Choose a tag to compare

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 in EnumSet<> 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

01 Feb 10:22
Compare
Choose a tag to compare

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

20 Jan 11:14
Compare
Choose a tag to compare

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 in AutoComplete use correct IFactory implementation. Thanks to Mikołaj Krzyżanowski for the pull request.
  • [#608] Bugfix: defaulting usageHelp or versionHelp 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

10 Jan 16:15
Compare
Choose a tag to compare

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, not toString() 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 call System.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).