mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-11 00:51:05 +02:00
221 lines
6.9 KiB
Text
221 lines
6.9 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 a underscores (like `_setopt).
|
|
# The first line of these files will be read and has to say what should be
|
|
# done with its contents:
|
|
#
|
|
# `#defcomp <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
|
|
#
|
|
# `#defpatcomp <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
|
|
#
|
|
# `#defkeycomp <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.
|
|
#
|
|
# `#autoload'
|
|
# 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.
|
|
#
|
|
# See the file `dump' for how to speed up initialiation.
|
|
|
|
# If we got the `-d'-flag, we will automatically dump the new state (at
|
|
# the end).
|
|
|
|
if [[ "$1" = -d ]]; then
|
|
_i_autodump=1
|
|
else
|
|
_i_autodump=0
|
|
fi
|
|
|
|
# The associative array containing the definitions for the commands.
|
|
# Definitions for patterns will be stored in the normal array `patcomps'.
|
|
|
|
typeset -A comps
|
|
|
|
|
|
# This may be used to define completion handlers. The first argument is the
|
|
# name of the function 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
|
|
|
|
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
|
|
# 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"
|
|
fi
|
|
name="$1"
|
|
shift
|
|
zle -C "$name" "$1" "$name"
|
|
shift
|
|
while (( $# )); do
|
|
bindkey "$1" "$name"
|
|
shift
|
|
done
|
|
}
|
|
|
|
# This searches $1 in the array for normal completions and calls the result.
|
|
|
|
_compalso() {
|
|
local tmp
|
|
|
|
tmp="$comps[$1]"
|
|
[[ -z "$tmp" ]] || "$tmp" "$@"
|
|
}
|
|
|
|
# These can be used to easily save and restore the state of the special
|
|
# variables used by the completion code.
|
|
|
|
alias _compsave='local _oprefix$_level _oiprefix$_level _oargv$_level _ocurrent$_level _ocommand$_level _ocontext$_level; \
|
|
eval "_oprefix${_level}=\"\$PREFIX\"; \
|
|
_oiprefix${_level}=\"\$IPREFIX\"; \
|
|
_oargv${_level}=( \"\$@\" ); \
|
|
_ocurrent${_level}=\"\$CURRENT\"; \
|
|
_ocommand${_level}=\"\$COMMAND\"; \
|
|
_ocontext${_level}=\"\$CONTEXT\""'
|
|
alias _compreset='eval "PREFIX=\"\$_oprefix${_level}\"; \
|
|
IPREFIX=\"\$_oiprefix${_level}\"; \
|
|
argv=( \"\$_oargv${_level}[@]\" ); \
|
|
CURRENT=\"\$_ocur${_level}\"; \
|
|
COMMAND=\"\$_ocommand${_level}\"; \
|
|
CONTEXT=\"\$_ocontext${_level}\""'
|
|
|
|
# These can be used to build tests that modify the special parameters
|
|
# without having to reset them by hand.
|
|
|
|
alias _if='(( $+_level )) || local _level=0; (( _level++ )); _compsave; if'
|
|
alias _elif='_compreset; elif'
|
|
alias _else='_compreset; else'
|
|
alias _fi='_compreset; fi; unset _oprefix$_level _oiprefix$_level _oargv$_level _ocurrent$_level _ocommand$_level _ocontext$_level; (( _level-- ))'
|
|
|
|
|
|
# Now we automatically make the definition files autoloaded.
|
|
|
|
# First we get the name of a dump file if this will be used.
|
|
|
|
: ${COMPDUMP:=$0.dump}
|
|
|
|
_i_files=( ${^~fpath}/_*~*~ )
|
|
_i_initname=$0
|
|
_i_done=''
|
|
|
|
# If we have a dump file, load it.
|
|
|
|
if [[ -f "$COMPDUMP" ]]; then
|
|
read -rA _i_line < "$COMPDUMP"
|
|
if [[ _i_autodump -eq 1 || $_i_line[2] -eq $#_i_files ]]; then
|
|
builtin . "$COMPDUMP"
|
|
_i_done=yes
|
|
fi
|
|
unset _i_line
|
|
fi
|
|
if [[ -z "$_i_done" ]]; then
|
|
|
|
for _i_dir in $fpath; do
|
|
[[ $_i_dir = . ]] && continue
|
|
for _i_file in $_i_dir/_*~*~(N); do
|
|
read -rA _i_line < $_i_file
|
|
_i_tag=$_i_line[1]
|
|
shift _i_line
|
|
if [[ $_i_tag = '#defcomp' ]]; then
|
|
defcomp -a ${_i_file:t} "${_i_line[@]}"
|
|
elif [[ $_i_tag = '#defpatcomp' ]]; then
|
|
defpatcomp -a "${_i_file:t}" "${_i_line[@]}"
|
|
elif [[ $_i_tag = '#defkeycomp' ]]; then
|
|
defkeycomp -a "${_i_file:t}" "${_i_line[@]}"
|
|
elif [[ $_i_tag = '#autoload' ]]; then
|
|
autoload ${_i_file:t}
|
|
fi
|
|
done
|
|
done
|
|
|
|
bindkey |
|
|
while read -rA _i_line; do
|
|
if [[ "$_i_line[2]" = complete-word ||
|
|
"$_i_line[2]" = delete-char-or-list ||
|
|
"$_i_line[2]" = expand-or-complete ||
|
|
"$_i_line[2]" = expand-or-complete-prefix ||
|
|
"$_i_line[2]" = list-choices ||
|
|
"$_i_line[2]" = menu-complete ||
|
|
"$_i_line[2]" = menu-expand-or-complete ||
|
|
"$_i_line[2]" = reverse-menu-complete ]]; then
|
|
zle -C _complete_$_i_line[2] $_i_line[2] _main_complete
|
|
bindkey "${_i_line[1][2,-2]}" _complete_$_i_line[2]
|
|
fi
|
|
done
|
|
|
|
unset _i_dir _i_line _i_file _i_tag
|
|
|
|
# if autodumping was requested, do it now.
|
|
|
|
(( _i_autodump )) && builtin . ${_i_initname:h}/dump
|
|
fi
|
|
|
|
unset _i_files _i_initname _i_done _i_autodump
|