Bash and the readline library provide completion facilities, whereby you can type part of a command name, hit the Tab key, and Bash will fill in part or all of the rest of the command or filename. Programmable completion lets you, as a shell programmer, write code to customize the list of possible completions that Bash will present for a particular partially entered word. This is accomplished through the combination of several facilities:
The complete command allows you to provide a completion specification, or compspec, for individual commands. You specify, via various options, how to tailor the list of possible completions for the particular command. This is simple, but adequate for many needs. (See the entry for complete.)
For more flexibility, you can use complete -F
funcname
command
. This tells Bash to call funcname
to provide the list of completions for command.
You write the funcname function.
Within the code for a -F
function, the COMP*
shell variables provide information about the current command line.
COMPREPLY
is an array into which the function
places the final list of completion results.
Also within the code for a -F
function, you may
use the compgen command to generate a list of results, such as “usernames that
begin with a
” or “all set
variables.” The intent is that such results would be used with an
array assignment:
…
COMPREPLY=( $( compgen options arguments
) )
…
Compspecs may be associated with either a full pathname for a command or, more commonly, an unadorned command name (/usr/bin/man versus plain man). Completions are attempted in the following order, based on the options provided to the complete command:
If completion is attempted on an empty input line, Bash applies
the compspec given with complete -E
. Otherwise, it
proceeds to the next step.
Bash first identifies the command. If a pathname is used, Bash looks to see if a compspec exists for the full pathname. Otherwise, it sets the command name to the last component of the pathname, and searches for a compspec for the command name.
If a compspec exists, Bash uses it. If not, Bash uses the
“default” compspec given with complete -D
. If there
is none, then Bash falls back to the default built-in completions.
Bash performs the action indicated by the compspec to generate a
list of possible matches. Of this list, only those that have the word
being completed as a prefix are used for the list of possible
completions. For the -d
and -f
options, the variable FIGNORE
is used to filter out
undesirable matches.
Bash generates filenames as specified by the -G
option. GLOBIGNORE
is not used to filter the
results, but FIGNORE
is.
Bash processes the argument string provided to
-W
. The string is split using the characters in
$IFS
. The resulting list provides the candidates
for completion. This is often used to provide a list of options that a
command accepts.
Bash runs functions and commands as specified by the
-F
and -C
options. For both, Bash
sets COMP_LINE
and COMP_POINT
as
described in the section Built-in Shell Variables.
For a shell function, COMP_WORDS
and
COMP_CWORD
are also set.
Also, for both functions and commands, $1
is the name of the command whose
arguments are being completed, $2
is the word being completed, and $3
is the word in front of the word being completed. Bash does
not filter the results of the command or
function:
Functions named with -F
are run first. The
function should set the COMPREPLY
array to the
list of possible completions. Bash retrieves the list from
there.
Commands provided with -C
are run next, in
an environment equivalent to command substitution. The command
should print the list of possible completions, one per line. An
embedded newline should be escaped with a backslash.
Once the list is generated, Bash filters the results according
to the -X
option. The argument to -X
is a pattern specifying files to exclude. By prefixing the pattern
with a !
, the sense is reversed,
and the pattern instead specifies that only matching files should be
retained in the list.
An &
in the pattern is
replaced with the text of the word being completed. Use &
to produce a literal &
.
Finally, Bash prepends or appends any prefixes or suffixes
supplied with the -P
or -S
options.
In the case that no matches were generated, if -o dirnames
was used,
Bash attempts directory name completion.
On the other hand, if -o
plusdirs
was provided, Bash adds the
result of directory completion to the previously generated
list.
Normally, when a compspec is provided, Bash’s default completions are not attempted, nor are the readline library’s default filename completions:
If the compspec produces no results and -o bashdefault
was
provided, then Bash attempts its default completions.
If neither the compspec nor the Bash default completions
with -o bashdefault
produced
any results, and -o default
was
provided, then Bash has the readline library
attempt its filename completions.
A compspec may be modified with the compopt command. When used without command names inside an executing completion, it affects the executing completion.
When a shell function used as a completion handler returns 124, Bash
retries the completion process from the beginning. This is most useful
with the default completion handler (complete -D
) to dynamically build up a set
of completions instead of loading a
large set at startup. The bash(1) manpage has an
example at the end of its Programmable Completion section.
Ian Macdonald has collected a large set of useful compspecs, often distributed as the file /etc/bash_completion. If your system does not have it, you can download it at http://freshmeat.net/projects/bashcompletion/. It is worth reviewing.
Restrict files for the C compiler to C, C++ and assembler source files, and relocatable object files:
complete -f -X '!*.[Ccos]' gcc cc
For the man command, restrict expansions to things that have manpages:
# Simple example of programmable completion for manual pages. # A more elaborate example appears in bash_completion file. # Assumes man [num] command command syntax. shopt -s extglob # Enable extended pattern matching # Define completion function _man () { local dir mandir=/usr/share/man # Local variables COMPREPLY=( ) # Clear reply list if [[ ${COMP_WORDS[1]} = +([0-9]) ]] # Have section no. then # section provided: man 3 foo # look in specified directory dir=$mandir/man${COMP_WORDS[COMP_CWORD-1]} else # no section, default to commands # look in command directories dir=$mandir/'man[18]' fi COMPREPLY=( $( # Generate raw file list find $dir -type f | # Remove leading directories sed 's;..*/;;' | # Remove trailing suffixes sed 's/.[0-9].*$//' | # Keep those that match given prefix grep "^${COMP_WORDS[$COMP_CWORD]}" | # Sort final list sort ) ) } # Associate function with command complete -F _man man
3.14.253.152