github remkop/picocli v2.2.0
picocli 2.2.0

latest releases: v4.7.5, v4.7.4, v4.7.3...
6 years ago

Picocli 2.2.0

The picocli community is pleased to announce picocli 2.2.

This release is a "Project Coin"-like release for picocli: small changes that add a lot of value.

In command line applications with subcommands, options of the parent command are often intended as "global" options that apply to all the subcommands. This release introduces a new @ParentCommand annotation that makes it easy for subcommands to access such parent command options: fields of the subcommand annotated with @ParentCommand are initialized with a reference to the parent command.

This release adds support for more built-in types, so applications don't need to register custom converters for common types. The new types include Java 7 classes like java.nio.file.Path and Java 8 classes like the value classes in the java.time package. These converters are loaded using reflection and are not available when running on Java 5 or Java 6.

This release also adds a converter attribute to the @Option and @Parameter annotations. This allows a specific option or positional parameter to use a different converter than would be used by default based on the type of the field.

Furthermore, the @Command annotation now supports a versionProvider attribute. This is useful when the version of an application should be detected dynamically at runtime. For example, an implementation may return version information obtained from the JAR manifest, a properties file or some other source.

Finally, applications may now specify a custom factory for instantiating classes that were configured as annotation attributes, like subcommands, type converters and version providers.

This is the seventeenth public release.
Picocli follows semantic versioning.

Table of Contents

  • New and noteworthy
  • Promoted features
  • Fixed issues
  • Deprecations
  • Potential breaking changes

New and noteworthy

New @ParentCommand annotation

In command line applications with subcommands, options of the top level command are often intended as "global" options that apply to all the subcommands. Prior to this release, subcommands had no easy way to access their parent command options unless the parent command made these values available in a global variable.

The @ParentCommand annotation makes it easy for subcommands to access their parent command options: subcommand fields annotated with @ParentCommand are initialized with a reference to the parent command. For example:

@Command(name = "fileutils", subcommands = List.class)
class FileUtils {

    @Option(names = {"-d", "--directory"},
            description = "this option applies to all subcommands")
    File baseDirectory;
}

@Command(name = "list")
class List implements Runnable {

    @ParentCommand
    private FileUtils parent; // picocli injects reference to parent command

    @Option(names = {"-r", "--recursive"}, 
            description = "Recursively list subdirectories")
    private boolean recursive;

    @Override
    public void run() {
        list(new File(parent.baseDirectory, "."));
    }

    private void list(File dir) {
        System.out.println(dir.getAbsolutePath());
        if (dir.isDirectory()) {
            for (File f : dir.listFiles()) {
                System.out.println(f.getAbsolutePath());
                if (f.isDirectory() && recursive) {
                    list(f);
                }
            }
        }
    }
}

More built-in types

This release adds support for more built-in types, so applications don't need to register custom converters for common types. The new types include Java 7 classes like java.nio.file.Path and Java 8 classes like the value classes in the java.time package. These converters are loaded using reflection and are not available when running on Java 5 or Java 6.

Converters for the following types were added in this release:

  • java.nio.file.Path (requires Java 7 or higher)
  • java.time value objects: Duration, Instant, LocalDate, LocalDateTime, LocalTime, MonthDay, OffsetDateTime, OffsetTime, Period, Year, YearMonth, ZonedDateTime, ZoneId, ZoneOffset (requires Java 8 or higher, invokes the parse method of these classes)
  • java.lang.Class (for the fully qualified class name)
  • java.nio.ByteOrder (for the Strings "BIG_ENDIAN" or "LITTLE_ENDIAN")
  • java.util.Currency (for the ISO 4217 code of the currency)
  • java.net.NetworkInterface (for the InetAddress or name of the network interface)
  • java.util.TimeZoneConverter (for the ID for a TimeZone)
  • java.sql.Connection (for a database url of the form jdbc:subprotocol:subname)
  • java.sql.Driver (for a database URL of the form jdbc:subprotocol:subname)
  • java.sql.Timestamp (for values in the "yyyy-MM-dd HH:mm:ss" or "yyyy-MM-dd HH:mm:ss.fffffffff" formats)

Option-specific Type Converters

This release adds a converter attribute to the @Option and @Parameter annotations. This allows a specific option or positional parameter to use a different converter than would be used by default based on the type of the field.

For example, you may want to convert the constant names defined in java.sql.Types to their int value for a specific field, but this should not impact any other int fields: other int fields should continue to use the default int converter that parses numeric values.

Example usage:

class App {
    @Option(names = "--sqlType", converter = SqlTypeConverter.class)
    int sqlType;
}

Example implementation:

class SqlTypeConverter implements ITypeConverter<Integer> {
    public Integer convert(String value) throws Exception {
        switch (value) {
            case "ARRAY"  : return Types.ARRAY;
            case "BIGINT" : return Types.BIGINT;
            case "BINARY" : return Types.BINARY;
            case "BIT"    : return Types.BIT;
            case "BLOB"   : return Types.BLOB;
            ...
        }
    }
}

Dynamic Version Information

From this release, the @Command annotation supports a versionProvider attribute. Applications may specify a IVersionProvider implementation in this attribute, and picocli will instantiate this class
and invoke it to collect version information.

This is useful when the version of an application should be detected dynamically at runtime. For example, an implementation may return version information obtained from the JAR manifest, a properties file or some other source.

Custom version providers need to implement the picocli.CommandLine.IVersionProvider interface:

public interface IVersionProvider {
    /**
     * Returns version information for a command.
     * @return version information (each string in the array is displayed on a separate line)
     * @throws Exception an exception detailing what went wrong when obtaining version information
     */
    String[] getVersion() throws Exception;
}

The GitHub project has a manifest file-based example and a build-generated version properties file-based example version provider implementation.

Custom factory

Declaratively registered subcommands, type converters and version providers must be instantiated somehow. From this release, a custom factory can be specified when constructing a CommandLine instance. This allows full control over object creation and opens possibilities for Inversion of Control and Dependency Injection. For example:

IFactory myFactory = getCustomFactory();
CommandLine cmdLine = new CommandLine(new Git(), myFactory);

Promoted features

Promoted features are features that were incubating in previous versions of picocli but are now supported and subject to backwards compatibility.

No features have been promoted in this picocli release.

Fixed issues

  • [#247] New @ParentCommand annotation to inject a reference to the parent command into subcommand fields. Thanks to michaelpj for the request.
  • [#83] Add more built-in converters. Thanks to garydgregory for the inspiration.
  • [#237] Option and Positional Parameter-specific type converters. Thanks to godzsa for the request.
  • [#236] Allow obtaining version information dynamically at runtime. Thanks to kcris for the request.
  • [#169] Configurable factory to instantiate subcommands that are registered via annotation attributes. Thanks to kakawait for the request.
  • [#252] Example version provider implementations.

Deprecations

This release has no additional deprecations.

Potential breaking changes

This release has no breaking changes.

Don't miss a new picocli release

NewReleases is sending notifications on new releases.