Programmable Completion

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:

  1. If completion is attempted on an empty input line, Bash applies the compspec given with complete -E. Otherwise, it proceeds to the next step.

  2. 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.

  3. 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.

  4. 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.

  5. Bash generates filenames as specified by the -G option. GLOBIGNORE is not used to filter the results, but FIGNORE is.

  6. 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.

  7. 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:

    1. 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.

    2. 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.

  8. 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 &.

  9. Finally, Bash prepends or appends any prefixes or suffixes supplied with the -P or -S options.

  10. In the case that no matches were generated, if -o dirnames was used, Bash attempts directory name completion.

  11. On the other hand, if -o plusdirs was provided, Bash adds the result of directory completion to the previously generated list.

  12. Normally, when a compspec is provided, Bash’s default completions are not attempted, nor are the readline library’s default filename completions:

    1. If the compspec produces no results and -o bashdefault was provided, then Bash attempts its default completions.

    2. 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.

Examples

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
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.253.152