Search code examples
javacommand-linepicocli

How to get PicoCLI to interpret next item as flag and not string


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

Solution

  • 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).