Shell Auto-completion
Auto-completion
Shell autocompletion allows to suggest most relevant hints on hitting Tab
key, while typing a command line.
Auto-completion provided by nuclear
is enabled by default to all known keywords based on the declared subcommands and options.
Defining possible choices may imporove auto-completing arguments. You can declare explicit possible values list or a function which provides such a list at runtime.
completers.py:
#!/usr/bin/env python3
import re
from typing import List
from nuclear import CliBuilder, parameter, default_action
from nuclear.utils.shell import shell, shell_output
def list_screens() -> List[str]:
"""Return list of available screen names in a system"""
xrandr = shell_output('xrandr 2>/dev/null')
regex_matcher = re.compile(r'^([a-zA-Z0-9\-]+) connected(.*)')
return [regex_matcher.sub('\\1', line)
for line in xrandr.splitlines()
if regex_matcher.match(line)]
def adjust_screen(output: str, mode: str):
shell(f'xrandr --output {output} --mode {mode}')
CliBuilder('completers-demo').has(
parameter('output', choices=list_screens, required=True),
parameter('mode', choices=['640x480', '800x480', '800x600'], required=True),
default_action(adjust_screen),
).run()
In order to enable auto-completion, you need to install some extension to bash. Fortunately nuclear
has built-in tools to do that:
foo@bar:~$ sudo ./completers.py --install-bash completers-demo
[info] creating link: /usr/bin/completers-demo -> ~/nuclear/docs/example/completers.py
#!/bin/bash
_autocomplete_98246661() {
COMPREPLY=( $(completers-demo --autocomplete "${COMP_LINE}") )
}
complete -F _autocomplete_98246661 completers-demo
[info] Autocompleter has been installed in /etc/bash_completion.d/autocomplete_completers-demo.sh. Please restart your shell.
completers-demo
application installed in /usr/bin/
(symbolic link to the current script) and bash completion script installed as well.
We can hit [Tab]
key to complete command when typing. Here are some completions examples:
foo@bar:~$ completers-d[Tab]
foo@bar:~$ completers-demo
foo@bar:~$ completers-demo [Tab][Tab]
--autocomplete -h --mode --output
--install-bash --help --mode= --output=
foo@bar:~$ completers-demo --mo[Tab]
foo@bar:~$ completers-demo --mode
foo@bar:~$ completers-demo --mode [Tab][Tab]
640x480 800x480 800x600
foo@bar:~$ completers-demo --mode 640[Tab]
foo@bar:~$ completers-demo --mode 640x480
foo@bar:~$ completers-demo --mode 640x480 --output [Tab][Tab]
eDP-1 HDMI-1
Custom completers
You can provide your custom auto-completers (providers of possible values) to the choices
parameter.
The example is the function which returns a list of available screens:
def list_screens() -> List[str]:
"""Return list of available screen names in a system"""
xrandr = shell_output('xrandr 2>/dev/null')
regex_matcher = re.compile(r'^([a-zA-Z0-9\-]+) connected(.*)')
return [regex_matcher.sub('\\1', line)
for line in xrandr.splitlines()
if regex_matcher.match(line)]
CliBuilder().has(
parameter('output', choices=list_screens, required=True),
)
Installing Autocompletion
In order to enable the autocompletion, there must be a specific script in /etc/bash_completion.d/
.
With nuclear
you just need to run:
# sudo ./sample-app.py --install-bash sample-app
/usr/bin/
,
so as you can run your app with sample-app
command instead of ./sample_app.py
.
Now you can type sample-app
and hit Tab
to see what are the possible commands and options.
If you type sample-app --he
, it will automatically fill the only possible option: --help
.
Sometimes, you need to make some modifications in your code,
but after these modifications you will NOT need to reinstall autocompletion again.
You had to do it only once, because autocompletion script only redirects its query and run sample_app.py
:
sample-app --autocomplete "sample-app --he"
How does auto-completion work?
- While typing a command in
bash
, you hitTab
key. (your-app.py cmd[TAB]
) bash
looks for an autocompletion script in/etc/bash_completion.d/
. There should be a script installed for your command after running--install-bash
on your application. So when it's found, this script is called by bash.- The autocompletion script redirects to your application, running it with
--autocomplete
option, namely script runsyour-app.py --autocomplete "cmd"
, asking it for returning the most relevant command proposals. Notice that in that manner, the autocompletion algorithm is being run always in up-to-date version. your-app.py
has--autocomplete
option enabled by default so it starts to analyze which keyword from your CLI definition is the most relevant to the currently typed word (cmd
).- If you defined custom completers functions, they will be invoked right now (if needed) in order to get up-to-date proposals and analyze them as well.
your-app.py
returns a list of proposals to thebash
.bash
shows you these results. If there's only one matching proposal, the currently typed word is automatically filled.
Note that your application is being run each time when trying to get matching arguments proposals.