Picocli is a modern framework for building powerful, user-friendly, GraalVM-enabled command line apps with ease. It supports colors, autocompletion, subcommands, and more. In 1 source file so apps can include as source & avoid adding a dependency. Written in Java, usable from Groovy, Kotlin, Scala, etc.
The picocli community is pleased to announce picocli 4.7.5.
This release includes bugfixes and enhancements.
Many thanks to the picocli community for raising these issues and providing the pull requests to address them!
This is the eighty-forth public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
echo=false
for interactive
options and positional parameters. Thanks to szzsolt for raising this.picocli.shell.jline3.PicoCommand
. Thanks to clebertsuconic for the pull request.exclusive=false
and multiplicity=1
should require at least one option; fix regression and refine solution introduced in [#1848][#2030]. Thanks to Utkarsh Mittal for raising this.graalvm-native-image-plugin
. Thanks to Bhavik Patel for the pull request.No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.7.4.
This release includes bugfixes and enhancements.
Many thanks to the picocli community for raising these issues and providing the pull requests to address them!
This is the eighty-third public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
See fixed items below.
I cheated on the semantic versioning in this release: a public setter method was added in a class in the picocli.shell.jline3
module. In spite of that, the version number went from 4.7.3 to 4.7.4 (not 4.8.0). My apologies.
picocli.shell.jline3.PicocliCommands
. Thanks to Irina Leontyuk for raising this.java.nio.charset.UnsupportedCharsetException: cp0
on windows, and fall back to the default charset if the charset provided by System property sun.stdout.encoding
is invalid. Thanks to
Bartosz Spyrko-Smietanko for the pull request.ArgGroup
becoming optional when combined with DefaultValueProvider
. Thanks to Ruud Senden and Mike Snowden for the pull request.No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.7.3.
This release includes bugfixes and enhancements.
This is the eighty-second public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
Fixed a regression introduced in picocli 4.7.2.
Multi-value options whose fallbackValue
is set to CommandLine.Option.NULL_VALUE
, may see a NullPointerException
if the option is specified on the command line without a parameter but with a =
attached, like --option=
.
Also, this release fixes broken links in the Javadoc.
NOTE: A minor issue with this release is that the version string in the info.picocli.CommandLine.VERSION
field is incorrectly set to 4.7.3-SNAPSHOT
(should have been 4.7.3
).
No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.7.2.
This release includes bugfixes and enhancements.
This is the eighty-first public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
fallbackValue=Option.NULL_VALUE
did not work for Collection
or array options.isJansiConsoleInstalled
performance issue.paramLabel
string auto-generated from Kotlin internal
methods which have mangled names with embedded "$".fallbackValue=Option.NULL_VALUE
did not work for Collection
or array options. Thanks to Jiri Daněk for raising this.isJansiConsoleInstalled
performance issue. Thanks to ChrisTrenkamp for the pull request.paramLabel
string auto-generated from Kotlin internal
methods which have mangled names with embedded "$". Thanks to Ken Yee for raising this.No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.7.1.
This release includes bugfixes and enhancements.
This is the eightieth public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
picocli-groovy
module should not declare org.codehaus.groovy:groovy-all
as dependency. Thanks to Mattias Andersson and Michael Kutz for raising this, and to Paul King for the analysis.CommandLine.Interpreter.applyValueToSingleValuedField
. Thanks to Jiehong for the pull request.StringIndexOutOfBoundsException
in usage help when command has many (and long) aliases. Thanks to Martin for raising this.fallbackValue
to vararg multi-value options, not just single-value options. Thanks to Andreas Sewe for raising this.ManPageGeneratorTest
. Thanks to Mike Snowden for the pull request.System.exit
usage. Thanks to Tadaya Tsuyukubo for the pull request.picocli-codegen/README.adoc
. Thanks to Seyyed Emad Razavi for the pull request.picocli-annotation-processing-tests
failures on Java 16+: rewrite tests to avoid Google compiler-test
API that internally uses com.sun.tools.javac.util.Context
.No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.7.0.
This release includes bugfixes and enhancements.
A potentially breaking change is that the parser now treats char[]
as a single-value type.
From this release, applications can programmatically set the trace level, and use tracing in custom components.
Applications can improve startup time by setting system property picocli.disable.closures
to true
to disable support for closures in annotations.
Many more fixes and enhancements, see the sections below for more details.
This is the seventy-ninth public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
From picocli 4.7.0, applications can programmatically set the trace level, and use tracing in custom components.
In addition to setting system property picocli.trace
, applications can now change the trace level via the Tracer::setLevel
method. For example:
CommandLine.tracer().setLevel(CommandLine.TraceLevel.INFO);
The new public method CommandLine.tracer()
returns the singleton Tracer
object that is used internally by picocli, and can also be used by custom component implementations to do tracing. For example:
class MyIntConverter implements ITypeConverter<Integer> {
public Integer convert(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException ex) {
CommandLine.tracer().info(
"Could not convert %s to Integer, returning default value -1", value);
return -1;
}
}
}
By default, options that take a parameter do not consume values that match a subcommand name or an option name.
This release introduces two parser configuration options to change this behaviour:
CommandLine::setAllowOptionsAsOptionParameters
allows options to consume option namesCommandLine::setAllowSubcommandsAsOptionParameters
allows options to consume subcommand namesWhen set to true
, all options in the command (options that take a parameter) can consume values that match option names or subcommand names.
This means that any option will consume the maximum number of arguments possible for its arity.
USE WITH CAUTION!
If an option is defined as arity = "*"
, this option will consume all remaining command line arguments following this option (until the End-of-options delimiter) as parameters of this option.
By default, the synopsis displays options in alphabetical order.
Picocli 4.7.0 introduces a sortSynopsis = false
attribute to let the synopsis display options in the order they are declared in your class, or sorted by their order
attribute.
@Command(sortSynopsis = false)
char[]
optionsPrior to 4.7, the picocli parser treated options and positional parameters with type char[]
as array (multi-value) options, except for interactive options. However, it is more intuitive to treat all char[]
options as single-value options, similar to String
options.
For end users, this means that existing applications that use non-interactive char[]
options will no longer allow multiple characters to be specified separately on the command line. That is, input like -c A -c B -c C
will be rejected and the user needs to specify -c ABC
instead.
Applications that want to preserve the previous behaviour will need to change their code to use java.lang.Character[]
instead of char[]
.
picocli-codegen
artifact is now an explicitly declared named JPMS module with a module-info.class
.picocli-groovy
artifact is now an explicitly declared named JPMS module with a module-info.class
.picocli-shell-jline2
is now an explicitly declared named JPMS module with a module-info.class
.picocli-shell-jline3
is now an explicitly declared named JPMS module with a module-info.class
.picocli-spring-boot-starter
is now an explicitly declared named JPMS module with a module-info.class
. NOTE: its module name changed to info.picocli.spring.boot
from info.picocli.spring
.picocli-spring-boot-starter
JPMS module name to info.picocli.spring.boot
from info.picocli.spring
.requires static java.sql
to picocli module-info
.TraceLevel
. Thanks to ekinano for raising this.requiredOptionMarker
should not be displayed on ArgGroup
options. Thanks to Ahmed El Khalifa for the pull request.PicocliSpringFactory
to allow custom fallback IFactory
. Thanks to Andrew Holland for raising this.OptionSpec.getValue()
and add IScoped
internal API. Thanks to Ruud Senden for the discussion and the pull request.order
.setUsageHelpLongOptionsMaxWidth
method no longer throws an exception when an invalid value is specified; instead, the value is ignored and an INFO-level trace message is logged. Thanks to Fabio for the pull request.char[]
as single-value types (Potentially breaking change). Thanks to Lukáš Petrovický for the pull request with the test to verify the solution.picocli.disable.closures
to true
to disable support for closures in annotations. Thanks to patric-r for raising this.order
if specified. Thanks to Simon for raising this.order
(if specified). Thanks to Enderaoe for the pull request with unit tests.Help
command description. Thanks to Michael L Heuer for the pull request. Thanks to Garret Wilson for raising this.Option
and Parameters
annotations. Thanks to xehpuk for raising this, and thanks to Adam McElwee for the pull request.multiplicity="0"
are now disallowed at construction time and no longer throw a StackOverflowError
while parsing. Thanks to ARNOLD Somogyi for raising this.getCJKAdjustedLength()
no longer miscalculates for supplementary code points. Thanks to gwalbran for the pull request.posixClusteredShortOptionsAllowed
is set to false.@Command
-annotated method parameters are assigned incorrect indices when contained in a @Command
class that is added as a subcommand to another @Command
class which has scope = CommandLine.ScopeType.INHERIT
. Thanks to Onedy for raising this.CommandSpec
. Thanks to Philippe Charles for raising this.null
as defaultValue
and fallbackValue
.main
from master
. Thanks to Andreas Deininger for the pull request.picocli-codegen
README
. Thanks to Andreas Deininger for the pull request.picocli-examples
in the user manual. Thanks to Markus Elfring for raising this.@Command
-annotated method with int
return value in user manual. Thanks to SinaMobasheri for raising this.picocli-groovy
module now declares groovy-all
as dependency.slf4j
from picocli-spring-boot-starter
.No features were deprecated in this release.
picocli-spring-boot-starter
has been changed to info.picocli.spring.boot
from info.picocli.spring
.picocli-groovy
module now declares groovy-all
as dependency.char[]
as a single-value type.The picocli community is pleased to announce picocli 4.6.3.
This release includes bugfixes and enhancements, as well as documentation and security improvements.
Several improvements to the annotation processor and the generated autocompletion scripts.
Much gratitude to the picocli community for the many pull requests and other contributions!
This is the seventy-eighth public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
main
The default branch has been renamed! master
is now named main
.
If you have a local clone, you can update it by running the following commands:
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
compopt: command not found
on older versions of Bashcompinit
onceDuplicateOptionAnnotationsException
when multiple commands had a subcommand in common and an inherited (scope = ScopeType.INHERIT
) option. Thanks to nemetsSY for raising this.-Averbose=true
no longer incorrectly triggers warning: The following options were not recognized by any processor: '[verbose]'
. Thanks to Lorenz Leutgeb for raising this.UnsupportedCharsetException: cp65001
on Microsoft Windows console when code page is set to UTF-8. Thanks to epuni for raising this.parseArgs
invocations when CommandLine
instance is reused. Thanks to kaushalkumar for raising this.compopt: command not found
on older versions Bash. Thanks to Andres Almiray for raising this.AbstractCommandSpecProcessor#extractTypedMember
. Thanks to Ross Goldberg for raising this.help
command only works on the first argument. Thanks to Patrice Duroux for the pull request.CommandSpec#validateSubcommandName
implementation. Thanks to Ross Goldberg for the pull request.org.junit.Assert.assertThat
deprecation warning; Thanks to Ross Goldberg for the pull request.AbstractCommandSpecProcessor#isSubcommand
; Thanks to Ross Goldberg for the pull request.DefaultFactory#create(Class<T>)
. Thanks to Ross Goldberg for the pull request.TypedMember
constructor. Thanks to Ross Goldberg for the pull request.compinit
once. Thanks to Ben Herweyer for the pull request.System.exit
tests on Java 18.jline-console
in picocli-shell-jline3
. Thanks to kaushalkumar for raising this.No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.6.2.
This release includes bugfixes and enhancements. Many improvements in the documentation.
Thanks to the many people in the picocli community for raising issues and contributing pull requests to fix issues!
From this release, picocli uses system properties sun.stdout.encoding
and sun.stderr.encoding
when creating the PrintWriters
returned by CommandLine::getOut
and CommandLine::getErr
. When these system properties do not exist, picocli falls back to the default charset (determined by file.encoding
). This addresses an issue on Windows, where the default charset is not the same as the encoding for its console (often the older cp437
codepage on English-language versions of Windows).
Note that these system properties seem to have been introduced in Java 8 (although I cannot find it in the JDK 8 release notes) and may not exist on earlier JVMs or on JVMs other than the Oracle and OpenJDK implementations.
This is the seventy-seventh public release. Picocli follows semantic versioning. Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
@Option
help
attribute; it is useful for custom help options. Thanks to kaushalkumar for raising this.WARNING: tag not found in include file
messages when generating man pages. Thanks to Philip Crotwell for the pull request.completionCandidates
when displaying usage help if ${COMPLETION-CANDIDATES}
is not specified in description. Thanks to Wenhao ZHANG, sustc11810424 and Yining Tang for the pull request.IllegalArgumentException: argument type mismatch
error in method subcommands with inherited mixed-in standard help options. Thanks to Andreas Deininger for raising this.CommandLine
with ArgGroup. Thanks to Yashodhan Ghadge for raising this.DuplicateOptionAnnotationsException
thrown on mixinStandardHelpOptions
for subcommands when parent has scope = INHERIT
by picocli-codegen
annotation processor. Thanks to Philippe Charles for raising this.DuplicateOptionAnnotationsException
when parent has inherited mixed-in help options and the built-in HelpCommand
subcommand. Thanks to Andreas Deininger for raising this.IllegalArgumentException
when parent has no standard help options and scope = INHERIT
, while subcommand does have mixed-in standard help options. Thanks to Andreas Deininger for raising this.CommandSpec.remove(arg)
should also remove the arg from the args
collection in the CommandSpec. Thanks to kaushalkumar for the pull request.sun.stdout.encoding
and sun.stderr.encoding
when creating the PrintWriters
returned by CommandLine::getOut
and CommandLine::getErr
. Thanks to Philippe Charles for the investigation and the pull request..gitattributes
should include HTML files to convert CRLF to LF. Thanks to wenhoujx for pointing this out.execute
method in RunAll
, RunFirst
and RunLast
should not be deprecated. Thanks to Gamal DeWeever for raising this.IParameterPreprocessor
from IParameterConsumer
javadoc. Thanks to Andreas Deininger for the pull request.IParameterConsumer
as n-ary type converter. Thanks to Martin for raising this.converter
, improve text for default values. Thanks to Abhijit Sarkar for raising this.setLongOptionsMaxWidth
to setUsageHelpLongOptionsMaxWidth
in user manual section 'Long Option Column Width'. Thanks to kunlk for raising this.picocli-shell-jline2/README.md
. Thanks to Ahmed Ashour for the pull request.MANIFEST.MF
. Thanks to Fiouz for the pull request.pom.xml
. Thanks to Fiouz for the pull request.No features were deprecated in this release.
The @Option
help
attribute is no longer deprecated from this release; it is useful for custom help options.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.6.1.
This release fixes a problem (introduced in the 4.6.0 release) with dependency scope in the following sub-modules:
The problem was that these modules contained dependencies that were declared to have implementation
scope instead of api
scope.
However, these were transitive dependencies, and necessary to compile any project that uses the above picocli modules.
In this release, transitive dependencies are declared with api
scope in the above modules.
Special thanks to Sualeh Fatehi, Dejan Stojadinović and Semyon Levin for the quick community feedback, pull request and reviews!
This is the seventy-sixth public release. Picocli follows semantic versioning.
picocli-shell-jline3
. Thanks to Sualeh Fatehi for raising this.picocli-shell-jline3
. Thanks to Dejan Stojadinović for the pull request, and Semyon Levin for the review.picocli-spring-boot-starter
. Thanks to Semyon Levin for raising this.No features were deprecated in this release.
This release has no breaking changes.
The picocli community is pleased to announce picocli 4.6.0.
This release contains new features, bug fixes and other enhancements.
This release contains many, many community contributions, for which I am extremely grateful. Let's give the contributors some credit!
IModelTransformer
API for user-defined model transformations after initialization and before parsing.picocli-shell-jline3
module that adds a built-in clear
command and improves the help
command.echo
and prompt
for interactive options and positional parameters.Annotation::getClass
and assignment in if
condition.@ParentObject
should be @ParentCommand
.@Command
attributes with scope=INHERIT
.CommandSpec::removeSubcommand
method.Optional<T>
type for options and positional parameters.-Dkey
as well as -Dkey=value
).@Spec
-annotated members in ArgGroup
classes.MissingParameterException
should not be thrown when subcommand has required options and help option is specified on parent command.ReflectionConfigGenerator
should not generate method section in subclass config for private superclass methods in reflect-config.json
.CommandLine::getFactory
accessor method.Improved Groovy support: this release introduces a new @PicocliScript2
annotation that adds support for exit codes and @Command
-annotated methods to define subcommands. Also, from this release, Groovy programs can use closures in the picocli annotations instead of specifying a class.
From this release, Map options accept key-only parameters, so end users can specify -Dkey
as well as -Dkey=value
.
There is a new mapFallbackValue
attribute that enables this, which can be used to control the value that is put into the map when only a key was specified on the command line.
Also, this release adds support for java.util.Optional<T>
: single-value types can be wrapped in an Optional
container object when running on Java 8 or higher.
If the option or positional parameter was not specified on the command line, picocli assigns the value Optional.empty()
instead of null
.
This release also adds support for commands with scope = ScopeType.INHERIT
. Commands with this scope have their attributes copied to all subcommands (and sub-subcommands).
New parser plugin: IParameterPreprocessor
and new configuration plugin: IModelTransformer
.
From this release, @Spec
-annotated elements can be used in ArgGroup
classes, which can be convenient for validation.
Interactive options and positional parameters can now set echo = true
(for non-security sensitive data) so that user input is echoed to the console, and control the prompt
text that is shown before asking the user for input.
Help API: this release adds public methods Help.Layout::colorScheme
, Help.Layout::textTable
, Help.Layout::optionRenderer
, Help.Layout::parameterRenderer
, and Help::calcLongOptionColumnWidth
, making it easier to customize the table format used to lay out options and positional parameters in the usage help message.
CommandSpec API: added method CommandSpec::removeSubcommand
.
This is the seventy-fifth public release. Picocli follows semantic versioning.
@PicocliScript2
annotationThe older @picocli.groovy.PicocliScript
annotation is deprecated from picocli 4.6.
New scripts should use the @picocli.groovy.PicocliScript2
annotation (and associated picocli.groovy.PicocliBaseScript2
base class) instead.
The table below lists the differences between the PicocliBaseScript2
and PicocliBaseScript
script base classes.
PicocliBaseScript2 |
PicocliBaseScript |
---|---|
Subcommands can be defined as @Command -annotated methods in the script. |
No support for @Command -annotated methods. |
Support for help subcommands (both the built-in one and custom ones). |
No support for help subcommands. |
Exit code support: scripts can override afterExecution(CommandLine, int, Exception) to call System.exit . |
No support for exit code. |
Invokes CommandLine::execute . Scripts can override beforeParseArgs(CommandLine) to install a custom IExecutionStrategy . |
Execution after parsing is defined in PicocliBaseScript::run and is not easy to customize. Any subcommand and the main script are both executed. |
Scripts can override beforeParseArgs(CommandLine) to install a custom IParameterExceptionHandler . |
Invalid input handling can be customized by overriding PicocliBaseScript::handleParameterException . |
Scripts can override beforeParseArgs(CommandLine) to install a custom IExecutionExceptionHandler . |
Runtime exception handling can be customized by overriding PicocliBaseScript::handleExecutionException . |
Implements Callable<Object> , script body is transformed to the call method. |
Script body is transformed to the runScriptBody method. |
From picocli 4.6, Groovy programs can use closures in the picocli annotations instead of specifying a class. This can be especially useful in Groovy scripts, where one cannot define a static inner class.
Example:
@Command(name = "ClosureDemo",
versionProvider = {
{ -> ["line1" , "line2"] as String[] } as IVersionProvider // <1>
},
defaultValueProvider = {
{ argSpec -> "some default" } as IDefaultValueProvider // <2>
})
class ClosureDemo {
@Option(names = '-x', completionCandidates = {["A", "B", "C"]}) // <3>
String x
@Option(names = '-y',
parameterConsumer = {
{ args, argSpec, commandSpec -> // <4>
argSpec.setValue(args.toString() + commandSpec.name())
args.clear()
} as IParameterConsumer
})
String y
@Option(names = '-z', converter = [ // requires Groovy 3.0.7
{ { str -> MessageDigest.getInstance(str) } as ITypeConverter } // <5>
])
MessageDigest z
}
When a class is specified, picocli creates an instance of the class. By contrast, when a closure is specified, picocli calls the closure to get an instance. (To be precise, both of these are delegated to the configured factory, and the default factory implementation supports closures from picocli 4.6.)
As you can see in the above example, each closure in the annotation should contain another closure that has the required type (IVersionProvider
, IDefaultValueProvider
, etc.)
versionProvider
: note the empty parameter list before the ->
arrow. This is needed to help the Groovy compiler. The closure must be cast to IVersionProvider
.defaultProvider
: return a default value for the specified ArgSpec
parameter. The closure must be cast to IDefaultValueProvider
.completionCandidates
: return a list of Strings. No parameter list or casting is required.parameterConsumer
: given a Stack
, ArgSpec
and CommandSpec
, process the remaining arguments. The closure must be cast to IParameterConsumer
.converter
takes an array of closures. Groovy 3.0.7 or greater is required: older versions of Groovy ignore closures in class array annotations. Each closure must have a parameter and be cast to ITypeConverter
.By default, picocli expects Map options and positional parameters to look like key=value
, that is, the option parameter or positional parameter is expected to have a key part and a value part, separated by a =
character. If this is not the case, picocli shows a user-facing error message: Value for ... should be in KEY=VALUE format but was ...
.
From picocli 4.6, applications can specify a mapFallbackValue
to allow end users to specify only the key part. The specified mapFallbackValue
is put into the map when end users to specify only a key. The value type can be wrapped in a java.util.Optional
. For example:
@Option(names = {"-P", "--properties"}, mapFallbackValue = Option.NULL_VALUE)
Map<String, Optional<Integer>> properties;
@Parameters(mapFallbackValue = "INFO", description = "... ${MAP-FALLBACK-VALUE} ...")
Map<Class<?>, LogLevel> logLevels;
This allows input like the following:
<cmd> --properties=key1 -Pkey2 -Pkey3=3 org.myorg.MyClass org.myorg.OtherClass=DEBUG
The above input would give the following results:
properties = [key1: Optional.empty, key2: Optional.empty, key3: Optional[3]]
logLevels = [org.myorg.MyClass: INFO, org.myorg.OtherClass: DEBUG]
Note that the option description may contain the ${MAP-FALLBACK-VALUE}
variable which will be replaced with the actual map fallback value when the usage help is shown.
A common requirement for command line applications is to support the -Dkey=value
syntax to allow end users to set system properties.
The example below uses the Map
type to define an @Option
-annotated method that delegates all key-value pairs to System::setProperty
.
Note the use of mapFallbackValue = ""
to allow key-only option parameters.
class SystemPropertiesDemo {
@Option(names = "-D", mapFallbackValue = "") // allow -Dkey
void setProperty(Map<String, String> props) {
props.forEach((k, v) -> System.setProperty(k, v));
}
}
java.util.Optional<T>
From version 4.6, picocli supports single-value types wrapped in a java.util.Optional
container when running on Java 8 or higher.
If the option or positional parameter was not specified on the command line, picocli assigns the value Optional.empty()
instead of null
.
For example:
@Option(names = "-x")
Optional<Integer> x;
@Option(names = "-D", mapFallbackValue = Option.NULL_VALUE)
Map<String, Optional<Integer>> map;
WARNING: Picocli has only limited support for java.util.Optional
types:
only single-value types, and the values in a Map
(but not the keys!) can be wrapped in an Optional
container.
java.util.Optional
cannot be combined with arrays or other Collection
classes.
Picocli 4.6 adds support for inheriting @Command
attributes with the scope = ScopeType.INHERIT
annotation.
Commands with this scope have their @Command
attributes copied to all subcommands (and sub-subcommands, to any level of depth).
When a subcommand specifies an explicit value in its @Command
annotation, this value is used instead of the inherited value.
For example:
@Command(name = "app", scope = ScopeType.INHERIT,
mixinStandardHelpOptions = true, version = "app version 1.0",
header = "App header",
description = "App description",
footerHeading = "Copyright%n", footer = "(c) Copyright by the authors",
showAtFileInUsageHelp = true)
class App implements Runnable {
@Option(names = "-x") int x;
public void run() { System.out.printf("Hello from app %d%n!", x); }
@Command(header = "Subcommand header", description = "Subcommand description")
void sub(@Option(names = "-y") int y) {
System.out.printf("Hello app sub %d%n!", y);
}
}
The app
command in the above example has scope = ScopeType.INHERIT
, so its @Command
properties are inherited by the sub
subcommand.
The sub
subcommand defines its own header
and description
, so these are not inherited from the parent command.
The help message for the subcommand looks like this:
Subcommand header
Usage: app sub [-hV] [-y=<arg0>] [@<filename>...]
Subcommand description
[@<filename>...] One or more argument files containing options.
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
-y=<arg0>
Copyright
(c) Copyright by the authors
Note that the subcommand has inherited the mixed-in standard help options (--help
and --version
), the @file
usage help, and the footer and footer heading.
It also inherited the version string, shown when the user invokes app sub --version
.
When a command has scope = INHERIT
, the following attributes are copied to its subcommands:
mixinStandardHelpOptions
helpCommand
Attributes that are not copied include:
mixinStandardHelpOptions
)mixinStandardHelpOptions
Introduced in picocli 4.6, the IParameterPreprocessor
is also a parser plugin, similar to IParameterConsumer
, but more flexible.
Options, positional parameters and commands can be assigned a IParameterPreprocessor
that implements custom logic to preprocess the parameters for this option, position or command.
When an option, positional parameter or command with a custom IParameterPreprocessor
is matched on the command line, picocli's internal parser is temporarily suspended, and this custom logic is invoked.
This custom logic may completely replace picocli's internal parsing for this option, positional parameter or command, or augment it by doing some preprocessing before picocli's internal parsing is resumed for this option, positional parameter or command.
The "preprocessing" actions can include modifying the stack of command line parameters, or modifying the model.
This may be useful when disambiguating input for commands that have both a positional parameter and an option with an optional parameter. For example, suppose we have a command with the following synopsis:
edit [--open[=<editor>]] <file>
One of the limitations of options with an optional parameter is that they are difficult to combine with positional parameters.
With a custom parser plugin, we can customize the parser, such that VALUE
in --option=VALUE
is interpreted as the option parameter, and in --option VALUE
(without the =
separator), VALUE is interpreted as the positional parameter.
The code below demonstrates:
@Command(name = "edit")
class Edit {
@Parameters(index = "0", description = "The file to edit.")
File file;
enum Editor { defaultEditor, eclipse, idea, netbeans }
@Option(names = "--open", arity = "0..1", preprocessor = Edit.MyPreprocessor.class,
description = {
"Optionally specify the editor to use; if omitted the default editor is used. ",
"Example: edit --open=idea FILE opens IntelliJ IDEA (notice the '=' separator)",
" edit --open FILE opens the specified file in the default editor"
})
Editor editor = Editor.defaultEditor;
static class MyPreprocessor implements IParameterPreprocessor {
public boolean preprocess(Stack<String> args,
CommandSpec commandSpec,
ArgSpec argSpec,
Map<String, Object> info) {
// we need to decide whether the next arg is the file to edit
// or the name of the editor to use...
if (" ".equals(info.get("separator"))) { // parameter was not attached to option
// act as if the user specified --open=defaultEditor
args.push(Editor.defaultEditor.name());
}
return false; // picocli's internal parsing is resumed for this option
}
}
}
With this preprocessor, the following user input gives the following command state:
# User input # Command State
# --------------------------
--open A B # editor: defaultEditor, file: A, unmatched: [B]
--open A # editor: defaultEditor, file: A, unmatched: []
--open=A B # editor: A, file: B, unmatched: []
--open=A # editor: A, file: null, unmatched: []
From picocli 4.6, it is possible to use the annotations API to modify the model (commands, options, subcommands, etc.) dynamically at runtime.
The @Command
annotation now has a modelTransformer
attribute where applications can specify a class that implements the IModelTransformer
interface:
This allows applications to dynamically add or remove options, positional parameters or subcommands, or modify the command in any other way, based on some runtime condition.
@Command(modelTransformer = Dynamic.SubCmdFilter.class)
class Dynamic {
private static class SubCmdFilter implements IModelTransformer {
public CommandSpec transform(CommandSpec commandSpec) {
if (Boolean.getBoolean("disable_sub")) {
commandSpec.removeSubcommand("sub");
}
return commandSpec;
}
}
@Command
private void sub() {
// subcommand business logic
}
}
@Command(scope=INHERIT)
. Thanks to Nick Cross for raising this.@PicocliScript2
annotation to support subcommand methods in Groovy scripts. Thanks to Mattias Andersson for raising this.mapFallbackValue
attribute to @Options
and @Parameters
annotations, and corresponding ArgSpec.mapFallbackValue()
.IParameterPreprocessor
parser plugin to invoke custom logic when a command, option or positional parameter is matched. Thanks to David Walluck for raising this.IModelTransformer
to support user-defined model transformations after initialization and before parsing. Thanks to Marko Mackic for the pull request.echo
and prompt
in for interactive options and positional parameters. Thanks to H.Sakata for the pull request.Help.Layout::colorScheme
, Help.Layout::textTable
, Help.Layout::optionRenderer
, Help.Layout::parameterRenderer
, and Help::calcLongOptionColumnWidth
.ArgSpec::root
: this method returns the original ArgSpec
for inherited ArgSpec
objects, and null
for other ArgSpec
objects. Thanks to Daniel Gray for the pull request.CommandSpec::removeSubcommand
method. Thanks to Marko Mackic for raising this.CommandLine::getFactory
accessor for the factory. Thanks to Sualeh Fatehi for the suggestion.Optional<T>
type for options and positional parameters. Thanks to Max Rydahl Andersen for raising this.-Dkey
as well as -Dkey=value
). Thanks to Max Rydahl Andersen and David Walluck for raising this and subsequent discussion.@Spec
-annotated members in ArgGroup
classes. Thanks to Jannick Hemelhof for raising this.picocli-shell-jline3
: add built-in clear
command and improve help
command. Thanks to Sualeh Fatehi for the pull request.Annotation::getClass
and assignment in if
condition. Thanks to nveeser-google for the pull request.MissingParameterException
thrown when subcommand has required options and help option is specified on parent command. Thanks to drkilikil for raising this.Help.calcLongOptionColumnWidth
now calls Help.createDefaultOptionRenderer
, so overriding createDefaultOptionRenderer
uses the correct column width in the options and parameters list.ReflectionConfigGenerator
should not generate method section in subclass config for private superclass methods in reflect-config.json
. Thanks to Sebastian Thomschke for raising this.Spring-Boot-Starter
version to 2.3.5.RELEASE. Thanks to Andreas Deininger for the pull request.@ParentObject
should be @ParentCommand
. Thanks to Laurent Almeras for the pull request.Issue1225UnmatchedArgBadIndex
. Thanks to David Walluck for the pull request.From this release, the @picocli.groovy.PicocliScript
annotation in the picocli-groovy
module is deprecated in favor of @picocli.groovy.PicocliScript2
, and the picocli.groovy.PicocliBaseScript
class is deprecated in favor of picocli.groovy.PicocliBaseScript2
.
Added method isOptional()
to the picocli.CommandLine.Model.ITypeInfo
interface.