2

When I type evince, and then hit tab, the bash shell will list all files that can be opened by evince, which seems to be based on the ext part of the filename.

Is this done by shell or the application evince?

If former, how does the shell know what the application needs?

4
  • Have a look at the contents of /usr/share/bash-completion/completions/...
    – jasonwryan
    Commented Sep 10, 2014 at 2:44
  • mine is /etc/bash_completion. I also have /etc/bash_completion.d/. what are their differences?
    – Tim
    Commented Sep 10, 2014 at 3:10
  • The full list of completion scripts should be in /usr/share... but it may vary on some distros. Packages that install their own completions tend to drop them in /etc/bash_completion.d/
    – jasonwryan
    Commented Sep 10, 2014 at 3:17
  • here you find an answer of how to add auto completion to your scripts unix.stackexchange.com/q/489235/240990
    – nath
    Commented Aug 15, 2019 at 11:58

1 Answer 1

2

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .