An Introduction to PicoCLI

These days I created a small test replacement of a CLI for demo purposes. At first, I was tempted to use Apache Commons CLI a library I knew because I already used it previously. Since the goal was to create a small mock-up of an already existing CLI we wanted to keep the 3rd party dependencies as small as possible and found an attractive alternative in picocli.

picocli - a mighty tiny command line interface

Within a few cycles we created a simple demo-stub with all options of the original command line program:

$ ./bin/demo-stub --help
Usage: demo-stub [-ehV] [-output=<outputFile>] title option [option [option
                 [option]]]
Stub for XML Writer
      title                  Title of the XML document.
                             Important: Should not contain new lines!
      option [option [option [option]]]
                             Up to four additional options per title.
  -e                         Encrypt the output XML file.
  -h, --help                 Show this help message and exit.
      -output=<outputFile>   Write sample XML file
  -V, --version              Print version information and exit.

The dead-simple Gradle build.gradle perfectly shows the only explicit dependency on picocli:

apply plugin: 'java'
apply plugin: 'application'

group = 'de.datenkollektiv.demo'
version = '0.1.0'

application {
    mainClassName = 'de.datenkollektiv.demo.DemoStub'
}

repositories {
    mavenCentral()
}

dependencies {
    compile 'info.picocli:picocli:3.9.0'
}

with no further transitive dependencies.

$ ./gradlew dependencies
...
compile - Dependencies for source set 'main' (deprecated, use 'implementation' instead).
\--- info.picocli:picocli:3.9.0
...

A single class with @Command, @Option and @Parameters annotations is everything you need...

@Command(description = "A simple picocli demo",
         name = "picocli-demo",
         mixinStandardHelpOptions = true,
         version = "0.1.0")
public class PicocliDemo implements Callable<Void> {

    @Option(names = { "-output" }, description = "Write sample XML file")
    private File outputFile = Paths.get("build", "sample.xml").toFile();

    @Option(names = { "-e" }, description = "Encrypt the output XML file")
    private boolean encrypted = true;

    @Parameters(index = "0", paramLabel = "Title", description = "Title of the XML document.\nImportant: Should not contain new lines!")
    private String title;

    @Parameters(index = "1", arity = "1..4", paramLabel = "Options", description = "Up to four available options per title")
    private String[] options;

    public static void main(String[] args) {
        CommandLine.call(new PicocliDemo(), args);
    }

    @Override
    public Void call() throws URISyntaxException, IOException {
        ...
    }
}

Once you are satisfied with the @Option and @Parameter definitions in your stub - build the program with:

./gradlew distZip

...and give it a try!


Photo by Waldemar Brandt on Unsplash