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 generates 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:
. 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:
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.
2.5. Distribution
Have a subcommand that generates a completion script. |
You could generate completion scripts for your commands during the build and distribute them with your application, but an alternative is to give your application the ability to generate its own completion script on demand.
That allows end users to install completion for your application with a single command.
For example, if your utility is called mycommand
, users can install completion for it by running the following command:
$ source <(mycommand generate-completion)
This can be accomplished by registering the built-in picocli.AutoComplete.GenerateCompletion
class as a subcommand of the top-level command.
For example:
import picocli.AutoComplete.GenerateCompletion;
import picocli.CommandLine;
import picocli.CommandLine.Command;
@Command(name = "mycommand", subcommands = GenerateCompletion.class)
public class MyApp implements Runnable {
@Override
public void run() { // top-level command business logic here
}
public static void main(String[] args) {
new CommandLine(new MyApp()).execute(args);
}
}
By default, the generate-completion
command shows up as a subcommand in the usage help message of its parent command.
Applications that want the completion subcommand to be hidden in the usage help message, can do the following:
public static void main(String... args) {
CommandLine cmd = new CommandLine(new MyApp());
CommandLine gen = cmd.getSubcommands().get("generate-completion");
gen.getCommandSpec().usageMessage().hidden(true);
int exitCode = cmd.execute(args);
// ...
}
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 will display the list of enum values.
For example:
$ demo --timeUnit <TAB><TAB>
DAYS HOURS MICROSECONDS MILLISECONDS MINUTES NANOSECONDS SECONDS
3.3. Other Completion Candidates
Picocli 3.2 introduces a completionCandidates
API that can be used to generate completion candidates
regardless of the type of the option or positional parameter.
Picocli calls this iterator when the completion script is generated.
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 thepicocli.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/ZSH
This section describes installing completion scripts in more depth than the Quick Start Tutorial.
Source the generated completion script to install it in your current bash or zsh session.
6.1. ZSH
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.
Since picocli 4.1, the generated completion script contains the following code to run bashcompinit
after compinit
; this will define complete
and compgen
functions corresponding to the bash builtins.
It is no longer necessary to manually run the below commands.
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
6.2. If bash-completion
is Installed
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.)
6.3. Without bash-completion
Installed
Alternatively, make a directory mkdir ~/bash_completion.d
, and place the completion script in this directory. Edit your ~/.bashrc
file (or ~/.zshrc
file on ZSH) 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 the generated completion script or launch a new terminal to start using this completion script.
7. Generating Completion Scripts During the Build
It may be useful to generate your completion scripts automatically during the build. Below is an example Maven snippet that demonstrates how to achieve this.
7.1. Maven Example
Setting system property picocli.autocomplete.systemExitOnError ensures the build fails if there is any problem generating the completion script (requires picocli v3.9.1).
|
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec-maven-plugin.version}</version>
<executions>
<execution>
<id>generate-autocompletion-script</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Dpicocli.autocomplete.systemExitOnError</argument>
<argument>-cp</argument>
<classpath/>
<argument>picocli.AutoComplete</argument>
<argument>--force</argument><!-- overwrite if exists -->
<argument>--completionScript</argument>
<argument>${project.build.directory}/mycommand_completion.sh</argument>
<argument>mypackage.MyCommand</argument><!-- replace with your class -->
</arguments>
</configuration>
</plugin>
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.