mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-07-25 21:31:03 +02:00
253 lines
7.7 KiB
Text
253 lines
7.7 KiB
Text
# 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
|