# Autocomplete for Java Command Line Applications

version 1.0.0-BETA1, 2017-08-07

> Every main method deserves picocli!

## 1. Command Line Completion

Starting from version 1.0.0, picocli-based applications can have command line completion in Bash or ZSH Unix shells. Picocli can generate an autocompletion script tailored to your application.

With this script installed, users can type the first few letters of a subcommand or an option, then press the TAB key, and the Unix shell will complete the subcommand or option.

In the case of multiple possible completions, the Unix shell will display all subcommands or options beginning with those few characters. The user can type more characters and press TAB again to see a new, narrowed-down list if the typed characters are still ambiguous, or else complete the subcommand or option.

## 2. Quick Start Tutorial

This tutorial uses the CheckSum example application from the picocli user manual. We created a class `com.myproject.CheckSum` and put it in a jar file, `myproject.jar`.

Follow these steps to give this application command line autocompletion.

### 2.1. Create Command

First, create an executable command that runs the main application class. For this tutorial, the command name is `jchecksum`.

We use an alias here to create the command (see alternatives):

    alias jchecksum='java -cp "picocli-1.0.0.jar;myproject.jar" com.myproject.CheckSum'

Let’s test that the command works:

    $ jchecksum --help
    Usage: jchecksum [-h] [-a=<algorithm>] <file>
    Prints the checksum (MD5 by default) of a file to STDOUT.
          file                    The file whose checksum to calculate.
      -a, --algorithm=<algorithm> MD5, SHA-1, SHA-256, ...
      -h, --help                  Show this help message and exit.

### 2.2. Generate Completion Script

To generate the completion script, run the `picocli.AutoComplete` class as a java application. Pass it the command name and the fully qualified class name of the annotated command class. (See also full description for using `AutoComplete`.)

    java -cp "picocli-1.0.0.jar;myproject.jar" picocli.AutoComplete -n jchecksum com.myproject.CheckSum

This generated a `jchecksum_completion` script in the current directory. To verify:

    $ ls
    jchecksum_completion  myproject.jar  picocli-1.0.0.jar

### 2.3. Install Completion Script

Finally, source the completion script:

Bash

    . jchecksum_completion

ZSH

    autoload -U +X compinit && compinit
    autoload -U +X bashcompinit && bashcompinit
    . ./jchecksum_completion

…​and you are done. The `jchecksum` command now has autocompletion:

    $ jchecksum <TAB><TAB>
    -a           --algorithm  -h           --help

### 2.4. Permanent Installation

The above will last for the duration of your shell session. If you want to make this permanent you need to modify your ~/.bashrc or ~/.zshrc file to add a line that defines the command alias and a line that sources the completion script:

Bash

    echo "alias jchecksum='java -cp \"picocli-1.0.0.jar;myproject.jar\" com.myproject.CheckSum'" >> ~/.bashrc
    echo ". jchecksum_completion" >> ~/.bashrc

Make sure to use `>>` (append), using a single `>` would overwrite the file.

`~/.bashrc` indicates `.bashrc` is in your home directory.

(See detailed Bash installation, Installing Completion Scripts Permanently in ZSH.)

## 3. Designing for Completion

When writing a picocli-based command line application there are a few things to consider to facilitate autocompletion.

### 3.1. Register Subcommands Declaratively

Register subcommands declaratively in your application with `@Command(subcommands = { …​ })` annotations where possible.

This way, you can generate a completion script by passing a single command class name to `picocli.AutoComplete`, and picocli will be able to infer the full hierarchy of command and subcommands from that top-level command class.

If your application registers subcommands programmatically, you can still generate a completion script, it is just more work.

### 3.2. Use Strong Typing

When generating the completion script, picocli inspects the type of the fields annotated with `@Option`. For some types, tab completion can also generate possible option values.

Picocli can generate completion matches for the following types:

- `java.io.File`

- `java.nio.file.Path`

- `java.net.InetAddress`

- any java `enum`

#### 3.2.1. Files and Directories

Generating autocomplete matches for `@Option` fields of type `java.io.File` or `java.nio.file.Path` will display a list of all files and directories in the current directory.

    $ demo --file <TAB><TAB>
    basic.bash              hierarchy               nestedSubcommands.bash

#### 3.2.2. Host Names

Generating autocomplete matches for `@Option` fields of type `java.net.InetAddress` will display a list of known hosts (from your `/etc/hosts` file).

    $ demo --host <TAB><TAB>
    cluster-p-1                          openvpn-client.myvpn.picocli.com
    cluster-p-2                          picop1
    cluster-p-3                          picop2
    cluster-p-4                          picop3
    cluster-scm-1                        picop4
    client.openvpn.net                   picoscm1

#### 3.2.3. Java `enum` Values

Generating autocomplete matches for `@Option` fields of any Java `enum` type `java.net.InetAddress` will display the list of enum values.

For example:

    $ demo --timeUnit <TAB><TAB>
    DAYS     HOURS     MICROSECONDS  MILLISECONDS  MINUTES    NANOSECONDS   SECONDS

## 4. Alternative Ways to Define Commands

This section describes creating commands in more depth than the Quick Start Tutorial.

In Bash and ZSH, there are multiple ways to create an executable command for a java class.

### 4.1. Alias

One way is to define an alias:

    alias jchecksum='java -cp "picocli-1.0.0.jar;myproject.jar" com.myproject.CheckSum'

