Picocli 3.0.0-alpha-1
The picocli community is pleased to announce picocli 3.0.0-alpha-1.
This release offers a programmatic API for creating command line applications, in addition to annotations. The programmatic API allows applications to dynamically create command line options on the fly, and also makes it possible to create idiomatic domain-specific languages for processing command line arguments, using picocli, in other JVM languages.
Another new feature in this release are Mixins. Mixins allow reusing common options, parameters and command attributes in multiple applications without copy-and-paste duplication.
Third, this release aims to reduce boilerplate code in user applications even further with the new mixinStandardHelpOptions
command attribute. Picocli adds standard usageHelp
and versionHelp
options to commands with this attribute. Additionally picocli now offers a HelpCommand
that can be installed as a subcommand on any application command to provide usage help for the parent command or sibling subcommands.
From this release, picocli is better at following unix conventions: print to stdout when the user requested help, and print to stderr when the input was invalid or an unexpected error occurred.
Also, this release gives better control over the process exit code.
Additionally, fields annotated with @Unmatched
will be populated with the unmatched arguments.
Furthermore, this release adds a showDefaultValue
attribute to the @Option
and @Parameters
annotation.
This is the twenty-first public release.
Picocli follows semantic versioning.
Table of Contents
- New and noteworthy
- Promoted features
- Fixed issues
- Deprecations
- Potential breaking changes
New and Noteworthy
Programmatic API (INCUBATING)
This release offers a programmatic API for creating command line applications, in addition to annotations. The programmatic API allows applications to dynamically create command line options on the fly, and also makes it possible to create idiomatic domain-specific languages for processing command line arguments, using picocli, in other JVM languages.
Note that the programmatic API is incubating and the API may change in subsequent releases. If you have suggestions for improving the programmatic API, please raise a ticket on GitHub!
Example
CommandSpec spec = CommandSpec.create();
spec.mixinStandardHelpOptions(true); // usageHelp and versionHelp options
spec.addOption(OptionSpec.builder("-c", "--count")
.paramLabel("COUNT")
.type(int.class)
.description("number of times to execute").build());
spec.addPositional(PositionalParamSpec.builder()
.paramLabel("FILES")
.type(List.class)
.auxiliaryTypes(File.class) // List<File>
.description("The files to process").build());
CommandLine commandLine = new CommandLine(spec);
commandLine.parseWithSimpleHandlers(new AbstractSimpleParseResultHandler() {
public void handle(ParseResult pr) {
int count = pr.optionValue('c', 1);
List<File> files = pr.positionalValue(0, Collections.<File>emptyList());
for (int i = 0; i < count; i++) {
for (File f : files) {
System.out.printf("%d: %s%n", i, f);
}
}
}
}, args);
CommandSpec (INCUBATING)
CommandSpec
models a command. It is the programmatic variant of the @Command
annotation. It has a name and a version, both of which may be empty. It also has a UsageMessageSpec
to configure aspects of the usage help message and a ParserSpec
that can be used to control the behaviour of the parser.
OptionSpec and PositionalParamSpec (INCUBATING)
OptionSpec
models a named option, and PositionalParamSpec
models one or more positional parameters. They are the programmatic variant of the @Option
and @Parameters
annotations, respectively.
An OptionSpec
must have at least one name, which is used during parsing to match command line arguments. Other attributes can be left empty and picocli will give them a reasonable default value. This defaulting is why OptionSpec
objects are created with a builder: this allows you to specify only some attributes and let picocli initialise the other attributes. For example, if only the option’s name is specified, picocli assumes the option takes no parameters (arity = 0), and is of type boolean
. Another example, if arity is larger than 1
, picocli sets the type to List
and the auxiliary type
to String
.
PositionalParamSpec
objects don’t have names, but have an index range instead. A single PositionalParamSpec
object can capture multiple positional parameters. The default index range is set to 0..*
(all indices). A command may have multiple PositionalParamSpec
objects to capture positional parameters at different index ranges. This can be useful if positional parameters at different index ranges have different data types.
Similar to OptionSpec
objects, Once a PositionalParamSpec
is constructed, its configuration becomes immutable, but its value
can still be modified. Usually the value is set during command line parsing when a non-option command line argument is encountered at a position in its index range.
ParseResult (INCUBATING)
A ParseResult
class is now available that allows applications to inspect the result of parsing a sequence of command line arguments.
This class provides methods to query whether the command line arguments included certain options or position parameters, and what the value or values of these options and positional parameters was. Both the original command line argument String value as well as a strongly typed value can be obtained.
Mixins for Reuse
Mixins are a convenient alternative to subclassing: picocli annotations from any class can be added to ("mixed in" with) another command. This includes options, positional parameters, subcommands and command attributes. Picocli autoHelp internally uses a mixin.
A mixin is a separate class with options, positional parameters, subcommands and command attributes that can be reused in other commands. Mixins can be installed by calling the CommandLine.addMixin
method with an object of this class, or annotating a field in your command with @Mixin
. Here is an example mixin class:
public class ReusableOptions {
@Option(names = { "-v", "--verbose" }, description = {
"Specify multiple -v options to increase verbosity.", "For example, `-v -v -v` or `-vvv`" })
protected boolean[] verbosity = new boolean[0];
}
Adding Mixins Programmatically
The below example shows how a mixin can be added programmatically with the CommandLine.addMixin
method.
CommandLine commandLine = new CommandLine(new MyCommand());
commandline.addMixin("myMixin", new ReusableOptions());
@Mixin
Annotation
A command can also include mixins by annotating fields with @Mixin
. All picocli annotations found in the mixin class
are added to the command that has a field annotated with @Mixin
. For example:
@Command(name = "zip", description = "Example reuse with @Mixin annotation.")
public class MyCommand {
// adds the options defined in ReusableOptions to this command
@Mixin
private ReusableOptions myMixin;
}
Standard Help Options
This release introduces the mixinStandardHelpOptions
command attribute. When this attribute is set to true
, picocli adds a mixin to the command that adds usageHelp
and versionHelp
options to the command. For example:
@Command(mixinStandardHelpOptions = true, version = "auto help demo - picocli 3.0")
class AutoHelpDemo implements Runnable {
@Option(names = "--option", description = "Some option.")
String option;
@Override public void run() { }
}
Commands with mixinStandardHelpOptions
do not need to explicitly declare fields annotated with @Option(usageHelp = true)
and @Option(versionHelp = true)
any more. The usage help message for the above example looks like this:
Usage: <main class> [-hV] [--option=<option>]
--option=<option> Some option.
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
Help Command
From this release, picocli provides a help
subcommand (picocli.CommandLine.HelpCommand
) that can be installed as a subcommand on any application command to provide usage help for the parent command or sibling subcommands. For example:
@Command(subcommands = HelpCommand.class)
class AutoHelpDemo implements Runnable {
@Option(names = "--option", description = "Some option.")
String option;
@Override public void run() { }
}
# print help for the `maincommand` command
maincommand help
# print help for the `subcommand` command
maincommand help subcommand
For applications that want to create a custom help command, this release also introduces a new interface picocli.CommandLine.IHelpCommandInitializable
that provides custom help commands with the information they need: access to the parent command and sibling commands, whether to use Ansi colors or not, and the streams to print the usage help message to.
@Unmatched
Annotation
From this release, fields annotated with @Unmatched
will be populated with the unmatched arguments.
The field must be of type String[]
or List<String>
.
If picocli finds a field annotated with @Unmatched
, it automatically sets unmatchedArgumentsAllowed
to true
so no UnmatchedArgumentException
is thrown when a command line argument cannot be assigned to an option or positional parameter.
Stdout or Stderr
From picocli v3.0, the run
and call
convenience methods follow unix conventions:
print to stdout when the user requested help, and print to stderr when the input was invalid or an unexpected error occurred.
Custom handlers can extend AbstractHandler
to facilitate following this convention.
AbstractHandler
also provides useOut
and useErr
methods to allow customizing the target output streams,
and useAnsi
to customize the Ansi style to use:
@Command class CustomizeTargetStreamsDemo implements Runnable {
public void run() { ... }
public static void main(String... args) {
CommandLine cmd = new CommandLine(new CustomizeTargetStreamsDemo());
PrintStream myOut = getOutputPrintStream(); // custom stream to send command output to
PrintStream myErr = getErrorPrintStream(); // custom stream for error messages
cmd.parseWithHandlers(
new RunLast().useOut(myOut).useAnsi(Help.Ansi.ON),
new DefaultExceptionHandler().useErr(myErr).useAnsi(Help.Ansi.OFF),
args);
}
}
Exit Code Support
From picocli v3.0, the built-in parse result handlers (RunFirst
, RunLast
and RunAll
) and exception handler
(DefaultExceptionHandler
) can specify an exit code.
If an exit code was specified, the handler terminates the JVM with the specified status code when finished.
@Command class ExitCodeDemo implements Runnable {
public void run() { throw new ParameterException(new CommandLine(this), "exit code demo"); }
public static void main(String... args) {
CommandLine cmd = new CommandLine(new ExitCodeDemo());
cmd.parseWithHandlers(
new RunLast().andExit(123),
new DefaultExceptionHandler().andExit(456),
args);
}
}
Running this command prints the following to stderr and exits the JVM with status code 456
.
exit code demo
Usage: <main class>
Custom handlers can extend AbstractHandler
to inherit this behaviour.
Fine-grained ShowDefault
This release adds a showDefaultValue
attribute to the @Option
and @Parameters
annotation. This allows you to specify for each individual option and positional parameter whether its default value should be shown in the usage help.
This attribute accepts three values:
ALWAYS
- always display the default value of this option or positional parameter, evennull
values, regardless what value ofshowDefaultValues
was specified on the commandNEVER
- don't show the default value for this option or positional parameter, regardless what value ofshowDefaultValues
was specified on the commandON_DEMAND
- (this is the default) only show the default value for this option or positional parameter ifshowDefaultValues
was specified on the command
The NEVER
value is useful for security sensitive command line arguments like passwords. The ALWAYS
value is useful when you only want to show the default value for a few arguments but not for all (in combination with @Command(showDefaultValues = false)
).
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
- [#245] New Feature: from 3.0, picocli offers an API for programmatic configuration.
- [#257] New Feature: new
ParseResult
class allows programmatic inspection of the result of parsing a sequence of command line arguments. - [#144] New Feature: added support for mixins to allow reusing common options, positional parameters, subcommands and command attributes from any object.
- [#253] New Feature: added
@Unmatched
annotation for unmatched arguments. - [#175] New Feature:
mixinStandardHelpOptions
attribute to install the standard--help
and--version
options, obviating the need for fields annotated with@Option(usageHelp = true)
and@Option(versionHelp = true)
. - [#175] New Feature: picocli now provides a
HelpCommand
that can be installed as a subcommand on any application command to provide usage help for the parent command or sibling subcommands. - [#175] New Feature: new
IHelpCommandInitializable
interface facilitates construction of custom help commands. - [#250] Enhancement: the
run
andcall
convenience methods now follow convention: print to stdout when the user requested help, print to stderr when the input was invalid or an unexpected error occurred. AddedAbstractHandler
to facilitate following this convention for custom parse result handlers and exception handlers. - [#251] New Feature: exit code support. The built-in parse result handlers (
RunFirst
,RunLast
andRunAll
) and exception handler (DefaultExceptionHandler
) can now optionally specify an exit code. If specified, the handler terminates the JVM with the specified status code when finished. Custom handlers can extendAbstractHandler
to inherit this behaviour. - [#262] New Feature: new
showDefaultValue
attribute on@Option
and@Parameters
gives fine-grained control over which default values to show or hide. Thanks to ymenager for the request. - [#268] New Feature: new
helpCommand
attribute on@Command
: if the command line arguments contain a subcommand annotated withhelpCommand
, the parser will not validate the required options or positional parameters of the parent command. Thanks to ymenager for the request. - [#277] New Feature: new
hidden
attribute on@Command
to omit the specified subcommand from the usage help message command list of the parent command. Thanks to pditommaso. - [#159] Enhancement: make help usage message width configurable. Thanks to pditommaso.
Deprecations
The picocli.CommandLine.Help::Help(Object, CommandLine.Help.ColorScheme)
constructor has been deprecated. Use the picocli.CommandLine.Help::Help(CommandLine.CommandSpec, CommandLine.Help.ColorScheme)
constructor instead.
The picocli.CommandLine.IParseResultHandler
interface has been deprecated. Use the picocli.CommandLine.IParseResultHandler2
interface instead.
The picocli.CommandLine.IExceptionHandler
interface has been deprecated. Use the picocli.CommandLine.IExceptionHandler2
interface instead.
Potential breaking changes
Help API Changes
The following public fields were removed from the picocli.CommandLine.Help
class. Instead, set these attributes on a CommandLine.CommandSpec
object passed to any of the Help
constructors.
- abbreviateSynopsis
- commandListHeading
- commandName
- customSynopsis
- description
- descriptionHeading
- footer
- footerHeading
- header
- headerHeading
- optionFields
- optionListHeading
- parameterLabelRenderer - replaced with the
Help.parameterLabelRenderer()
method - parameterListHeading
- requiredOptionMarker
- separator
- showDefaultValues
- sortOptions
- synopsisHeading
Method signature changes on inner classes and interfaces of the Help
class:
- Interface method
CommandLine.Help.IOptionRenderer::render
signature changed:CommandLine.Option
andField
parameters are replaced with a singleCommandLine.OptionSpec
parameter. - Interface method
CommandLine.Help.IParameterRenderer::render
signature changed:CommandLine.Parameters
andField
parameters are replaced with a singleCommandLine.PositionalParamSpec
parameter. - Interface method
CommandLine.Help.IParamLabelRenderer::renderParameterLabel
signature changed:Field
parameter replaced withCommandLine.ArgSpec
parameter. - Class
CommandLine.Help.Layout
all methods changed:Field
parameters replaced byCommandLine.ArgSpec
,CommandLine.OptionSpec
andCommandLine.PositionalParamSpec
parameters.