mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-20 05:53:52 +01:00
270 lines
8.4 KiB
Plaintext
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
|