1

I'm having a problem trying to get the PicoCLI library in Java to interpret the next position after a certain flag to be a string, and not another flag.

Say for example I have the following command:

$ my-cli -t -b -b "some value" my-file.txt

What I want is for the library to interpret the above as the following:

t: the string "-b"
b: the string "some value"

I should note that using -t "-b" is not an option. Currently the library returns the following error when running the program:

Expected parameter for option '-t' but found '-b'

These are my definitions for the -t and -b parameters:

@Option(names = "-b")
String bOption;

@Option(names = "-t", arity = "1..*")
public void checkTOption(List<String> values) {
  if (values != null && !values.isEmpty()) {
    tOption = values.get(values.size() - 1);
  }
}

Given the definition above, -t can also be specified multiple times, but only the last value is used. For example, these are equivalent commands:

$ my-cli -t a -t b -b "some string" -t c my-file.txt
$ my-cli -t c -b "some string" my-file.txt
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Scott Crooks
  • 1,523
  • 4
  • 24
  • 39
  • I'd interpret `-t -b -b` as 3 flags, if the second `-b` should be a string I'd expect `-t "-b" -b`. Why is this not an option? – Thomas Apr 12 '23 at 07:19
  • @Thomas Generally, double quotes are parsed by the shell, and do not occur in the actual arguments passed to the program (unless explicitly escaped) – Mark Rotteveel Apr 12 '23 at 07:30
  • Exactly. What I meant was that it's not an option for the user to pass `-t "-b"` to explicitly make it a string. – Scott Crooks Apr 12 '23 at 10:06

1 Answers1

3

This is covered in the PicoCLI documentation, section Option Names or Subcommands as Option Values.

There are in theory three options:

  1. Quote the parameter (like suggested by Thomas in the comments). You'll need to escape the double quotes according to the requirements of your shell:

    $ my-cli -t \"-b\" -b "some value" my-file.txt
    
  2. Enable the option setAllowOptionsAsOptionParameters on CommandLine. However, given the arity of -t is 1..*, this would consume all following options, and therefor is not an option in your case.

  3. Write a custom parameter consumer (see details in the documentation). I don't think it would be easy to solve the ambiguity of your example with that though (which is also why PicoCLI doesn't allow it anymore by default).

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 2
    Thank you Mark! The `setAllowOptionsAsOptionParameters` did the trick. And you're right also about the `arity`; it should have been just `1` since the `-t` option only ever needs / takes one parameter. – Scott Crooks Apr 12 '23 at 10:33
  • @ScottCrooks The fact that your current implementation uses `checkTOption` to take the last item, suggests it was an intentional design (maybe for backwards compatibility). Not knowing the greater context of this, I would recommend that you proceed with caution. – Mark Rotteveel Apr 12 '23 at 10:36