TODO comments are in the source
This spec must be validated by implementing it in at least one library. I may do this in Haskell's optparse-applicative.
Considering that the auto completions for any program are highly coupled with the program, many libraries and programs implement some degree of shell auto- completion logic in the command's main executable. These include Python optcomplete, Nix's completion.sh and Haskell's optparse-applicative.
Each of these solutions implements some kind of protocol between the executable and a helper script. This leads to a situation where each combination of autocompletion library × shell variant needs to reimplement much of the same logic.
By formalizing the interface between the executable and the shell, both the executables and the shells only need to implement one interface.
When a shell requests completions through the ACES protocol, the following happens:
shell
-----
| --invokes-->
| wrapper script
| --------------
| | --invokes-->
| | main executable
| | ---------------
| | |
| | parse ACES command line
| | |
| | write completions in ACES format
| | <--stdout-- |
| reads exit 0
| |
| return completions
| to the shell
| <--commands, |
| <--stdout, etc. |
| exit
show completions
Shells may choose to avoid the wrapper script and implement the ACES protocol directly.
When the executable runs, it needs to know its context. This is provided through command line arguments. This is an implementation detail that the user of the executable need not be aware of.
--aces-completion-index INDEX
: this option signifies that the executable must not
perform its main role, but return possible completions using ACES. It takes
one base 10 integer argument (INDEX
) describing the argument where completions
are requested.
--aces-completion-argument ARG
: this option must be repeated for each of the
entered arguments.
--aces-*
: any other options with the prefix --aces-
must be ignored when
--aces-completion-index
is provided.
The ACES Stdout format is a custom line-based text format, in order to ease shell script based implementation, as most shells do not have good support for semi-structured formats.
The executable prints lines to stdout. It should print only a carriage return. Carriage returns should be ignored when reading the format.
Each line is either an instruction or a completion. Each completion must be
preceded by a %value
instruction line.
An instruction line consist of %
, an extension word and optionally:
- a space (
The extension word consists of a nonempty sequence of alphanumeric characters
and/or -
.
Instruction lines with an unknown instruction must be ignored by the shell.
Shells and libraries may independently agree on extensions that make use of
instruction lines. Such extensions should prefix the extension word with x-
;
e.g. %x-no-socket-highlight
.
Standard instruction words:
%value
: Indicates that the next line is a completion. The next line will be
read as a completion, even if it starts with %
.
%addspace
: Indicates that the following completion forms a complete argument.
The shell should add a space, to indicate that the argument is complete and to
help the user enter the next argument. This is different from an actual space
trailing the completion, because such a space should be escaped by the shell, in
order not to serve as an argument boundary.
%files
: Indicates that the following completion contains a file or directory
that the shell may highlight as such. The shell may append a /
if it determines
that the completion is a directory.
- ACES protocol: the entire protocol, including the process architecture
- ACES format: the format written to stdout
- ACES command line: the flags that are used by the executable to perform completion instead of the main program.
Prior art includes at least the unfinished ShellAC, which uses JSON. That could be a problem for implementing shims in most shells, which do not have suitable facilities for processing that language.