All features work in bash and zsh, apart from one: In zsh the autocompletions can additionally use description labels, which aren't supported in bash.
The core of the script is a config parser developed in AWK. It is embedded in the shell script and can be exported for delepment purposes as described below.
All used variables begin with __CLI_
All but __CLI_VERSION
, __CLI_AWK_SCRIPT
and __CLI_PROGNAME
are initialized during completion and command execution
To list them all you can use the shell builtin compgen in bash (and zsh with loaded bash completion support, see README.md
)
compgen -A variable | grep ^__CLI_
All functions begin with _cli_
Functions are loaded by sourcing the cli script
Registered completion functions can be listed by calling complete without arguments
$ complete | grep ^_cli
Serves multiple purposes:
- flattens the tree to one line per command for the shell script
- is used to query for commands and their arguments
- exports argument completion environment vars to the CLI script
- is used to query for command help texts
- extracts the [env] content from the config file
For development of the embedded AWK script I use this cycle:
-
Export the AWK script
$ cli --cli-print-awk-script > cli.awk
-
Edit cli.awk
-
Test run
$ awk -f cli awk output=commands command_filter=""
-
Run syntax check
$ awk --lint -f cli.awk
-
If everything is good, copy the script to mouse buffer
$ cat cli.awk | xclip
-
Edit CLI file to embed the new AWK script search for AWK_EOF remove old script paste the mouse buffer with middle click
To run the embedded awk script it can be executed like shown below. The script parameters are described in the comments in the script header.
$ cli --cli-run-awk-script output=command_names
I use shellcheck to find sources of uninteded errors.
$ shellcheck cli.sh
Latency is important. It makes your computer feel slow or quick. It may sound obvious, but it's very very important for a good user experience.
Therefore, in auto completion functons, do not, unless absolutely necessary
- use subshells
- call external programs
Script execution time of 400 ms definitely makes it feel sluggish
- About 200ms is OK
- 100ms is good
- <100ms is very good
time it with the time
command
$ time <yourcli> <yourcommand>
strace -c $YOUR_CLI_COMMAND
Run bats test with the following command after checking out submodules
test/bats/bin/bats test/test.bats
Arguments and command names which the user provided are completed or expanded to a matching valid word, if there is an unambiguous match for the word position.
I use 'expand' instead of 'complete' in variable and function naming to differentiate between auto completion during typing and expansion of submitted commands for execution, to allow abbreviation of commands.
$ cli --cli-run-awk-command output=commands command_filter="filter bla rating"
__COMMAND=filter bla rating
__COMMAND_ARG[0]="list:lt|le|qe|gt|ge:comparison operator"
__COMMAND_ARG[1]="int_range:1-5:rating value to compare against"
$ cli --cli-run-awk-command output=commands command_filter="set comment"
__COMMAND=set comment
__COMMAND_ARG[0]="INTEGER"
__COMMAND_ARG[1]="STRING"
$ cli --cli-run-awk-command output="command_names"