💪Autocomplete
Overview
Fig defines a standard schema for building autocomplete for CLI tools. This schema is called a completion spec. Fig takes a user's input in the terminal, maps it to the relevant completion spec, and renders suggestions accordingly.
The below is an example of a simple completion spec. Think of it as a big tree that maps out a CLI tool.
Git Repo
Personally, I learn best by looking at examples. I suggest looking at some of the completion specs for commands you know well. You should be able to pick up the format pretty quickly.
Git Repo: withfig/autocomplete Git Repo URL: https://github.com/withfig/autocomplete/tree/master/specs
Contributing
We ❤️contributors. Autocomplete is a community driven effort. Just fork the repo, make changes, and submit a pull request.
If you have any questions, please email us: hello@withfig.com or join our slack. We are very responsive
Note: A completion spec is a javascript object. Therefore, it must always begin with var completionSpec =
Getting Started
Fig takes a user's terminal input, splits it into an abstract syntax tree (AST), maps this AST to the completion-spec, works out the range of possibilities of what the user could input next (these possibilities are called suggestions), and renders the suggestions to the user.
This is a lot of steps. The only thing you need to worry about is making a good completion spec.
Fig's completion specs serve two purposes. They
1. Define a CLI tool in a structured tree-like representation. Mapping a user's Terminal input to this defined tree structure gives us the context on the user's input. This lets us accurately generate suggestions.
e.g. we will generate very different suggestions if a user types git
versus git commit -
2. Contain Content Completion specs provide content (like descriptions, icons etc) for the suggestions that are rendered to the user. If instructions on how to generate suggestions (like get all the files in this specific folder)
i.e. your description of the -m
option in git commit -m
is what will displayed to the user!
Defining the CLI Structure (and Quick Summary of How CLI Tools work)
It is important to understand these concepts to successfully build a completion spec.
CLI Tool / Program A CLI tool is essentially a mini program. These program take a list of strings as input (usually separated by spaces). The strings can be subcommands, options, or arguments
Examples of CLI tools / Programs are git
, cd
, echo
, ls
, cat
, docker
, npm
Subcommands
A subcommand is like another program / CLI tool, nested beneath the original program. Examples of subcommands are git commit
, git add
, git push
, docker build
, npm install
etc.
Like CLI tools, subcommands can then have their own subcommands, options, and arguments.
Options Options are special strings with dashes (single or double). They add extra information to a CLI tool and are parsed specially by the CLI tool.
Some options take arguments
e.g. git commit -m "my message"
: -m
is the option and it takes the argument "my message"
Other options don't take arguments. These are known as boolean options or flags
e.g. git --version
, heroku apps --json
, npm --global
, ls -l
Argument Finally, an argument is like a user input. Each CLI tool has its own rules about what arguments it takes.
CLI tools, subcommands, and options can all take arguments. They can take 0 arguments, 1 argument, 2 arguments, ... n arguments, or infinite arguments. Note: A command / option that takes infinite arguments is called variadic.
examples
git commit -m "my message"
-> -m
takes one input which is a string
git add index.html app.js
-> takes infinite arguments, but the user only input two
BONUS: Man Pages
The synopsis section of man pages (try running man git
in your terminal) gives a good mapping of a CLI tool's structure. Some hints:
Square brackets indicate subcommands/options/arguments are optional
Angle brackets indicate subcommands/options/arguments are mandatory
Fig is working on a parser that converts the synopsis section into an autocomplete spec. If you know of an open source tool OR want to contribute, let us know: hello@withfig.com
Objects You Need to Know to Build Completion Specs
Note: If you haven't already, read / skim the above section so you understand how CLI tools work. The objects below are based on this.
There are 4 objects you need to understand to successfully build a completion spec.
Suggestion Object - objects generated by a completion spec. What Fig uses to render suggestions to the user
Command Object - defines a CLI tool / subcommand
Option Object - defines the options a CLI tool / subcommand takes
Arg Object - defines the inputs / arguments a CLI tool / subcommand / option takes
A Suggestion object is what Fig renders in the Autocomplete popup. In your completion spec, you will almost always use the Command, Option, and Arg objects.
Command and Option objects are supersets of the Suggestion object i.e. they have the same properties as the Suggestion object and more. When parsing a completion-spec, Command and Option objects are more or less converted directly into Suggestion objects.
The Arg object is more like a schema or a blueprint. We know the full range of subcommands or options a user could input. We also know that certain commands / options take arguments, but we don't necessarily know what these arguments will be. If the argument must be constrained in some way (e.g. it MUST be a file or MUST be a folder), we define some rules in the Arg object to generate suggestions.
The presence of an Arg object indicates a command/option takes an argument. Extra details inside the Arg object are used to help us generate suggestions.
For instance, we know git add
takes an array of files, cd
takes a folder path, and heroku -a
takes a string representing your Heroku app. Because we know certain conditions about these arguments, we can define special rules for generating Suggestion objects for each of these.
You can learn more about each object type in the sections below.
Suggestion Objects (and How They're Rendered)
After taking a user's Terminal input to the relevant completion spec. It then outputs an array of Suggestion objects.
AGAIN: you will almost never use this object. Fig will create it for you. This section is just for your reference.
-m
example from git commit
Note: the only required property is "name". Fig automatically generates the remaining properties from rules in the completion spec. You can choose to override them if you want to.
icon
name
description
insertValue
name
This is what will show up as a suggestion in the autocomplete box. If it's an array, all strings will be shown separated by a comma.
type
This is the type of suggestion being shown. It can be one of subcommand, option, argument, shortcut, special. It is used to generate the icon if one is not provided.
description
The description for this specific suggestion. This is what will show up in the bottom autocomplete box. There isn't too much space, so try to be as concise as possible!
insertValue
When a user selects a suggestion (clicks tab or enter) it will insert this value.
Default: current suggestions name
property + space
When a user selects a suggestion (clicks tab or enter) it will insert this value.
The insertValue property is often used when you can anticipate what the user is typing next. e.g. if you could automatically insert quotes if you know they are about to type a long string.
insertValue allows specific shortcuts that represent keyboard keys
\b
- backspace\033[D
- left arrow key\033[C
- right arrow key{cursor}
- will insert the cursor to where it was placed
e.g. in git commit -m
, the completion object may look like:
icon
The icon that will display next to the suggestion. It can be an emoji or a url that will be inserted as the href to an img tag. If an icon property is not provided, Fig will use a default icon based on the type property
Command Object
The Command object is a superset of the Suggestion object i.e. it takes all the same properties as a Suggestion object plus the following properties
The command object is the backbone of the completion spec. It is recursive (the subcommands property takes an array of Command objects). Fig uses a Command object to create suggestions for commands and subcommands + for parsing.
Important Things to Note
the
name
property must be a string NOT an array of strings like in a Suggestion object. This is for parsing purposes.The subcommands, options, and args properties are all optional
The args property must be included if the subcommand takes an argument(s) and you want Fig to parse it correctly.
When converting a Command object into a Suggestion object, Fig automatically makes the type property = "subcommand"
Quick Example
Let's look at git
git
is a Command object. It has a property
subcommands
which is an array of all of git's subcommands (e.g.commit
,push
,add
...)options
which is an array of all of the options available to git at that particular levele.g.
--version
is available to git but not togit commit
etc
Now let's look at git push
push
is one of the Command objects listed in the subcommands property for git
. It represents the command git push
. It is a Command Object, with properties:
args
which is an array of Arg objects, each representing the arguments thegit push
command takes (ie the repository and branch)etc
You can look at the git
completion spec here: https://github.com/withfig/autocomplete/blob/master/specs/git.js
Option Object
The Option object is a superset of the Suggestion object i.e. it takes all the same properties as a Suggestion object. It is literally exactly the same.
Here is an example of git --version
Important Things to Note
When converting an Option object into a Suggestion object, Fig automatically makes the type property = "option"
The args property is optional but must be included if the option takes an argument(s) and you want Fig to parse it correctly.
Remember: you don't need properties like icon, insertValue, or type - Fig can create these for you
Arg Object
Please read this full section
The Arg object is NOT superset of the Suggestion object. These are the below properties
property
type
required
name
string
false
description
string
false
optional
boolean
false
variadic
boolean
false
suggestions
array of strings OR array of Suggestions
false
templates
Template Object
false
generator
Generator Object
false
NOTE: No properties are required. But please read below.
Important things to Note
The presence of an Arg object signals to Fig's parser that a command or an option takes an argument (or arguments). This is VERY IMPORTANT. If we don't know a command / option takes an argument, Fig's parser will get mixed up and will present the wrong suggestions.
If a command or option takes arguments, include the correct number of Arg objects
If you don't know what to include for the argument, you should include an empty object
If an argument is optional, add the optional property.
Here is an example of why this is very important. Let's say you are building the git
completion spec. You are trying to define the -m
option in git commit -m
If you didn't signal to Fig that -m took an argument, Fig would just assume that the next string the user inserts could be another option and will give poor suggestions. In reality, the next string the user inserts must be the argument to the -m option. We should only suggest accordingly. Therefore, you must include an array with a single empty Arg object in the Option object like so:
Properties
name
The name for the argument. Currently it is not rendered, but will be in the future.
e.g. git push <remote> [refspec]
- the names of the two arguments are remote
and refspec
description
The description for the argument. Similar to the name property, it is not currently rendered, but describes the argument in more depth than the name.
optional
Signals that an argument input is optional. Usually this is when something has a default value
e.g. npm install
takes an optional input. npm install
on its own is a valid command that will install all the files in your package.json. But if you did npm install react
it would specifically install react. In this case, react is an optional argument.
Including this is important for Fig's parsing.
variadic
Signals that Fig should stop offering suggestion for future inputs because this one will continue indefinitely.
e.g. echo
& git add
both take a single argument that is variadic
Including this is important for Fig's parsing.
suggestions
Suggestions to provide if the user is inputting the current argument. This can either be an array of Suggestion objects OR an array of strings (which Fig will convert to an array of Suggestion objects with the name equal to each string)
generator
This property is a javascript object. If present, the object will run the script property in the user's local shell. It will then get the shell output as one big string. It will then convert this into Suggestion objects by splitting on the splitOn property (e.g. \n
or ,
) or by taking the string and applying a function specified in the postProcess property. The postProcess function may output an array of strings that Fig will convert into Suggestion objects OR output an array of Suggestion Objects
key
value type
options
description
required
script
string
yes
splitOn
string
yes or postProcess
postProcess
javascript function that takes one string input and outputs array of strings or Suggestion objects
yes or splitOn
Note: when using the script property you are writing bash/zsh. When you try and write a bash string in javascript, the parsing of certain characters gets annoying. I strongly recommend using the String.raw method
Look at the heroku.js completion spec for Heroku for good examples of generator.
templates
This is very similar to the generator property. There are several standard types of arguments that CLI tools take. For example, CLI tools often take filepaths and folders as input.
Rather than you implementing this yourself with generator, Fig has pre-built the logic to generate suggestions for:
filepaths (see example when using Fig autocomplete and
open
command)folders (see example when using Fig
autocomplete
and cd command)
It is a javascript object with the following properties
properties
value type
type
string (can be one of "filepaths", "folders")
postProcess
javascript function that takes an array of suggestion objects as input and outputs array of SuggestionObjects
Alternatively, rather than including a javascript object, the templates property could just take the a single string of paths that would be provided to the template property mentioned just above.
Look at the open.js completion spec and cd.js completion spec for good examples of templates.
Testing Your Completion Spec
Where should I save my completion spec
We suggest saving your completion spec in the following folder: ~/.fig/autocomplete
and editing it from there.
What's the best way to test my spec
Fig loads the completion specs as you type in your Terminal. But to be faster and save computer power, we keep the current script loaded until you start using a new CLI tool for which we have a completion spec.
So, if you make changes to a spec, go to your terminal, load up another spec (e.g. type cd plus space), then backspace to the start, then you can type in your command which will load up your newly updated spec.
Can Fig get confused
Yes! If you find yourself using keys like the arrow keys, cmd/option,ctrl/shift, OR terminal aliases or history etc, Fig may get confused. When Fig gets confused, it stops rendering completions.
If this happens, just got to a new line (enter or ctrl + c). Maybe do this twice just in case. It should be better
My spec isn't showing up in autocomplete
Is autocomplete working? Try going to a new line in the terminal and typing git
or cd
plus a space.
If Fig pops up, autocomplete is working. Chances are it is a problem with your script. Make sure you have correct
If Fig doesn't pop up, autocomplete has crushed 😬. Click to the Fig Icon (◧) in the mac status bar (very top right of your screen near the battery percentage and time) -> Click Autocomplete
This Toggles autocomplete on and off and should make it work
If Fig still doesn't work, quit Fig and start again ( ◧ -> Quit Fig)
If Fig still doesn't work, message us in Slack or email hello@withfig.com
How else can I debug?
Type git
plus a space to show the autocomplete window. Right click the fig window, and click Inspect Element. Look at the console for errors.
Autocomplete is working but my script isn't showing
Chances are you have
Others Things to Know / General Advice
If you have a problem, message the founders
We are very responsive: Slack or email hello@withfig.com
Make sure to Include Args if relevant
Your suggestions will be really weird if you don't do this. Read the Arg Object section and ask for advice if confused.
If a subcommand / option takes an argument or arguments, include an Arg object, even if it is literally an empty object.
If a subcommand / option does not take an argument, do not include the args property!
This is very important!!!
File Format
Save your completion specs like [CLI Name].js
e.g.
git.js
orcd.js
File Location
Save your completion spec in the following folder: ~/.fig/autocomplete
Other
Your completion script must start with the root object defined as a variable called completionSpec
e.g.
var completionSpec = {...}
Last updated