DocsDynamic suggestions

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.

  1. Find a shell command that outputs relevant information.
  2. 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 the cat 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.

  1. filepaths - suggests files and folders
  2. folders - 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 and filterTerm.

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.