1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-11-20 05:53:52 +01:00
zsh/Completion/Core/compinit
1999-04-15 18:05:38 +00:00

270 lines
8.4 KiB
Plaintext

# 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 `compdump' for how to speed up initialiation.
#
# If you are using global matching specifications with `compctl -M ...'
# have a look at the files `_match_test' and `_match_pattern'. To make
# all the example functions use matching as specified with `-M' these
# need some editing.
#
# 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
_patcomps=()
# This function is used to register or delete completion functions. For
# registering completion functions, it is invoked with the name of the
# function as it's first argument (after the options). The other
# arguments depend on what type of completion function is defined. If
# none of the `-p' and `-k' options is given a function for a command is
# defined. The arguments after the function name are then interpreted as
# the names of the command for which the function generates matches.
# With the `-p' option a function for a name pattern is defined. This
# function will be invoked when completing for a command whose name
# matches the pattern given as argument after the function name (in this
# case only one argument is accepted).
# With the `-k' option a function for a special completion keys is
# defined and immediatly bound to those keys. Here, the extra arguments
# are the name of one of the builtin completion widgets and any number
# of key specifications as accepted by the `bindkey' builtin.
# In any case the `-a' option may be given which makes the function
# whose name is given as the first argument be autoloaded. When defining
# a function for command names the `-n' option may be given and keeps
# the definitions from overriding any previous definitions for the
# commands.
# For deleting definitions, the `-d' option must be given. Without the
# `-p' option, this deletes definitions for functions for the commands
# whose names are given as arguments. If combined with the `-p' option
# it deletes the definitions for the patterns given as argument.
# The `-d' option may not be combined with the `-k' option, i.e.
# definitions for key function can not be removed.
#
# Examples:
#
# compdef -a foo bar baz
# make the completion for the commands `bar' and `baz' use the
# function `foo' and make this function be autoloaded
#
# compdef -p foo 'c*'
# make completion for all command whose name begins with a `c'
# generate matches by calling the function `foo' before generating
# matches defined for the command itself
#
# compdef -k foo list-choices '^X^M' '\C-xm'
# make the function `foo' be invoked when typing `Control-X Control-M'
# or `Control-X m'; the function should generate matches and will
# behave like the `list-choices' builtin widget
#
# compdef -d bar baz
# delete the definitions for the command names `bar' and `baz'
compdef() {
local opt autol type func delete new i
# Get the options.
while getopts "anpkd" opt; do
case "$opt" in
a) autol=yes;;
n) new=yes;;
[pk]) if [[ -n "$type" ]]; then
# Error if both `-p' and `-k' are given (or one of them
# twice).
echo "$0: type already set to $type"
return 1
fi
if [[ "$opt" = p ]]; then
type=pattern
else
type=key
fi
;;
d) delete=yes;;
esac
done
shift OPTIND-1
if [[ -z "$delete" ]]; then
# Adding definitions, first get the name of the function name
# and probably do autoloading.
func="$1"
[[ -n "$autol" ]] && autoload "$func"
shift
case "$type" in
pattern)
if [[ $# -gt 1 ]]; then
echo "$0: only one pattern allowed"
return 1
fi
# Patterns are stored in strings like `c* foo', with a space
# between the pattern and the function name.
_patcomps=("$_patcomps[@]" "$1 $func")
;;
key)
if [[ $# -lt 2 ]]; then
echo "$0: missing keys"
return 1
fi
# Define the widget.
zle -C "$func" "$1" "$func"
shift
# And bind the keys...
for i; do
bindkey "$i" "$func"
done
;;
*)
# For commands store the function name in the `_comps'
# associative array, command names as keys.
for i; do
[[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
done
;;
esac
else
# Handle the `-d' option, deleting.
case "$type" in
pattern)
# Note the space.
for i; do
_patcomps=("${(@)patcomps:#$i *}")
done
;;
key)
# Oops, cannot do that yet.
echo "$0: cannot restore key bindings"
return 1
;;
*)
# Deleting definitons for command is even simpler.
for i; do
unset "_comps[$i]"
done
esac
fi
}
# 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}
if [[ ! -o extendedglob ]]; then
_i_noextglob=yes
setopt extendedglob
fi
typeset -U _i_files
_i_files=( ${^~fpath}/_*~*~(N:t) )
_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
compdef -na "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#defpatcomp' ]]; then
compdef -pa "${_i_file:t}" "${_i_line[@]}"
elif [[ $_i_tag = '#defkeycomp' ]]; then
compdef -ka "${_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}/compdump
fi
[[ -z "$_i_noextglob" ]] || unsetopt extendedglob
unset _i_files _i_initname _i_done _i_autodump _i_noextglob