-
Notifications
You must be signed in to change notification settings - Fork 418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1409 documentation tests #1463
1409 documentation tests #1463
Changes from all commits
9a7ddf7
fa18b18
16c6ef9
ebf37f2
3c25dcb
c7a2bb3
021dc8d
79b1de9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3033,7 +3033,7 @@ The <<Default Values,default values>> of options in an argument group are applie | |
|
||
Picocli will not initialize the `@ArgGroup`-annotated field (and so no default values are applied) if none of the group options is specified on the command line. | ||
|
||
==== Default Values in Group Usage Help | ||
==== Showing Default Values in Group Usage Help | ||
|
||
When options are used in argument groups, they can only define default values via the `@Option(defaultValue = "...")` annotation (not in the field declaration). | ||
|
||
|
@@ -3138,6 +3138,106 @@ usage help shows the wrong default value | |
---- | ||
==== | ||
|
||
==== Using Default Values in Argument Groups | ||
For picocli, there are two recommendations for successfully employing default values. First, using default values requires setting the default value within the annotation and declaratively within your code. The second is deciding how to instantiate your objects. | ||
|
||
[source,role="primary"] | ||
---- | ||
@Option(names= {"-x"}, defaultValue = "X") String X = "X"; | ||
---- | ||
Matching the annotation and declaration ensures that picocli sets the default values regardless of the user supplies the arguments. | ||
|
||
Next, identify your preferred default behavior. For `+@ArgGroup+`'s there are two distinct ways of instantiating an object. | ||
|
||
The first is to instantiate the object declaratively. This behavior is best when you desire no ambiguity in whether or not an `+@ArgGroup+` is instantiated. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I imagine some readers may be confused as to what ambiguity you are referring to. How about something like this?
|
||
|
||
.Java | ||
[source,java,role="primary"] | ||
---- | ||
@ArgGroup MyGroup myGroup = new MyGroup(); | ||
---- | ||
|
||
.Kotlin | ||
[source,kotlin,role="secondary"] | ||
---- | ||
@ArgGroup var myGroup = MyGroup(); | ||
---- | ||
|
||
The second way is to initialize the objects using business logic, such as `+run+` or `+call+` methods. This way is better if the desired behavior is to allow the application to determine whether the user specified a value for the `+@ArgGroup+`. It is recommended that the program called using `+execute+` instead of `+parseArgs+` | ||
|
||
.Java | ||
[source,java,role="primary"] | ||
---- | ||
@Command(name = "test", description = "demonstrates Default Value declaration") | ||
class MyApp { | ||
@ArgGroup Outer outer; | ||
|
||
static class Outer { | ||
@Options(names = "-x", defaultValue = "XX") String x = "XX"; | ||
@ArgGroup(exclusive = "true") Inner inner; | ||
} | ||
|
||
static class Inner { | ||
@Options(names = "-a", defaultValue = "AA") String a = "AA"; | ||
@Options(names = "-b", defaultValue = "BB") String b = "BB"; | ||
} | ||
|
||
public void run() { | ||
if (outer == null) { // no options specified on command line; apply default values | ||
outer = new Outer; | ||
} | ||
if (outer.inner == null) { // handle nested sub-groups; apply default for inner group | ||
outer.inner = new Inner; | ||
} | ||
|
||
// remaining business logic... | ||
} | ||
remkop marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
public static void main() { | ||
final MyApp obj = new MyApp(); | ||
new CommandLine(obj).execute("-x", "ANOTHER_VALUE"); | ||
} | ||
---- | ||
|
||
.Kotlin | ||
[source,kotlin,role="secondary"] | ||
---- | ||
|
||
import sun.tools.jar.CommandLine@Command(name = "test", description =["demonstrates Default Value declaration"]) | ||
class MyApp { | ||
@ArgGroup lateinit var outer: Outer | ||
|
||
class Outer { | ||
@Options(names = "-x", defaultValue = "XX") var x = "XX"; | ||
@ArgGroup lateinit var inner: Inner | ||
} | ||
|
||
class Inner { | ||
@Options(names = "-a", defaultValue = "AA") var a : "AA" | ||
@Options(names = "-b", defaultValue = "BB") var b : "BB" | ||
} | ||
|
||
override fun run() { | ||
if (outer == null) { // no options specified on command line; apply default values | ||
outer = Outer(); | ||
} | ||
if (outer.inner == null) { // handle nested sub-groups; apply default for inner group | ||
outer.inner = Inner(); | ||
} | ||
|
||
// remaining business logic... | ||
} | ||
} | ||
|
||
remkop marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fun main(args: Array<String>) { | ||
var obj = MyApp(); | ||
var commandLine = CommandLine(obj); | ||
commandLine.execute(args); | ||
} | ||
---- | ||
|
||
|
||
=== Positional Parameters | ||
|
||
When a `@Parameters` positional parameter is part of a group, its `index` is the index _within the group_, not within the command. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will be good to acknowledge that there is some duplication here, just to be clear and explicit that this is intentional.
Also (nitpicking again), it is actually not picocli who is setting the default value here: remember that the group is not instantiated when there is no match. By setting an initial value, the application is actually doing the work of assigning a default value themselves. I think it is good to be explicit that this is necessary, and mention something like the below, somewhere in this section: