rdiff-backup complete [--cword <index>] [--unique|--no-unique] -- <words...>
Home Architecture // Programmatic Completion
Using the complete
action of rdiff-backup, one can quite easily write a shell completion script.
It shouldn’t require to analyze all possible completions because rdiff-backup itself is doing the analysis.
The completion "glue" for each shell only needs to prepare the results.
Note
|
the code has been written with 'bash' as guinea pig for the approach. The expectation is that the programmatic completion of other shells will have similar requirements and facilities. Should this prove wrong, additional requirements are welcome as enhancement issue. |
The principle is rather simple:
one calls rdiff-backup complete
with the current arguments entered by the user on the command line, and rdiff-backup outputs a list of possible completions.
The completion script then only needs to use this list as required by the shell.
rdiff-backup complete [--cword <index>] [--unique|--no-unique] -- <words...>
The 'words' are the words on the command line as currently entered by the user. The 'cword' option represents the zero-based index where the cursor of the user is currently placed.
$ rdiff-backup --verb⌷
(the ⌷
represents the user’s cursor when they triggers the completion, e.g. with <TAB><TAB> under bash)
rdiff-backup complete --cword 1 -- rdiff-backup --verb
--verbosity
$ rdiff-backup --verbosity ⌷
(notice the blank between verbosity and cursor)
rdiff-backup complete --cword 2 -- rdiff-backup --verbosity ''
(notice accordingly the empty last word)
a list of integers from 0 to 10 as possible parameter for --verbosity
$ rdiff-backup --verbosity⌷ 5
rdiff-backup complete --cword 1 -- rdiff-backup --verbosity 5
(notice the cword pointing at --verbosity
)
--verbosity
again
Important
|
the double minus -- is absolutely required to avoid that the words are interpreted as options of the complete action.
|
Finally the --unique
/--no-unique
option toggles if the returned completion values should return values already entered on the command line.
By default options are considered unique (see Limitations on this topic).
In the current stage, the returned completion values might be a mixture of old and new CLI options, as long as rdiff-backup doesn’t have enough information to differentiate them.
In all cases, the possible completion values are returned on stdout with one possible value on each line. The values are considered pre-sorted and shouldn’t be sorted by the completion script/toolset, but this decision remains to the judgement of the script’s author.
Important is that the last option in the list might have a specific meaning, and the special format ::action::.
Currently there is only one possible action, and it is file
.
This action means that the completion script should remove this one option, and replace it with the list of files which could be used to complete the command line.
$ rdiff-backup backup D⌷
rdiff-backup complete --cword 2 -- rdiff-backup backup D
::file::
.
It would be the responsibility of the completion script to replace it (for example) with Desktop
, Documents
and Downloads
.
Tip
|
the bash built-in command complete resp. compgen offers the option -A file to do this.
In our example, calling compgen -A file D in a typical Linux home drive would exactly return the three directories listed above.
|
$ rdiff-backup backup ⌷
rdiff-backup complete --cword 2 -- rdiff-backup backup ''
(without first letter D)
all possible backup options followed by the said ::file::
option, i.e. something like:
--acls --carbonfile [...] --resource-forks --user-mapping-file ::file::
Some options, like --user-mapping-file
, followed by a filename would similarly trigger the output of the ::file::
parameter.
The default value for cword
is -1, meaning the last word of the list.
This is a rather sensitive approach should there be a shell completion not supporting this parameter.
By default all parameters are considered 'unique' and only offered once to the user as completion.
This limitation is due to the author’s reluctance to have an algorithm based on intrinsic knowledge of the options' semantic.
As the actions ('backup', 'compare', etc…) are actually plugins, the complete
action plugin shouldn’t rely on knowing how to use their options, as this approach would break with each new plug-in.
Despite the above stated lack of knowledge about options' semantic, some assumptions are made, which could be broken if care isn’t taken:
an option which has a 'type' which isn’t a boolean is followed by a parameter
if this kind of option has 'choices', those are output by complete
if there is no choice but a type FileType
or 'str' with additionally a 'metavar' ending in _FILE
, then the option is deemed having a file as parameter
arguments called locations
are supposed to represent a list of files (or directories).
Note
|
it shouldn’t be the worry of the completion script’s author to make sure that those assumptions are kept true. |
There is no reasonable way to help the user with completion if the locations are remote, so we always assume "local" locations and expect files/directories represented by the ::file::
placeholder.
The exact number of possible locations/files isn’t really validated, just cursorily checked.
The options are sorted by ignoring the hyphens, this means that actions and options are mixed.
It should be pretty simple in most cases, if you know how to create a fork and a pull request against rdiff-backup’s Git repo:
add a subdirectory and script to tools/completions
, e.g. bash/rdiff-backup
(the script must have its definitive name on the file system, hence the sub-directory)
add an entry of the form "<relative-target-directory>" = ["tools/completions/myshell/myscript"]
in the [tool.setuptools.data-files]
section of the pyproject.toml
file.
Take the already existing bash entry "share/bash-completion/completions" = ["tools/completions/bash/rdiff-backup"]
as sample.
That’s it, test (e.g. using pip install .
), commit and push, a pull request is then just a click or two away.