Be aware that the alias only lasts as long as the current shell session. To make it permanent, add it to your `~/.bashrc` or `~/.zshrc` file.

You may also want to specify the full path to the jar files in the classpath so that the command can be executed anywhere.

### 4.2. Function

Another way is to define a function:

    jchecksum() {
        java -cp "picocli-1.0.0.jar;myproject.jar" com.myproject.CheckSum "$@"
    }

To make it permanent, add it to your `~/.bashrc` or `~/.zshrc` file.

### 4.3. Script

Yet another way is to create a script:

    $ echo '#!/usr/bin/env bash' > jchecksum
    $ echo 'java -cp "picocli-1.0.0.jar;myproject.jar" com.myproject.CheckSum $@' >> jchecksum
    $ chmod 755 jchecksum

    $ cat jchecksum
    #!/usr/bin/env bash
    java -cp "picocli-1.0.0.jar;myproject.jar" com.myproject.CheckSum $@

## 5. Completion Script Generation Details

This section describes generating completion scripts in more depth than the Quick Start Tutorial.

### 5.1. Running AutoComplete

To generate the completion script, run the `picocli.AutoComplete` class as a java application, passing it the fully qualified class name of the annotated command object.

    $ java -cp "picocli-1.0.0.jar;myproject.jar" picocli.AutoComplete com.myproject.CheckSum

This will instantiate your command, and inspect it for `@Option` and `@Command` annotations. Based on these annotations it will generate a completion script in the current directory.

Because of this, the command class needs to be on the classpath when running the `picocli.AutoComplete` class.

### 5.2. Command Name

The name of the generated completion script is based on the `@Command(name ="<COMMAND-NAME>")` annotation, or, if that is missing, the command class name. Use the `-n` or `--name` option to control the name of the command that the completion script is for.

    $ java -cp "picocli-1.0.0.jar;myproject.jar" picocli.AutoComplete -n jchecksum com.myproject.CheckSum

This will generate a `jchecksum_completion` script in the current directory.

Other options are:

- Use `-o` or `--completionScript` to specify the full path to the completion script to generate.

- Use the `-f` or `--force` option to overwrite existing files.

- Use the `-w`, `--writeCommandScript` option to generate a sample command script.

### 5.3. Subcommands

For commands with subcommands, bear in mind that the class that generates the completion script (`picocli.AutoComplete`) needs the full hierarchy of command and subcommands to generate a completion script that also works for the subcommands.

The above will work when subcommands are registered declaratively with annotations like `@Command(subcommands = { …​ })`.

### 5.4. Programmatically Registered Subcommands

When subcommands are not registered declaratively, you need to do a bit more work. You need to create a small program that does the following:

- Create a `CommandLine` instance with the full hierarchy of nested subcommands.

    // programmatically (see above for declarative example)
    CommandLine hierarchy = new CommandLine(new TopLevel())
            .addSubcommand("sub1", new Subcommand1())
            .addSubcommand("sub2", new Subcommand2());

- Pass this `CommandLine` instance and the name of the script to the `picocli.AutoComplete::bash` method. The method will return the source code of a completion script. Save the source code to a file and install it.

## 6. Installing Completion Scripts Permanently in Bash

This section describes installing completion scripts in more depth than the Quick Start Tutorial.

Make sure bash completion is installed.

Source the generated completion script to install it in your current bash session.

To install it more permanently, place the completion script file in `/etc/bash_completion.d` (or `/usr/local/etc/bash_completion.d` on a Mac). If `bash-completion` is installed, placing the completion script in either of these directories should be sufficient. (Source your `~/.bash_profile` or launch a new terminal to start using this completion script.)

Alternatively, make a directory `mkdir ~/bash_completion.d`, and place the completion script in this directory. Edit your `~/.bashrc` file and add the following:

    for bcfile in ~/bash_completion.d/* ; do
      . $bcfile
    done

All completion scripts in the `~/bash_completion.d` directory will now be available every time you launch a new shell.

Source your `~/.bash_profile` or launch a new terminal to start using this completion script.

## 7. Installing Completion Scripts Permanently in ZSH

This section describes installing completion scripts in more depth than the Quick Start Tutorial.

Zsh can handle bash completions functions. The latest development version of zsh has a function bashcompinit, that when run will allow zsh to read bash completion specifications and functions. The zshcompsys man page has details. To use it, run bashcompinit at any time after compinit. It will define complete and compgen functions corresponding to the bash builtins.

Source the generated completion script to install it in your current shell session.

To install it more permanently, make a directory `mkdir ~/bash_completion.d`, and place the completion script in this directory. Edit your `~/.zshrc` file and add the following:

    autoload -U +X compinit && compinit
    autoload -U +X bashcompinit && bashcompinit
    for bcfile in ~/bash_completion.d/* ; do
      . $bcfile
    done

All completion scripts in the `~/bash_completion.d` directory will now be available every time you launch a new shell.

Then reload your shell:

    exec $SHELL -l

## 8. Picocli User Manual

The picocli user manual explains how to build Java command line applications with picocli.

## 9. GitHub Project

The GitHub project has the source code, tests, build scripts, etc.

Star or fork this project on GitHub if you like it! (Projects with many forks are easier to find on GitHub Search.)

## 10. Issue Tracker

Please use the Issue Tracker to report bugs or request features.

## 11. License

Picocli is licensed under the Apache License 2.0.

## 12. Releases

Previous versions are available from the GitHub project Releases.