picocli icon indicating copy to clipboard operation
picocli copied to clipboard

inheritable exclusive options

Open garretwilson opened this issue 1 year ago • 3 comments

I'm not getting the exclusivity groups for inherited options. I've got a very simple use case: I want a user to indicate --quiet or --verbose, both optional, but mutually exclusive. And I want this to be set up in the base application class so we don't have to reproduce the code in all our CLI applications.

I seem to remember other CLI libraries allowing this in a very easy way like excludes = "verbose" or something as part of the annotation. It looks like picocli requires the use of argument groups. This seems a little over-complicated for my use case, although I realize it probably provides more flexibility. In any case I tried it:

private static class Verbosity {
  @Option(names = {"--quiet", "-q"}, description = "Reduces or eliminates output of unnecessary information.")
  private boolean quiet;
  @Option(names = {"--verbose", "-v"}, description = "Provides additional output information.")
  private boolean verbose;
}

private Verbosity verbosity;

/**
 * Sets quiet/verbose options.
 * @param verbosity The verbosity options;
 */
@ArgGroup(scope = ScopeType.INHERIT)
protected void setVerbosity(@Nonnull final Verbosity verbosity) {
  this.verbosity = requireNonNull(verbosity);
}

/** @return Whether quiet output has been requested. */
protected boolean isQuiet() {
  return verbosity != null ? verbosity.quiet : false;
}

/** @return Whether verbose output has been requested. */
protected boolean isVerbose() {
  return verbosity != null ? verbosity.verbose : false;
}

First off the compiler doesn't like scope = ScopeType.INHERIT.

And already it seems like way too much overhead. It would actually be much less code if I put a checkState(verbose!=null) and checkState(quiet!=null) in the setters for the respective options.

Am I going about this in the wrong way? Is there an easier approach?

garretwilson avatar Jul 12 '22 16:07 garretwilson

Am I going about this in the wrong way? Is there an easier approach?

No, I don't think you are doing it wrong, and unfortunately there is no easier way.

As is documented as one of the limitations, inherited options currently cannot be used in Argument Groups.
I don't see that changing in the near future.

remkop avatar Jul 13 '22 04:07 remkop

As is documented as one of the limitations, inherited options currently cannot be used in Argument Groups.

Thanks for the quick response and as always for the interest in my feedback.

This is a quick response before getting some sleep, so it may be a little unpolished, but the basic sentiment is, "but I don't care so much about the limitations of argument groups, because I didn't even want to use argument groups to begin with". i.e. I just want mutual exclusive options, and there are other ways to get them. For example an excludes="foo,bar" annotation should be super-easy to implement.

I'll review my response later and see if it was remotely understandable. Good night.

garretwilson avatar Jul 13 '22 04:07 garretwilson

I don't look forward to implementing, documenting, testing and maintaining an alternative way to define argument groups. Even if picocli added support for an excludes="foo,bar" annotation as a sort of syntactic sugar way to succinctly define argument groups, that still does not take care of the request to support inherited argument groups.

Both inherited options and argument groups are already complex enough as they are. I don't look forward to mixing these two.

remkop avatar Jul 13 '22 11:07 remkop