Skip to content

Plans and Notes for Future Articles

nosamu edited this page Nov 11, 2022 · 33 revisions

…​ the world needs more picocli articles!

Below is a TODO list of picocli articles to write to make the world a better place.

Avoid reflection with the picocli programmatic API

Shows how to use the picocli programmatic API to avoid reflection. When using the annotations API, picocli creates a model automatically, but it uses reflection to do so. Some applications want to avoid using reflection, and some developers don’t like the "magic" of annotation-based APIs.

Applications can use the picocli programmatic API to create a model manually. At a very basic level, this allows programmers to do everything they were able to do with other libraries that offer a programmatic API (without annotations) for command line applications, like Apache Commons CLI and Argparse4j.

This retains all the benefits picocli offers:

  • Convenient: parse user input and run your business logic with one line of code

  • Strongly typed everything - command line options as well as positional parameters

  • POSIX clustered short options (<command> -xvfInputFile as well as <command> -x -v -f InputFile)

  • Fine-grained control: an arity model that allows a minimum, maximum and variable number of parameters, e.g, "1..*", "3..5"

  • Subcommands (can be nested to arbitrary depth)

  • Feature-rich: composable arg groups, splitting quoted args, repeatable subcommands, and many more

  • User-friendly: usage help message uses colors to contrast important elements like option names from the rest of the usage help to reduce the cognitive load on the user

  • Distribute your app as a GraalVM native image

  • Works with Java 5 and higher

Evolution of a Library

Features from version 0.9.8 to 4.4, what was hard, what was easy. Mistakes, things we’re happy with.

Awesome CLI: Tiny, Powerful, Speedy Command Line Apps with Picocli and GraalVM

Kickstarting Tiny, Powerful Command Line Apps with Picocli and GraalVM

CLI Apps: What’s Your Style?

Most libraries support only a certain programming style. For example, Commons CLI, JOpt Simple and Argparse4j offer a programmatic API, while other libraries like JCommander, Args4J and Airline offer an annotations API. Some of these capture options in annotated fields, others use annotated methods. Perhaps you like JewelCLI for its annotated interface methods, or Tomitribe CREST's JAX-RS-like @Command-annotated methods.

Picocli supports all of these styles.

CliBuilder Tips and Tricks

Things possible with CliBuilder since Groovy 2.5.

  • colored usage help

  • autocompletion (try the built-in AutoComplete.GenerateCompletion subcommand)

  • control over usage help message

  • @-files

  • PropertiesDefaultProvider

Advanced Configuration

Create CLI apps that give your users more flexibility on whether command line args override the configuration or the other way around. See also prior art:

Picocli v3: Not Your Father’s Command Line Parser

Programmatic API makes it possible to apply picocli in a wide range of applications. One example is that it’s easy to build DSLs (Domain Specific Languages) like Groovy CliBuilder, or use picocli in applications where command line options are defined dynamically. 3.0 also adds support for reuse via Mixins, gives fine-grained control over STDOUT vs STDERR and exit codes. The programmatic API also facilitates the use of picocli in JVM languages where annotations and reflection are not supported or not convenient.

Migrating from Commons CLI to Picocli

Lessons learned while migrating the Groovy command line tools from Commons CLI to picocli.

Interactive CLIs with JLine and Picocli

Using picocli with Dependency Injection containers

Using picocli with JSR-380 Beans Validation

Command Line TAB Autocompletion for Java with Picocli

Java command line applications can now have TAB autocompletion when running on Bash. Now that Windows 10 natively supports Bash, that means pretty much anywhere! This is how you do it…​

ANSI Colors and Style for Kotlin Command Line Apps via Picocli

If you’re creating Kotlin command line applications, you may want to consider using this small library to parse command line options and output a smart-looking usage help message with ANSI colors and styles. Bonus: command line TAB autocompletion.

ANSI Colors and Style for Scala Command Line Apps via Picocli

If you’re creating Scala command line applications, you may want to consider using this small library to parse command line options and output a smart-looking usage help message with ANSI colors and styles. Bonus: command line TAB autocompletion.

Command Line Applications with Subcommands Made Easy with Picocli

Walk through the steps of building a command line application with subcommands. Demonstrates some of the things that picocli makes easy, and some of the things that you need to be aware of. Emphasize the convenience methods and error handling. For example, how to have global options apply to all subcommands. (Related: https://github.com/remkop/picocli/issues/247, https://github.com/remkop/picocli/issues/248, https://github.com/remkop/picocli/issues/175)

Testing Picocli-based Command Line Applications

How do you write unit tests for command line applications built with picocli?

option modifiers

Article on the idea to provide options with a similar prefix that give users different options for authenticating. See discussion in https://github.com/remkop/picocli/issues/176

Good timing for this article may be after https://github.com/remkop/picocli/issues/82 is implemented. We could suggest this in the user manual section on that feature as well.

Example: Sort/Uniq

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.concurrent.Callable;
import java.util.stream.Stream;

import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

@Command(name = "sort", mixinStandardHelpOptions = true, version = "sort 1.0",
    description = "Sort input lines and write to standard output.")
public class Sort implements Callable<Void> {
    @Parameters(description = "The path to read lines from")
    Path path;

    @Option(names = {"-u", "--unique"}, description = "Output only distinct values")
    boolean unique;

    @Option(names = {"-c", "--count"}, description = "Prefix values by the number of occurrences")
    boolean count;

    @Option(names = {"-r", "--reverse"}, description = "Reverse sort order")
    boolean reverse;

    @Option(names = {"-s", "--skip"}, paramLabel = "NUM", description = "Skip the first NUM values")
    long skip;

    @Override
    public Void call() throws Exception {
        Stream<String> sorted = Files.lines(path).skip(skip).sorted(
                reverse ? reverseOrder() : naturalOrder());
        if (unique) {
            String format = count ? "%d\t%s%n" : "%2$s%n";
            sorted.collect(groupingBy(identity(), LinkedHashMap::new, counting()))
                    .forEach((str, num) -> { System.out.printf(format, num, str); });
        } else {
            sorted.forEach(System.out::println);
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        CommandLine.call(new Sort(), args);
    }
}
Clone this wiki locally