Search code examples
javapicocli

How do I get picocli to parse `"--item --item foo"` as `[null, "foo"]` `:List<String>`


I have a parameter named --msg-content-list-item

public class CliProtonJ2Sender implements Callable<Integer> {

    @CommandLine.Option(
        names = {"--msg-content-list-item"},
        arity = "0..1",
        defaultValue = CommandLine.Option.NULL_VALUE)
    private List<String> msgContentListItem;


    // ...
}

I wish for the following test to pass

    @Test
    void test_msgContentListItem() {
        CliProtonJ2Sender a = new CliProtonJ2Sender();
        CommandLine b = new CommandLine(a);
        CommandLine.ParseResult r = b.parseArgs("--msg-content-list-item", "--msg-content-list-item", "pepa");

        // https://github.com/powermock/powermock/wiki/Bypass-Encapsulation
        List<String> v = Whitebox.getInternalState(a, "msgContentListItem", a.getClass());
        assertThat(v).containsExactly(null, "pepa");
    }

But it doesn't and I get

missing (1): null
---
expected   : [null, pepa]
but was    : [pepa]

How do I define @CommandLine.Option to behave the way I want?


Solution

  • There was a bug which is now fixed.

    Prior to version 4.7.2, use the workaround in my other answer.

    As of picocli 4.7.2, use the fallbackValue like this

    @Option(names = {"--list"}, arity = "0..1", fallbackValue = CommandLine.Option.NULL_VALUE)
    List<String> list;
    

    from https://github.com/remkop/picocli/blob/2944addb8ba34d2ee6f97564bd43128bb62ec382/src/test/java/picocli/FallbackTest.java#L192-L193