Dynamic Suggestions
Argument suggestions can be generated dynamically by running shell commands or reading local files.
While autocomplete for subcommands and options can be defined statically, in order to provide suggestions for arguments, completion specs must execute code at runtime.
Generators
A Generator defines a function that transforms the output of a shell command into an array of Suggestion objects.
For example, the following is an Argument object (with an associated Generator) that could provide branch suggestions for git checkout
,
{
name: "branch",
generators: [
{
script: "git branch -l",
postProcess: function(out) {
return out.split('\n').map(branch => {
return { name: branch, description: "branch"}
})
}
}
]
}
The script
property is executed as a command in the same working directory as the interactive shell.
See "Executing Shell Commands" for more details.
The result of running git branch -l
looks something like this:
$ git branch -l
main
staging
mschrage/aws
mschrage/feature-abc
mschrage/eng-334-build-universal-binary-to-support-m1
mschrage/filepath-issues
mschrage/fix-cp
The output of the script
is passed to to the postProcess
function. This function converts the raw string to a list of Suggestion objects. In the example above, the string is split on the newline character, then each line is iterated over and turned into a Suggestion.
This is a very common pattern when building your own generator.
- Find a shell command that outputs relevant information.
- Write a function that parses it into a richer format — adding a relevant description, setting a custom icon or determining the appropriate priority.
Tip: You can use the contents of files, like
package.json
, in a Generator by running thecat
command.
Templates
Some Generators are so common across CLI tools that it doesn't make sense for every spec to reimplement them from scratch.
Currently, there are only two types of templates.
filepaths
- suggests files and foldersfolders
- only suggests folders
The most notable examples are the generators that provide suggestions for filepaths
and folders
. Implementing these generators are surprisingly involved and require advanced properties, like filterTerm
and trigger
.
The completion spec for cd
demonstrates how templates are used. Rather than writing a complicated generator, we can just drop in the folders
template. template
is a property that is defined inside of Arguments.
const completionSpec: Fig.Spec = {
name: "cd",
description: "Change the shell's working directory.",
args: {
name: "directory"
template: "folders"
}
};
Templates are syntactic sugar for complicated Generators. Conceptually, they do the same thing: help Fig provide suggestions for an argument. However, rather than saying how to generate the suggestions, they merely say what to generate… and leave the underlying implementation to Fig.
See "Templates" for more information on how to use templates.
Advanced Generators
Most completion specs can be built using a mix of templates and basic generators. However, in some cases you need more flexibility.
Contextual Scripts
Providing suggestions that require context from other flags or options in the current edit buffer (i.e.based on values the user has just typed in their terminal but not yet executed).
To handle this case, a Generator needs to run a script
which incorporates the text that the user has typed.
heroku addons:remove --app my-example-app |
For example, when completing this heroku
command, Fig should only suggest addons that are associated with the specific app, my-example-app
.
See "Contextual Generators" to learn how to run a
script
that incorporates text from the user's edit buffer.
Triggers & Filtering
Providing a new set of suggestions after the user types a certain character, like the /
in a filepath, for instance.
See "Reimplementing the Filepath Generator" for more information of how to use
triggers
andfilterTerm
.
Caching & Debouncing
Suggestions are computed by an expensive function — a web request, for instance — and should be cached or debounced.
See "Making an HTTP Request from a Generator" for details on how to handle expensive functions.
Custom
Write imperative code where suggestions must be recomputed on every keypress, to handle tools with non-standard parsing, like chmod
.
See "Custom Generators" to learn more.