-
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
Repeating options with sub-options/arguments #635
Comments
Hi @hanslovsky , the plan is that picocli 4.0 will add support for composite repeating groups. The goal is that argument groups will support:
For example, it should be possible to have a command with a synopsis like this:
or, if the group needs to be specified at least once:
(Where I believe this will meet your requirements, but please give it a try when early versions become available. This is currently work in progress, and an early (but insuffient - lacks support for repeating composite arguments) version is currently in master. The #199 ticket has some comments that describe the current state of things and follow-up plans. This month I have other commitments but I will resume working on this from March. |
That looks very much like what I need! I'll close this issue as soon as I have tried and confirmed that it works for me. Thanks for keeping up the great work, have been waiting for a good Java command line parser for a long time and picocli exceeds expecations. I keep spreading the word and now my whole lab uses it. |
Picocli 4.0.0-alpha-1 has been released which includes support for repeating composite groups. Please try this and provide feedback. We can still make changes. What do you think of the annotations API? What about the programmatic API? Does it work as expected? Are the input validation error messages correct and clear? Is the documentation clear and complete? Anything you want to change or improve? Any other feedback? |
Great work, thanks for releasing 4.0.0-alpha-1!
but it is unclear to me how I could create a CLI with synopsis
I could add an Minimum working example: I tried to annotate import picocli.CommandLine;
import java.util.List;
public class OptionGroupsMWE {
@CommandLine.Command(name = "test-composite")
static class Args implements Runnable {
// @CommandLine.Option(names = "--add-group")
@CommandLine.ArgGroup(multiplicity = "0..*", exclusive = false)
List<Group> groups = null;
@CommandLine.Option(names = "--help", usageHelp = true)
boolean helpRequested;
@Override
public String toString() {
return String.format("%s[groups=%s,helpRequested=%s]", getClass().getSimpleName(), groups, helpRequested);
}
@Override
public void run() {}
}
static class Group {
@CommandLine.Option(names = "--option1", required = true)
String option1 = null;
@CommandLine.Option(names = "--option2", required = true)
String option2 = null;
@Override
public String toString() {
return String.format("%s[option1=%s,option2=%s]", getClass().getSimpleName(), option1, option2);
}
}
public static void main(String[] argv) {
final Args args = new Args();
CommandLine.run(args, argv);
System.out.println(args);
}
} |
Any option in the group will "trigger" the group. After a group is started, the parser verifies that all required elements are present. The second time that a required element is specified, it triggers another multiple of that group. To get the following synopsis:
you would create a nested group: @Command(name = "test-composite")
class TestComposite {
@ArgGroup(exclusive = false, multiplicity = "0..*")
List<OuterGroup> outerList;
static class OuterGroup {
@Option(names = "--add-group", required = true) boolean addGroup;
@ArgGroup(exclusive = false, multiplicity = "1")
Inner inner;
static class Inner {
@Option(names = "--option1", required = true) String option1;
@Option(names = "--option2", required = true) String option2;
}
}
} By creating an "inner" group, you make them a single element, so users can specify
By contrast, if all options are in a single group, for example, if OuterGroup was defined as a single flat group, like this: static class OuterGroup {
@Option(names = "--add-group", required = true) boolean addGroup;
@Option(names = "--option1", required = true) String option1;
@Option(names = "--option2", required = true) String option2;
} Then it would be valid to specify |
I reopened #454, because it may be more natural to model your use case as a repeating subcommand. |
Nested groups is a clever solution! For some reason, I can omit required options from the inner group without error, e.g. with the
For completeness, the entire example: import picocli.CommandLine;
import java.util.List;
@CommandLine.Command(name = "test-composite")
public class TestComposite {
@CommandLine.ArgGroup(exclusive = false, multiplicity = "0..*")
List<OuterGroup> outerList;
static class OuterGroup {
@CommandLine.Option(names = "--add-group", required = true) boolean addGroup;
@CommandLine.ArgGroup(exclusive = false, multiplicity = "1")
Inner inner;
static class Inner {
@CommandLine.Option(names = "--option1", required = true) String option1;
@CommandLine.Option(names = "--option2", required = true) String option2;
}
}
public static void main(String[] argv) {
final TestComposite args = new TestComposite();
new CommandLine(args).parse(argv);
}
} |
I’ll try this when I get to my PC. It’s possible that the validation logic needs more work. |
By the way, you can get insight into what the parser is doing by enabling tracing with system property |
Debug output for args
and or
|
Thanks for raising this! |
I raised #655 for the new issue I found. |
Will do. Unfortunately, I am rather busy writing up my thesis right now, so I will most likely not have a lot of time for extensive testing. |
No problem. Good luck with the thesis! |
I would like to add an option multiple times and add sub-options/parameters to it. In my scenario, I have a viewer application and, among other options and one positional argument, I would like to add datasets, somewhat like this:
For this call, I would add two datasets to my container:
d1
in containerc1
(type is auto-detected from meta data)d2
in containerfbc
as label datasetAs far as I can tell, this is not (yet) supported in picocli (please correct me if I am wrong), and my - kind of hackish way - to achieve that, is to add an
Option
that collects greedily all
String
s that follow that option into a list. Users need to append a split-char after the last option of each--add-dataset
(I chose_
here). I then split the list at_
, and parse each of the sublists with a separate parser. This works well for me but it has a few downsides, as far as I can tell:--add-dataset
._
)--add-dataset
) not included automaticallyI added my (kotlin) code and an invocation example at the very end of this comment for reference.
I think that this would be a useful addition. There are several issues that found that are related but not the same in my understanding:
Out of these, #454 seems to be the most closely related issues. For my real-world use case (viewer application with one positional argument, and more options), I could turn the one positional argument into an option and #454 could be a working solution for me. For anything that requires positional arguments, I would be concerned that the positional arguments might clash with the subcommands.
The text was updated successfully, but these errors were encountered: