diff options
author | Tanaka Akira <akr@users.sourceforge.net> | 1999-04-15 18:05:38 +0000 |
---|---|---|
committer | Tanaka Akira <akr@users.sourceforge.net> | 1999-04-15 18:05:38 +0000 |
commit | e74702b467171dbdafb56dfe354794a212e020d9 (patch) | |
tree | c295b3e9b2e93e2de10331877442615b0f37e779 /Functions/Completion/init | |
parent | c175751b501a3a4cb40ad4787340a597ea769be4 (diff) | |
download | zsh-e74702b467171dbdafb56dfe354794a212e020d9.tar.gz zsh-e74702b467171dbdafb56dfe354794a212e020d9.tar.xz zsh-e74702b467171dbdafb56dfe354794a212e020d9.zip |
Initial revision
Diffstat (limited to 'Functions/Completion/init')
-rw-r--r-- | Functions/Completion/init | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/Functions/Completion/init b/Functions/Completion/init new file mode 100644 index 000000000..a40c5f61b --- /dev/null +++ b/Functions/Completion/init @@ -0,0 +1,253 @@ +# Initialisation for new style completion. This mainly contains some helper +# function and aliases. Everything else is split into different files in this +# directory that will automatically be made autoloaded (see the end of this +# file). +# The names of the files that will be considered for autoloading have to +# start with two underscores (like `__setopt). +# The first line of these files will be read and has to say what should be +# done with its contents: +# +# `#function <names ...>' +# if the first line looks like this, the file is +# autoloaded as a function and that function will +# be called to generate the matches when completing +# for one of the commands whose <name> is given +# +# `#array <names ...>' +# with a first line like this, the filename is taken as +# the name of an array; when trying to generate matches +# for the command <name>, the file will be sourced and +# should define this array, the builtin `complist' will +# then be called with the elements of this array as its +# arguments; this is intended for simple definitions +# for which you don't need a shell function +# +# `#pattern-function <pattern>' +# this defines a function that should be called to generate +# matches for commands whose name matches <pattern>; note +# that only one pattern may be given +# +# `#pattern-array <pattern>' +# like `#pattern-function' but defining an array +# +# `#key-function <style> [ <key-sequence> ... ] +# this is used to bind special completions to all the given +# <key-sequence>(s). The <style> is the name of one of the built-in +# completion widgets (complete-word, delete-char-or-list, +# expand-or-complete, expand-or-complete-prefix, list-choices, +# menu-complete, menu-expand-or-complete, or reverse-menu-complete). +# This creates a widget behaving like <style> so that the +# completions are chosen as given in the the rest of the file, +# rather than by the context. The widget has the same name as +# the autoload file and can be bound using bindkey in the normal way. +# +# `#key-array <style> [ <key-sequence> ... ] +# like `#key-function', but defining an array instead +# +# `#helper' +# this is for helper functions that are not used to +# generate matches, but should automatically be loaded +# when they are called +# +# Note that no white space is allowed between the `#' and the rest of +# the string. + + +# An associative array for completions definitions. The keys of the entries +# are the names of the command, the values are names of functions or variables +# that are to be used to generate the matches. +# Pattern completions will be stored in an normal array named `patcomps'. +# Completion definitions bound directly to keys are stored in an assoc array +# named `keycomps'. + +typeset -A comps +typeset -A keycomps + + +# This may be used to define completion handlers. The first argument is the +# name of the function or variable containing the definition, the other +# arguments are the command names for which this definition should be used. +# With only one argument the function/variable-name __$1 is used. +# If given the `-a' option, the function is defined as being autoloaded. + +defcomp() { + local name autol='' + + if [[ "$1" = -a ]]; then + shift + autol=yes + fi + if [[ $# -eq 1 ]]; then + comps[$1]="__$1" + [[ -z "$autol" ]] || autoload "__$1" + else + name="$1" + shift + for i; do + comps[$i]="$name" + done + [[ -z "$autol" ]] || autoload "$name" + fi +} + + +# Almost like `defcomp', but this always gets two arguments: the name of a +# variable or function describing what should be completed and the pattern +# that will be compared to the command names for which completion is attempted. + +defpatcomp() { + if [[ "$1" = -a ]]; then + shift + autoload "$1" + fi + if (( $+patcomps )) then + patcomps=("$patcomps[@]" "$2 $1" ) + else + patcomps=( "$2 $1" ) + fi +} + + +# This is used to define completion handlers directly bound to keys. The +# first argument is as for `defcomp', giving the handler. The second +# argument is the name of one of the built-in completion widgets. Any +# remaining arguments are used as key sequences to bind the widget. +# Typing that key sequence will complete the word the cursor is on +# according to the completion definition given and will behave as if the +# built-in completion widget was used. + +defkeycomp() { + local name + + if [[ "$1" = -a ]]; then + shift + autoload "$1" + name="$1" + elif [[ "${1[1]}" = ' ' ]]; then + name="${1:t}" + else + name="$1" + fi + keycomps[$name]="$1" + shift + zle -C "$name" "$1" __main_key_complete + shift + while (( $# )); do + bindkey "$1" "$name" + shift + done +} + +# These can be used to easily save and restore the state of the special +# variables used by the completion code. + +alias compsave='local _oprefix _oiprefix _oargv _ocurrent; \ + _oprefix="$PREFIX"; \ + _oiprefix="$IPREFIX"; \ + _oargv=( "$@" ); \ + _ocurrent="$CURRENT"' +alias compreset='PREFIX="$_oprefix"; \ + IPREFIX="$_oiprefix"; \ + argv=( "$_oargv[@]" ); \ + CURRENT="$_ocur"' + + +# This is an easy way to get completion for sub-commands. + +alias compsub='__normal "$@" || return 1' + + +# This searches $1 in the array for normal completions and calls the result. + +compalso() { + local tmp + + tmp="$comps[$1]" + [[ -z "$tmp" ]] || callcomplete comps "$1" "$@" +} + + +# This generates matches. The first argument is the name of one of the +# arrays containing completion definitions. The second argument is the index +# into this array. The other arguments are the positional parameters to give +# to the completion function (containing the arguments from the command line). + +callcomplete() { + local file def + + # Get the definition from the array. + + eval "def=\$${1}[${2}]" + + # If the definition starts with a space then this means that we should + # source a file to get the definition for an array. + + if [[ "$def[1]" = ' ' ]]; then + # The definition starts with a space, so source the file and change + # the definition. + + file="$def[2,-1]" + builtin . "$file" + def="${file:t}" + eval "${1}[${2}]=$def" + fi + + # Get rid of the array-name and -index. + + shift 2 + if [[ ${(P)+def} -eq 1 ]]; then + # It is a parameter name, call complist directly. + + complist "${(@P)def}" + else + # Otherwise it's a function name, call this function. + + "$def" "$@" + fi +} + + +# Now we make the files automatically autoloaded. + +local dir file line func + +for dir in $fpath; do + [[ $dir = . ]] && continue + for file in $dir/__*~*~(N); do + read -rA line < $file + func=$line[1] + shift line + if [[ $func = '#function' ]]; then + defcomp -a ${file:t} "${line[@]}" + elif [[ $func = '#array' ]]; then + defcomp " $file" "${line[@]}" + elif [[ $func = '#pattern-function' ]]; then + defpatcomp -a ${file:t} "${line[@]}" + elif [[ $func = '#pattern-array' ]]; then + defcomp " $file" "${line[@]}" + elif [[ $func = '#key-function' ]]; then + defkeycomp -a "${file:t}" "${line[@]}" + elif [[ $func = '#key-array' ]]; then + defkeycomp " $file" "${line[@]}" + elif [[ $func = '#helper' ]]; then + autoload ${file:t} + fi + done +done + + +# Finally we make all this be called by changing the key bindings. + +bindkey | while read -A line; do + if [[ "$line[2]" = complete-word || + "$line[2]" = delete-char-or-list || + "$line[2]" = expand-or-complete || + "$line[2]" = expand-or-complete-prefix || + "$line[2]" = list-choices || + "$line[2]" = menu-complete || + "$line[2]" = menu-expand-or-complete || + "$line[2]" = reverse-menu-complete ]]; then + zle -C __complete_$line[2] $line[2] __main_complete + bindkey "${line[1][2,-2]}" __complete_$line[2] + fi + done |