picocli
picocli copied to clipboard
Add support for multi-value defaultValue and fallbackValue for parameters and options
Somehow related to #877:
Currently, it is possible to annotate a defaultValue for options and parameters. However, one can specify a string/value only, not multiple values. Fortunately, one can workaround this by using split
on the option/positional parameter definition, this solution has some limitations, however.
Code example that illustrates the issue:
public class DefaultValueMultipleOptions {
public static void main(String... args) {
CommandLine cmd = new CommandLine(new MyFileCommand());
cmd.execute(args);
}
}
@Command( name="myCommand", mixinStandardHelpOptions = true)
class MyFileCommand implements Runnable {
@Parameters(defaultValue = { "default file 1", "default file 2" }) // does not work (yet)
// @Parameters(defaultValue = "default file 1,default file 2", split = ",") // this is workaround
String[] files = { "file 1", "file 2" };
public void run() {
for (String file : files)
System.out.println("File: " + file);
System.out.println(String.format("%s files", files.length));
}
}
As said, this is a low priority enhacement as we have a workaround here. I just wanted to get the author's opinion on this prior to authoring a PR ;-)
If we do #877 then it makes sense to do this as well.
What I haven’t fully thought through is the edge cases. Basically, what if there are multiple default values specified for a single-value option or positional parameter?
What I haven’t fully thought through is the edge cases. Basically, what if there are multiple default values specified for a single-value option or positional parameter?
This reminds me of the discussion we had concerning #745. I would propose to implement the same solution that was eventually chosen for #745:
- runtime initialization exception from the CommandLine constructor
- compile-time error by the annotation processor
I considered doing this for 4.7, but having second thoughts (and I may give up on this altogether).
The problem is, that while this will be a backwards compatible change for Java, it will be a breaking change for languages that require different syntax for array type vs single value type annotation members.
Specifically for Groovy, Kotlin and Scala, this would be a breaking change: applications need to change their code in order to compile after this change.
For example:
Before the Change (Current Code)
Before the change, defaultValue = "someValue"
and fallbackValue = "someValue"
are valid syntax in Groovy, Kotlin and Scala.
// groovy / kotlin
@Option(names = ["--log-level"], defaultValue = "INFO")
// scala
@Option(names = Array("--log-level"), defaultValue = "INFO")
After the Change
After the change, [
and ]
or Array(
and )
become required around the default value:
// groovy / kotlin
@Option(names = ["--log-level"], defaultValue = ["INFO"]) // '[' and ']' become required around the default value
// scala
@Option(names = Array("--log-level"), defaultValue = Array("INFO")) // 'Array(' and ')' become required
I am not sure if this causes a runtime error. (Haven't tried this yet.)
If existing Kotlin, Groovy and Scala applications (compiled against an older version of picocli that requires single-value default values) would continue to work at runtime (with a newer version of picocli that requires array type default values), then it may be feasible to do this.
One idea is to add new API for multi-value defaults and leave the existing API as is for single-value defaults.
Something like this:
Option(defaultValues = {"1", "2"}, fallbackValues = {"3", "4"})
This introduces the possibility of some invalid combinations:
- use of both
defaultValue
anddefaultValues
- use of
defaultValues
annotation on single-value option
Both can be handled by throwing an InitializationException
at runtime, compile error from annotation processor.
Related: https://github.com/remkop/picocli/issues/1743