complete
// use a custom completion command for all args named "plugin"
complete "plugin" run="mycli plugins list"type — completions usage supplies itself
Instead of a run, a completer can name something usage already knows how to complete. run and type are alternatives; setting both is an error.
complete "path" type="file"
complete "manifest" type="path:toml,yaml"
complete "key" type="config_keys"
complete "value" type="config_values"Append a comma-separated extension list to path: or file: to keep directory traversal while offering only matching files. Extensions omit the leading dot; for example, type="path:toml,yaml" offers directories plus .toml and .yaml files.
| type | completes |
|---|---|
file, path | files and directories, relative to the working directory |
dir | directories only |
executable | executable paths |
command | commands known to the shell, including names found on PATH |
command_args | a command for the first value, then ordinary argument paths |
config_keys | the settings this spec's config block declares |
config_values | the values accepted by the setting named earlier on the command line |
username | user names, from the environment and /etc/passwd |
hostname | host names, from the environment and /etc/hosts |
none, url, email | nothing — the value has no completable candidates, and the file fallback is suppressed |
unknown | nothing, but the shell's normal fallback stays available |
The types below config_values exist mostly so specs generated from clap can carry its ValueHints. username and hostname offer real candidates; none, url, email, and unknown are hint passthroughs with no candidates of their own.
An arg or flag with no completer of its own falls back to file unless its declared choices say otherwise, so type="file" is only worth writing to be explicit.
Completing settings
config_keys and config_values are what a config get/config set pair wants, and they need no run: the spec already says what the keys are and what each accepts.
complete "key" type="config_keys"
complete "value" type="config_values"
cmd "config" {
cmd "set" {
arg "<key>"
arg "<value>"
}
}config_keys offers every prop in the block, dotted keys and all, with its help as the description. A hided setting is left out; a deprecated one is still offered — a config file in the wild names it, so it must be completable — with its description saying so.
config_values looks back along the command line for the last word that names a setting, so it does not matter where the key sits relative to the cursor. It offers that setting's choices with their own help, or true and false for a boolean. For anything else it stays quiet and the file fallback applies, which is what a path-valued setting wants anyway.
A key is matched by every name the setting answers to, not only the one it is declared under: an alias resolves to the setting that declares it, and a renamed_to chain is followed to the setting that now holds the values. Those are the names a config file in the wild still carries, so they are the ones a user types.
Both are closed: where the spec enumerates the candidates, a prefix matching none of them completes to nothing rather than falling back to filenames. A setting whose values the spec does not enumerate keeps the fallback — including a union like bool|path, where true and false are offered but a path is still valid, so a path prefix still completes.
Descriptions are reduced to their first line, since one candidate is one row of a menu.
Descriptions
If you set descriptions=#true, you can provide descriptions for the completions:
complete "plugin" run="mycli plugins list" descriptions=#trueResults will be split on ":" with the first part being the completion value and the second part being the description, e.g.:
user:User's full name
port:Port number":" can be escaped with a backslash.
Templates
The run can be customized with tera templates. The following values are available:
words: A list of all words currently in the prompt. Individual words can be accessedwords[1]CURRENT: The index of the word currently being typed, combine withwordsto get the current word e.g.words[CURRENT].PREV: The index of the previous word in the prompt (CURRENT-1), combine withwordsto get the previous word e.g.words[PREV].
Values interpolated into run are not escaped automatically. Pass every typed word that becomes one shell argument through shell_quote; the filter emits one POSIX-shell-safe word, including spaces, quotes, substitutions, and command separators as literal data:
complete "package" run="mycli complete --query={{ words[CURRENT] | shell_quote }}"Leaving off the filter is appropriate only when the interpolation is deliberately shell syntax. shell_quote accepts strings; quote list members individually rather than quoting a joined command line.
When a child process needs the complete argv as one command-line string, shell_join preserves the original word boundaries before shell_quote makes that command line one inert argument:
complete "arg" run="mycli __complete --line={{ words | shell_join | shell_quote }}"Example of completing the second argument based on the first:
arg "<module>"
arg "<controller>"
complete "module" run="ls modules"
complete "controller" run="ls modules/{{ words[PREV] | shell_quote }}/controllers"Example of using multiple words (one, two, three) for the completions of the fourth argument:
arg "<one>"
arg "<two>"
arg "<three>"
arg "<four>"
complete "four" run="echo {{ words | slice(start=-4) | join(sep='\"\n\"') }}"Here we just use simple commands like ls and echo but these words could be passed to any command.
Which shell runs run
run is executed with sh -c, so it is a POSIX shell command line: pipelines, ; sequences and shell builtins all work.
On Windows a POSIX shell is not guaranteed. usage still runs sh -c when sh is on PATH (Git for Windows provides it), and falls back to cmd /c when it is not. cmd cannot run any of the above — it only handles a plain command invocation — so a spec that targets Windows should either keep run to a single command or state that it needs a POSIX shell.
The script is run with stdin closed and stderr inherited, and with __USAGE set to the usage version so a script can tell it was invoked by usage.