Runs in shell
There are two separate questions here:
Where is the completion implemented, and
Which other software component does it belong to.
The implementation of completion is interacting closely with the command line editor, which is part of the shell; It basically needs to run in the shell.
A large part of the completion is implemented as shell functions in most shells;
Separate package
You asked whether it is somehow part of the application, or part of the shell;
In practice, it is neither the first nor the second actually, but independent.
Most completions under Ubuntu are in the separate package bash-completion
,
a large collection of the completions you might expect.
Is not part of bash, but managed and released independently.
Code
Let's take a look at your completion example for evince
:
$ apt-file list bash-completion | grep evince
bash-completion: /usr/share/bash-completion/completions/evince
$ ls -l /usr/share/bash-completion/completions/evince
-rw-r--r-- 1 root root 967 Apr 7 16:10 /usr/share/bash-completion/completions/evince
Interesting! We did not need to look for something general like completion for PDF viewers, but found something directly related to evince
.
The file contains a shell function implementation; Part of it consists of string constants that describe how evince
can be used on the command line - the most interesting parts of /usr/share/bash-completion/completions/evince
are:
_evince() {
[ ... ]
case $prev in --gdk-no-debug|--gtk-module|--gtk-debug|--gtk-no-debug|\
-p|--page-label|-i|--page-index|-l|--find|--display)
[ ... ]
_filedir '@(@(?(e)ps|?(E)PS|[pf]df|[PF]DF[...]|bmp|xpm|ico|xwd|tga|pcx)'
[ ... ]
It describes general options like --gtk-debug
, application speciffic options like --page-label
, and lists file name extensions that can be handeled by evince
like .eps
and .pdf
.
Hands on
You can show functions defined in the current shell with the declare
builtin. If you try that in a new shell, you get an error message:
$ declare -f -p _evince
bash: declare: _evince: not found
Assuming the package bash-completion
is installed, this just meas that the function in not yet loaded.
Because there are a large number of functions like this, and in one interactive shell session, only a few are used, it makes sense to only load functions when they are really needed, instead of loading all at startup.
To get the function loaded, we try to use it, by using the evince
completion. With the cursor at the location of |
, press the Tab key;
$ evince -|<TAB>
There may be some completion shown. Now, the function should be loaded, and look like in the file above if we print it:
$ declare -f -p _evince
To list all function names, or see all functions that are currently loaded - including ones that are unrelated to completion, use:
$ declare -F | less
$ declare -f | less
/usr/share/bash-completion/completions/
.../etc/bash_completion
. I also have/etc/bash_completion.d/
. what are their differences?/usr/share...
but it may vary on some distros. Packages that install their own completions tend to drop them in/etc/bash_completion.d/