summaryrefslogtreecommitdiff
path: root/Completion/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Core')
-rw-r--r--Completion/Core/.distfiles5
-rw-r--r--Completion/Core/_approximate197
-rw-r--r--Completion/Core/_comp_parts147
-rw-r--r--Completion/Core/_compalso13
-rw-r--r--Completion/Core/_complete52
-rw-r--r--Completion/Core/_correct19
-rw-r--r--Completion/Core/_expand149
-rw-r--r--Completion/Core/_files26
-rw-r--r--Completion/Core/_list61
-rw-r--r--Completion/Core/_main_complete48
-rw-r--r--Completion/Core/_match53
-rw-r--r--Completion/Core/_multi_parts201
-rw-r--r--Completion/Core/_normal54
-rw-r--r--Completion/Core/_options5
-rw-r--r--Completion/Core/_parameters8
-rw-r--r--Completion/Core/_path_files311
-rw-r--r--Completion/Core/_sep_parts171
-rw-r--r--Completion/Core/_set_options7
-rw-r--r--Completion/Core/_unset_options7
-rw-r--r--Completion/Core/compdump89
-rw-r--r--Completion/Core/compinit269
21 files changed, 1892 insertions, 0 deletions
diff --git a/Completion/Core/.distfiles b/Completion/Core/.distfiles
new file mode 100644
index 000000000..ddf2a707e
--- /dev/null
+++ b/Completion/Core/.distfiles
@@ -0,0 +1,5 @@
+DISTFILES_SRC='
+ .distfiles
+ _compalso _files _main_complete _multi_parts _normal _path_files
+ _sep_parts compdump compinit
+'
diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate
new file mode 100644
index 000000000..1b40f7cbf
--- /dev/null
+++ b/Completion/Core/_approximate
@@ -0,0 +1,197 @@
+#autoload
+
+# This code will try to correct the string on the line based on the
+# strings generated for the context if `compconfig[correct]' is set.
+# These corrected strings will be shown in a list and one can
+# cycle through them as in a menucompletion or get the corrected prefix.
+#
+# Supported configuration keys:
+#
+# approximate_accept
+# This should be set to a number, specifying the maximum number
+# of errors that should be accepted. If the string also contains
+# a `n' or `N', the code will use the numeric argument as the
+# maximum number of errors if a numeric argument was given. If no
+# numeric argument was given, the number from the value of this
+# key will be used. E.g. with `compconf approximate_accept=2n' two
+# errors will be accepted, but if the user gives another number
+# with the numeric argument, this will be prefered. Also, with
+# `compconf approximate_accept=0n', normally no correction will be
+# tried, but if a numeric argument is given, automatic correction
+# will be used. On the other hand, if the string contains an `!'
+# and a `n' or `N', correction is not attempted if a numeric
+# argument is given. Once the number of errors to accept is
+# determined, the code will repeatedly try to generate matches by
+# allowing one error, two errors, and so on. Independent of the
+# number of errors the user wants to accept, the code will allow
+# only fewer errors than there are characters in the string from
+# the line.
+#
+# approximate_original
+# This value is used to determine if the original string should
+# be included in the list (and thus be presented to the user when
+# cycling through the corrections). If it is set to any non-empty
+# value, the original string will be offered. If it contains the
+# sub-string `last', the original string will appear as the last
+# string when cycling through the corrections, otherwise it will
+# appear as the first one (so that the command line does not
+# change immediately). Also, if the value contains the sub-string
+# `always', the original string will always be included, whereas
+# normally it is included only if more than one possible
+# correction was generated.
+#
+# approximate_prompt
+# This can be set to a string that should be printed before the
+# list of corrected strings when cycling through them. This string
+# may contain the control sequences `%n', `%B', etc. known from
+# the `-X' option of `compctl'. Also, the sequence `%e' will be
+# replaced by the number of errors accepted to generate the
+# corrected strings.
+#
+# approximate_insert
+# If this is set to a string starting with `unambig', the code
+# will try to insert a usable unambiguous string in the command
+# line instead of always cycling through the corrected strings.
+# If such a unambiguous string could be found, the original
+# string is not used, independent of the setting of
+# `approximate_original'. If no sensible string could be found,
+# one can cycle through the corrected strings as usual.
+#
+# If any of these keys is not set, but the the same key with the
+# prefix `correct' instead of `approximate' is set, that value will
+# be used.
+
+local _comp_correct _correct_prompt comax
+local cfgacc cfgorig cfgps cfgins
+
+# Only if all global matchers hav been tried.
+
+[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
+
+# We don't try correction if the string is too short.
+
+[[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
+
+# Get the configuration values, using either the prefix `correct' or
+# `approximate'.
+
+if [[ "$compstate[pattern_match]" = (|\**) ]]; then
+ cfgacc="${compconfig[approximate_accept]:-$compconfig[correct_accept]}"
+ cfgorig="${compconfig[approximate_original]:-$compconfig[correct_original]}"
+ cfgps="${compconfig[approximate_prompt]:-$compconfig[correct_prompt]}"
+ cfgins="${compconfig[approximate_insert]:-$compconfig[correct_insert]}"
+else
+ cfgacc="$compconfig[correct_accept]"
+ cfgorig="$compconfig[correct_original]"
+ cfgps="$compconfig[correct_prompt]"
+ cfgins="$compconfig[correct_insert]"
+fi
+
+# Get the number of errors to accept.
+
+if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then
+ # Stop if we also have a `!'.
+
+ [[ "$cfgacc" = *\!* ]] && return 1
+
+ # Prefer the numeric argument if that has a sensible value.
+
+ comax="$NUMERIC"
+else
+ comax="${cfgacc//[^0-9]}"
+fi
+
+# If the number of errors to accept is too small, give up.
+
+[[ "$comax" -lt 1 ]] && return 1
+
+# Otherwise temporarily define functions to use instead of
+# the builtins that add matches. This is used to be able
+# to stick the `(#a...)' into the right place (after an
+# ignored prefix).
+
+compadd() {
+ [[ "$*" != *-([a-zA-Z/]#|)U* &&
+ "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
+
+ if [[ "$PREFIX" = \~*/* ]]; then
+ PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+ else
+ PREFIX="(#a${_comp_correct})$PREFIX"
+ fi
+ if [[ -n "$_correct_prompt" ]]; then
+ builtin compadd -X "$_correct_prompt" -J _correct "$@"
+ else
+ builtin compadd -J _correct "$@"
+ fi
+}
+
+compgen() {
+ [[ "$*" != *-([a-zA-Z/]#|)U* &&
+ "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
+
+ if [[ "$PREFIX" = \~*/* ]]; then
+ PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
+ else
+ PREFIX="(#a${_comp_correct})$PREFIX"
+ fi
+ if [[ -n "$_correct_prompt" ]]; then
+ builtin compgen "$@" -X "$_correct_prompt" -J _correct
+ else
+ builtin compgen "$@" -J _correct
+ fi
+}
+
+# Now initialise our counter. We also set `compstate[matcher]'
+# to `-1'. This allows completion functions to use the simple
+# `[[ compstate[matcher] -gt 1 ]] && return' to avoid being
+# called for multiple global match specs and still be called
+# again when correction is done. Also, this makes it easy to
+# test if correction is attempted since `compstate[matcher]'
+# will never be set to a negative value by the completion code.
+
+_comp_correct=1
+compstate[matcher]=-1
+
+_correct_prompt="${cfgps//\%e/1}"
+
+# We also need to set `extendedglob' and make the completion
+# code behave as if globcomplete were set.
+
+setopt extendedglob
+
+[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*'
+
+while [[ _comp_correct -le comax ]]; do
+ if _complete; then
+ if [[ "$cfgins" = unambig* &&
+ "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
+ compstate[pattern_insert]=unambiguous
+ elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then
+ if [[ "$cfgorig" = *last* ]]; then
+ builtin compadd -U -V _correct_original -nQ - "$PREFIX$SUFFIX"
+ elif [[ -n "$cfgorig" ]]; then
+ builtin compadd -U -nQ - "$PREFIX$SUFFIX"
+ fi
+
+ # If you always want to see the list of possible corrections,
+ # set `compstate[list]=list' here.
+
+ compstate[force_list]=list
+ fi
+ compstate[matcher]="$compstate[total_matchers]"
+ unfunction compadd compgen
+
+ return 0
+ fi
+
+ [[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
+ (( _comp_correct++ ))
+
+ _correct_prompt="${cfgps//\%e/$_comp_correct}"
+done
+
+compstate[matcher]="$compstate[total_matchers]"
+unfunction compadd compgen
+
+return 1
diff --git a/Completion/Core/_comp_parts b/Completion/Core/_comp_parts
new file mode 100644
index 000000000..7c24fd19d
--- /dev/null
+++ b/Completion/Core/_comp_parts
@@ -0,0 +1,147 @@
+#autoload
+
+# This function can be used to separately complete parts of strings
+# where each part may be one of a set of matches and different parts
+# have different sets.
+# Arguments are alternatingly arrays and separator strings. Arrays may
+# be given by name or literally as words separated by white space in
+# parentheses, e.g.:
+#
+# _comp_parts '(foo bar)' @ hosts
+#
+# This will make this function complete the strings in the array
+# `friends'. If the string on the line contains a `@', the substring
+# after it will be completed from the array `hosts'. Of course more
+# arrays may be given, each preceded by another separator string.
+#
+# This function understands the `-J group', `-V group', and
+# `-X explanation' options.
+#
+# This function does part of the matching itself and calls the functions
+# `_match_test' and `_match_pattern' for this.
+
+local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
+local matchflags opt group expl
+
+# Test if we should use this function for the global matcher in use.
+
+_match_test _comp_parts || return
+
+# Get the options.
+
+group=()
+expl=()
+while getopts "J:V:X:" opt; do
+ case "$opt" in
+ [JV]) group=("-$opt" "$OPTARG");;
+ X) expl=(-X "$OPTARG");;
+ esac
+done
+shift OPTIND-1
+
+# Get the string from the line.
+
+str="$PREFIX$SUFFIX"
+prefix=""
+
+# Walk through the arguments to find the longest unambiguous prefix.
+
+while [[ $# -gt 1 ]]; do
+ # Get the next array and separator.
+ arr="$1"
+ sep="$2"
+
+ if [[ "$arr[1]" == '(' ]]; then
+ tmparr=( ${=arr[2,-2]} )
+ arr=tmparr
+ fi
+ # Is the separator on the line?
+ [[ "$str" != *${sep}* ]] && break
+
+ # Build a pattern matching the possible matches and get all these
+ # matches in an array.
+ test="${str%%${sep}*}"
+ matchflags=""
+ _match_pattern _comp_parts test matchflags
+ test="${matchflags}${test}"
+ testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
+
+ # If there are no matches we give up. If there is more than one
+ # match, this is the part we will complete.
+ (( $#testarr )) || return
+ [[ $#testarr -gt 1 ]] && break
+
+ # Only one match, add it to the prefix and skip over it in `str',
+ # continuing with the next array and separator.
+ prefix="${prefix}${testarr[1]}${sep}"
+ str="${str#*${sep}}"
+ shift 2
+done
+
+# Get the array to work upon.
+arr="$1"
+if [[ "$arr[1]" == '(' ]]; then
+ tmparr=( ${=arr[2,-2]} )
+ arr=tmparr
+fi
+if [[ $# -le 1 || "$str" != *${2}* ]]; then
+ # No more separators, build the matches.
+ matchflags=""
+ test="$str"
+ _match_pattern _comp_parts test matchflags
+ test="${matchflags}${test}"
+ testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
+fi
+
+[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return
+
+# Now we build the suffixes to give to the completion code.
+shift
+matchers=()
+suffixes=("")
+autosuffix=()
+
+while [[ $# -gt 0 && "$str" == *${1}* ]]; do
+ # Remove anything up to the the suffix.
+ str="${str#*${1}}"
+
+ # Again, we get the string from the line up to the next separator
+ # and build a pattern from it.
+ if [[ $# -gt 2 ]]; then
+ test="${str%%${3}*}"
+ else
+ test="$str"
+ fi
+ matchflags=""
+ _match_pattern _comp_parts test matchflags
+ test="${matchflags}${test}"
+
+ # We incrementally add suffixes by appending to them the seperators
+ # and the strings from the next array that match the pattern we built.
+
+ arr="$2"
+ if [[ "$arr[1]" == '(' ]]; then
+ tmparr=( ${=arr[2,-2]} )
+ arr=tmparr
+ fi
+ suffixes=("${^suffixes[@]}${1}${(@M)^${(@P)arr}:#${~test}*}")
+
+ # We want the completion code to generate the most specific suffix
+ # for us, so we collect matching specifications that allow partial
+ # word matching before the separators on the fly.
+ matchers=("$matchers[@]" "r:|${1}=*")
+ shift 2
+done
+
+# If we were given at least one more separator we make the completion
+# code offer it by appending it as a autoremovable suffix.
+(( $# )) && autosuffix=(-qS "$1")
+
+# If we have collected matching specifications, we build an array
+# from it that can be used as arguments to `compadd'.
+[[ $#matchers -gt 0 ]] && matchers=(-M "$matchers")
+
+# Add the matches for each of the suffixes.
+for i in "$suffixes[@]"; do
+ compadd "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" -p "$prefix" -s "$i" - "$testarr[@]"
+done
diff --git a/Completion/Core/_compalso b/Completion/Core/_compalso
new file mode 100644
index 000000000..23a40e2d0
--- /dev/null
+++ b/Completion/Core/_compalso
@@ -0,0 +1,13 @@
+#autoload
+
+# This searches $1 in the array for normal completions and calls the result.
+# It is used to include completions for another command or special context
+# into the list generated by the calling function.
+# For example the function for `-subscript-' could call this as in
+# `_compalso -math- "$@"' to get the completions that would be generated
+# for a mathematical context.
+
+local tmp
+
+tmp="$_comps[$1]"
+[[ -z "$tmp" ]] || "$tmp" "$@"
diff --git a/Completion/Core/_complete b/Completion/Core/_complete
new file mode 100644
index 000000000..0f4d5ff4b
--- /dev/null
+++ b/Completion/Core/_complete
@@ -0,0 +1,52 @@
+#autoload
+
+# Generate all possible completions. Note that this is not intended as
+# a normal completion function, but as one possible value for the
+# compconfig[completer] parameter.
+
+local comp name
+
+# An entry for `-first-' is the replacement for `compctl -T'
+# Completion functions may set `_compskip' to any value to make the
+# main loops stop calling other completion functions.
+
+comp="$_comps[-first-]"
+if [[ ! -z "$comp" ]]; then
+ "$comp"
+ if (( $+_compskip )); then
+ unset _compskip
+ (( compstate[nmatches] ))
+ return
+ fi
+fi
+
+# For arguments and command names we use the `_normal' function.
+
+if [[ "$compstate[context]" = command ]]; then
+ _normal
+else
+ # Let's see if we have a special completion definition for the other
+ # possible contexts.
+
+ comp=''
+
+ case $compstate[context] in
+ equal) comp="$_comps[-equal-]";;
+ tilde) comp="$_comps[-tilde-]";;
+ redirect) comp="$_comps[-redirect-]";;
+ math) comp="$_comps[-math-]";;
+ subscript) comp="$_comps[-subscript-]";;
+ value) comp="$_comps[-value-]";;
+ array_value) comp="$_comps[-array-value-]";;
+ condition) comp="$_comps[-condition-]";;
+ parameter) comp="$_comps[-parameter-]";;
+ brace_parameter) comp="$_comps[-brace-parameter-]";;
+ esac
+
+ # If not, we use default completion, if any.
+
+ [[ -z "$comp" ]] && comp="$_comps[-default-]"
+ [[ -z "$comp" ]] || "$comp"
+fi
+
+(( compstate[nmatches] ))
diff --git a/Completion/Core/_correct b/Completion/Core/_correct
new file mode 100644
index 000000000..35ab01cf1
--- /dev/null
+++ b/Completion/Core/_correct
@@ -0,0 +1,19 @@
+#autoload
+
+# This is mainly a wrapper around the more general `_approximate.
+# By setting `compstate[pattern_match]' to something unequal to `*' and
+# then calling `_approximate, we get only corrections, not all strings
+# with the corrected prefix and something after it.
+#
+# Supported configuration keys are the same as for `_approximate', only
+# starting with `correct'.
+
+local ret=1 opm="$compstate[pattern_match]"
+
+compstate[pattern_match]='-'
+
+_approximate && ret=0
+
+compstate[pattern_match]="$opm"
+
+return ret
diff --git a/Completion/Core/_expand b/Completion/Core/_expand
new file mode 100644
index 000000000..9172b6cbf
--- /dev/null
+++ b/Completion/Core/_expand
@@ -0,0 +1,149 @@
+#autoload
+
+# This completer function is intended to be used as the first completer
+# function and allows one to say more explicitly when and how the word
+# from the line should be expanded than expand-or-complete.
+# This function will allow other completer functions to be called if
+# the expansions done produce no result or do not change the original
+# word from the line.
+#
+# Configuration keys:
+#
+# expand_substitute
+# If this is unset or set to the empty string, the code will first
+# try to expand all substitutions in the string (such as $(...) and
+# ${...}). If this is set to an non-empty string it should be
+# an expression usable inside a $[...] arithmetical expression.
+# In this case, expansion of substitutions will be done if the
+# expression evaluates to `1'. For example, with
+#
+# compconf expand_substitute='NUMERIC != 1'
+#
+# substitution will be performed only if given an explicit numeric
+# argument other than `1', as by typing ESC 2 TAB.
+#
+# expand_glob
+# If this is unset or set to an empty string, globbing will be
+# attempted on the word resulting from substitution or the
+# original string. The values accepted for this key are the same
+# as for expand_substitute.
+#
+# expand_menu
+# If this is unset or set to the empty string, the words resulting
+# from expansion (if any) will simply be inserted in the ommand line,
+# replacing the original string. However, if this key is set to an
+# non-empty string, the user can cycle through the expansion as in
+# a menucompletion. Unless the value contains the sub-string `only',
+# the user will still be offered all expansions at once as one of
+# the strings to insert in the command line. Also, if the value
+# contains the sub-string `last', the string with all expansion will
+# be offered first, whereas normally it is offered as the last string
+# to insert. Finally, if the value contains the sub-string `sort',
+# the expansions will be sorted alphabetically, normally they are
+# kept in the order the expansion produced them in.
+#
+# expand_original
+# If this is set to an non-empty string, the original string from the
+# line will be included in the list of strings the user can cycle
+# through as in a menucompletion. If the value contains the sub-string
+# `last', the original string will appear as the last string, with
+# other values it is inserted as the first one (so that the command
+# line does not change immediatly).
+#
+# expand_prompt
+# This may be set to a string that should be displayed before the
+# possible expansions. This is given to the -X option and thus may
+# contain the control sequences `%n', `%B', etc. Also, the sequence
+# `%o' in this string will be replaced by the original string.
+
+local exp word="$PREFIX$SUFFIX" group=-V
+
+# Do this only for the first global matcher.
+
+[[ "$compstate[matcher]" -le 1 ]] || return 1
+
+# In exp we will collect the expansion.
+
+exp=("$word")
+
+# First try substitution. That weird thing spanning multiple lines
+# changes quoted spaces, tabs, and newlines into spaces.
+
+[[ -z "$compconfig[expand_substitute]" ||
+ "${(e):-\$[$compconfig[expand_substitute]]}" -eq 1 ]] &&
+ exp=( "${(e)exp//\\[
+]/ }" )
+
+# If the array is empty, store the original string again.
+
+[[ -z "$exp" ]] && exp=("$word")
+
+# Now try globbing.
+
+[[ -z "$compconfig[expand_glob]" ||
+ "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] &&
+ exp=( ${~exp}(N) )
+
+# If we don't have any expansions or only one and that is the same
+# as the original string, we let other completers run.
+
+[[ $#exp -eq 0 ||
+ ( $#exp -eq 1 && "$exp[1]" = "$word" ) ]] && return 1
+
+# We have expansions, should we menucomplete them?
+
+if [[ -z "$compconfig[expand_menu]" ]]; then
+
+ # No, so if the user only wants a list, we add the strings
+ # separately. Otherwise we add the whole array as one string,
+ # probably also adding the original string.
+
+ if [[ -z "$compstate[insert]" ]]; then
+ compadd -U -V _expand -Q - "$exp[@]"
+ else
+ [[ -n "$compconfig[expand_original]" &&
+ "$compconfig[expand_original]" != *last* ]] &&
+ compadd -UnQ -V _expand_original - "$word"
+
+ compadd -UQ -V _expand - "$exp"
+
+ [[ -n "$compconfig[expand_original]" &&
+ "$compconfig[expand_original]" = *last* ]] &&
+ compadd -UnQ -V _expand_original - "$word"
+
+ compstate[insert]=menu
+ fi
+else
+ # Sorting? We just use a different group type then.
+
+ [[ "$compconfig[expand_menu]" = *sort* ]] && group=-J
+
+ # Now add the expansion string, probably also adding the original
+ # and/or the string containing all expanded string.
+
+ [[ -n "$compconfig[expand_original]" &&
+ "$compconfig[expand_original]" != *last* ]] &&
+ compadd -UnQ -V _expand_original - "$word"
+
+ [[ "$compconfig[expand_menu]" = *last* &&
+ "$compconfig[expand_menu]" != *only* ]] &&
+ compadd -UnQ -V _expand_all - "$exp"
+
+ if [[ -z "$compconfig[expand_prompt]" ]]; then
+ compadd -UQ $group _expand - "$exp[@]"
+ else
+ compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \
+ $group _expand - "$exp[@]"
+ fi
+ [[ "$compconfig[expand_menu]" != *last* &&
+ "$compconfig[expand_menu]" != *only* ]] &&
+ compadd -UnQ -V _expand_all - "$exp"
+
+ [[ -n "$compconfig[expand_original]" &&
+ "$compconfig[expand_original]" = *last* ]] &&
+ compadd -UnQ -V _expand_original - "$word"
+
+ compstate[insert]=menu
+fi
+
+return 0
diff --git a/Completion/Core/_files b/Completion/Core/_files
new file mode 100644
index 000000000..d2cce35e7
--- /dev/null
+++ b/Completion/Core/_files
@@ -0,0 +1,26 @@
+#autoload
+
+# Utility function for completing files of a given type or any file.
+# In many cases you will want to call this one instead of _path_files().
+
+local nm=$NMATCHES
+
+_path_files "$@"
+
+if [[ $# -ne 0 && -nmatches nm ]]; then
+ local opt opts
+
+ # We didn't get any matches for those types of files described by
+ # the `-g' or `-/' option. Now we try it again accepting all files.
+ # First we get those options that we have to use even if then. If
+ # we find out that the `-f' option was given, we already accepted
+ # all files and give up immediatly.
+
+ opts=()
+ while getopts "P:S:W:F:J:V:X:f/g:" opt; do
+ [[ "$opt" = f ]] && return
+ [[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG")
+ done
+
+ _path_files "$opts[@]"
+fi
diff --git a/Completion/Core/_list b/Completion/Core/_list
new file mode 100644
index 000000000..099c6bc7b
--- /dev/null
+++ b/Completion/Core/_list
@@ -0,0 +1,61 @@
+#autoload
+
+# This completer function makes the other completer functions used
+# insert possible completions only after once the list has been
+# shown.
+#
+# Configuration keys:
+#
+# list_condition
+# If this key is unset or set to the empty string, this completer
+# will delay the insertion of matches unconditionally. However,
+# if this value is set, it should be set to an expression usable
+# inside a $[...] arithmetical expression. In this case, delaying
+# will be done if the expression evaluates to `1'.
+# For example, with
+#
+# compconf list_condition='NUMERIC != 1'
+#
+# delaying will be done only if given an explicit numeric argument
+# other than `1'.
+#
+# list_word
+# To find out if only listing should be done, the code normally
+# compares the contents of the line with the contents the line
+# had at the time of the last invocation. If this key is set to
+# an non-empty string comparison is done using only the current
+# word. So if it is set, attempting completion on a word equal
+# to the one completion was called on the last time will not
+# delay the generation of matches.
+
+local pre suf
+
+# Get the strings to compare.
+
+if [[ -z "$compconfig[list_word]" ]]; then
+ pre="$HISTNO$LBUFFER"
+ suf="$RBUFFER"
+else
+ pre="$PREFIX"
+ suf="$SUFFIX"
+fi
+
+# Should we only show a list now?
+
+if [[ ( -z "$compconfig[list_condition]" ||
+ "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ) &&
+ ( "$pre" != "$_list_prefix" || "$suf" != "$_list_suffix" ) ]]; then
+
+ # Yes. Tell the completion code about it and save the new values
+ # to compare the next time.
+
+ compstate[insert]=''
+ compstate[list]=list
+ compstate[force_list]=yes
+ _list_prefix="$pre"
+ _list_suffix="$suf"
+fi
+
+# We always return one, because we don't really do any work here.
+
+return 1
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
new file mode 100644
index 000000000..c7f5a5a96
--- /dev/null
+++ b/Completion/Core/_main_complete
@@ -0,0 +1,48 @@
+#autoload
+
+# The main loop of the completion code. This is what is called when
+# completion is attempted from the command line.
+# The completion code gives us the special variables and the arguments
+# from the command line are given as positional parameters.
+
+local comp name
+
+setopt localoptions nullglob rcexpandparam globdots
+unsetopt markdirs globsubst shwordsplit nounset
+
+# An entry for `-first-' is the replacement for `compctl -T'
+# Completion functions may set `_compskip' to any value to make the
+# main loops stop calling other completion functions.
+
+comp="$_comps[-first-]"
+if [[ ! -z "$comp" ]]; then
+ "$comp" "$@"
+ if (( $+_compskip )); then
+ unset _compskip
+ return
+ fi
+fi
+
+# For arguments we use the `_normal function.
+
+if [[ $CONTEXT == argument || $CONTEXT == command ]]; then
+ _normal "$@"
+else
+ # Let's see if we have a special completion definition for the other
+ # possible contexts.
+
+ comp=''
+
+ case $CONTEXT in
+ redirect) comp="$_comps[-redirect-]";;
+ math) comp="$_comps[-math-]";;
+ subscript) comp="$_comps[-subscript-]";;
+ value) comp="$_comps[-value-]";;
+ condition) comp="$_comps[-condition-]";;
+ esac
+
+ # If not, we use default completion, if any.
+
+ [[ -z "$comp" ]] && comp="$_comps[-default-]"
+ [[ -z "$comp" ]] || "$comp" "$@"
+fi
diff --git a/Completion/Core/_match b/Completion/Core/_match
new file mode 100644
index 000000000..3c639935c
--- /dev/null
+++ b/Completion/Core/_match
@@ -0,0 +1,53 @@
+#autoload
+
+# This is intended to be used as a completer function after the normal
+# completer as in: `compconf completer=_complete:_match'.
+# It temporarily switches on pattern matching, allowing you to try
+# completion on patterns without having to setopt glob_complete.
+#
+# Note, however, that this is only really useful if you don't use the
+# expand-or-complete function because otherwise the pattern will
+# be expanded using globbing.
+#
+# Configuration key used:
+#
+# match_original
+# If this is set to a `only', pattern matching will only be tried
+# with the string from the line. If it is set to any other non-empty
+# string, the original pattern will be tried first and if that yields
+# no completions, matching will be tried again with a `*' inserted
+# at the cursor position. If this key is not set or set to an empty
+# string, matching will only be attempted with the `*' inserted.
+
+local tmp opm="$compstate[pattern_match]" ret=0
+
+# Do nothing if we don't have a pattern or there are still global
+# match specifications to try.
+
+tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
+[[ "$tmp:q" = "$tmp" ||
+ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
+
+# Try completion without inserting a `*'?
+
+if [[ -n "$compconfig[match_original]" ]]; then
+ compstate[matcher]=-1
+ compstate[pattern_match]='-'
+ _complete && ret=1
+ compstate[pattern_match]="$opm"
+ compstate[matcher]="$compstate[total_matchers]"
+
+ (( ret )) && return 0
+fi
+
+# No completion with inserting `*'?
+
+[[ "$compconfig[match_original]" = only ]] && return 1
+
+compstate[matcher]=-1
+compstate[pattern_match]='*'
+_complete && ret=1
+compstate[pattern_match]="$opm"
+compstate[matcher]="$compstate[total_matchers]"
+
+return 1-ret
diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts
new file mode 100644
index 000000000..1f51d2f6d
--- /dev/null
+++ b/Completion/Core/_multi_parts
@@ -0,0 +1,201 @@
+#autoload
+
+# This gets two arguments, a separator (which should be only one
+# character) and an array. As usual, the array may be given by it's
+# name or literal as in `(foo bar baz)' (words separated by spaces in
+# parentheses).
+# The parts of words from the array that are separated by the
+# separator character are then completed independently.
+
+local sep matches patstr orig matchflags pref i tmp1 tmp2 nm
+local group expl
+
+_match_test _multi_parts || return 1
+
+# Save the current number of matches to be able to return if we added
+# matches or not.
+
+nm=$compstate[nmatches]
+
+# Get the options.
+
+group=()
+expl=()
+while getopts "J:V:X:" opt; do
+ case "$opt" in
+ [JV]) group=("-$opt" "$OPTARG");;
+ X) expl=(-X "$OPTARG");;
+ esac
+done
+shift OPTIND-1
+
+# Get the arguments, first the separator, then the array. The array is
+# stored in `matches'. Further on this array will always contain those
+# words from the original array that still match everything we have
+# tried to match while we walk through the string from the line.
+
+sep="$1"
+if [[ "${2[1]}" = '(' ]]; then
+ matches=( ${2[2,-2]} )
+else
+ matches=( "${(@P)2}" )
+fi
+
+# Now build the pattern from what we have on the line. We also save
+# the original string in `orig'. The `eval' is used to replace our
+# separator character by `*<sep>'.
+
+if [[ -o globcomplete ]]; then
+ patstr="${PREFIX}*${SUFFIX}*"
+else
+ patstr="${PREFIX:q}*${SUFFIX:q}*"
+fi
+orig="${PREFIX}${SUFFIX}"
+
+matchflags=""
+_match_pattern _path_files patstr matchflags
+[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+patstr="${${patstr//$sep/*$sep}//\*##/*}"
+#eval patstr\="\$patstr:gs-${sep}-\*${sep}-:gs/\*\*/\*/"
+
+# First we will skip over those parts of the matches for which we have
+# exact substrings on the line. In `pref' we will build the
+# unambiguous prefix string.
+
+pref=''
+while [[ "$orig" = *${sep}* ]] do
+
+ # First build the pattern to use, then collect all strings from
+ # `matches' that match the prefix we have and the exact substring in
+ # the array `tmp1'.
+
+ pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}${patstr##*${sep}}"
+ tmp1=( "${(@M)matches:#${~matchflags}${orig%%${sep}*}${sep}${~pat}}" )
+
+ # If there are no words matching the exact substring, stop.
+
+ (( $#tmp1 )) || break
+
+ # Otherwise add the part to the prefix, remove it from the matches
+ # (which will also remove all words not matching the string at all),
+ # and set `patstr' and `orig' to the next component.
+
+ pref="$pref${orig%%${sep}*}${sep}"
+ matches=( "${(@)${(@)matches#${orig%%${sep}*}${sep}}:#}" )
+ orig="${orig#*${sep}}"
+ patstr="${patstr#*${sep}}"
+done
+
+# Now we get all the words that still match in `tmp1'.
+
+if [[ "$patstr" = *${sep}* ]]; then
+ tmp1="${patstr%${sep}*}${sep}"
+ pat="${tmp1//\*/[^${sep}]#}${patstr##*${sep}}"
+else
+ pat="$patstr"
+fi
+tmp1=( "${(@M)matches:#${~matchflags}${~pat}}" )
+
+if (( $#tmp1 )); then
+
+ # There are words that are matched, put them int `matches' and then
+ # move all unambiguous components from the beginning into `pref'.
+
+ matches=( "$tmp1[@]" )
+ while [[ "$matches[1]" = *${sep}* ]]; do
+
+ # We just take the first component of the first match and see if
+ # there are other matches with a different prefix (these are
+ # collected in `tmp2'). If there are any, we give up.
+
+ tmp1="${matches[1]%%${sep}*}${sep}"
+ tmp2=( "${(@)matches:#${tmp1}*}" )
+ (( $#tmp2 )) && break
+
+ # All matches have the same prefix, but it into `pref' and remove
+ # it from the matches.
+
+ pref="$pref$tmp1"
+ matches=( "${(@)${(@)matches#$tmp1}:#}" )
+
+ if [[ "$orig" = *${sep}* ]]; then
+ orig="${orig#*${sep}}"
+ else
+ orig=''
+ fi
+ done
+
+ # Now we can tell the completion code about the things we
+ # found. Strings that have a separator will be added with a suffix.
+
+ if [[ -z "$orig" && "$PREFIX$SUFFIX" != "$pref$orig" ]]; then
+ compadd -QU "$group[@]" "$expl[@]" -i "$IPREFIX" -S '' - "${pref}${orig}"
+ elif [[ $compstate[insert] = *menu ]]; then
+ for i in "$matches[@]" ; do
+ if [[ "$i" = *${sep}* ]]; then
+ compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
+ -p "$pref" -qS "$sep" - "${i%%${sep}*}"
+ else
+ compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
+ -p "$pref" - "${i%%${sep}*}"
+ fi
+ done
+ else
+ for i in "$matches[@]" ; do
+ if [[ "$i" = *${sep}* ]]; then
+ compadd -U -i "$IPREFIX" -p "$pref" -s "${sep}${i#*${sep}}" \
+ "$group[@]" "$expl[@]" -M "r:|${sep}=*" - "${i%%${sep}*}"
+ else
+ compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -p "$pref" - "$i"
+ fi
+ done
+ fi
+elif [[ "$patstr" = *${sep}* ]]; then
+
+ # We had no words matching the string from the line. But we want to
+ # be friendly and at least expand the prefix as far as we can. So we
+ # will loop through the rest of the string from the line and test
+ # the components one by one.
+
+ while [[ "$patstr" = *${sep}* ]]; do
+
+ # First we get all words matching at least this component in
+ # `tmp1'. If there are none, we give up.
+
+ tmp1=( "${(@M)matches:#${~matchflags}${~patstr%%${sep}*}${sep}*}" )
+ (( $#tmp1 )) || break
+
+ # Then we check if there are words that have a different prefix.
+
+ tmp2=( "${(@)tmp1:#${tmp1[1]%%${sep}*}${sep}*}" )
+ if (( $#tmp2 )); then
+
+ # There are words with another prefix, so we have found an
+ # ambiguous component. So we just give all possible prefixes to
+ # the completion code together with our prefix and the rest of
+ # the string from the line as the suffix.
+
+ compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" \
+ -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}"
+ return 0
+ fi
+
+ # All words have the same prefix, so add it to `pref' again and
+ # try the next component.
+
+ pref="$pref${tmp1[1]%%${sep}*}${sep}"
+ matches=( "${(@)matches#${tmp1[1]%%${sep}*}${sep}}" )
+ orig="${orig#*${sep}}"
+ patstr="${patstr#*${sep}}"
+ done
+
+ # Finally, add the unambiguous prefix and the rest of the string
+ # from the line.
+
+ compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" - "$orig"
+fi
+
+# This sets the return value to indicate that we added matches (or not).
+
+[[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/_normal b/Completion/Core/_normal
new file mode 100644
index 000000000..19da6d79b
--- /dev/null
+++ b/Completion/Core/_normal
@@ -0,0 +1,54 @@
+#autoload
+
+local comp cmd1 cmd2 pat val name
+
+# Completing in command position? If not we set up `cmd1' and `cmd2' as
+# two strings we have search in the completion definition arrays (e.g.
+# a path and the last path name component).
+
+if [[ $CONTEXT == command ]]; then
+ comp="$_comps[-command-]"
+ [[ -z "$comp" ]] || "$comp" "$@"
+ return
+elif [[ "$COMMAND[1]" == '=' ]]; then
+ eval cmd1\=$COMMAND
+ cmd2="$COMMAND[2,-1]"
+elif [[ "$COMMAND" == */* ]]; then
+ cmd1="$COMMAND"
+ cmd2="${COMMAND:t}"
+else
+ cmd1="$COMMAND"
+ eval cmd2=$(whence -p $COMMAND)
+fi
+
+# See if there are any matching pattern completions.
+
+for i in "$_patcomps[@]"; do
+ pat="${i% *}"
+ val="${i#* }"
+ if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then
+ "$val" "$@"
+ if (( $+_compskip )); then
+ unset _compskip
+ return
+ fi
+ fi
+done
+
+# Now look up the two names in the normal completion array.
+
+name="$cmd1"
+comp="$_comps[$cmd1]"
+
+if [[ -z "$comp" ]]; then
+ name="$cmd2"
+ comp="$_comps[$cmd2]"
+fi
+
+# And generate the matches, probably using default completion.
+
+if [[ -z "$comp" ]]; then
+ name=-default-
+ comp="$_comps[-default-]"
+fi
+[[ -z "$comp" ]] || "$comp" "$@"
diff --git a/Completion/Core/_options b/Completion/Core/_options
new file mode 100644
index 000000000..0a852e6ce
--- /dev/null
+++ b/Completion/Core/_options
@@ -0,0 +1,5 @@
+#autoload
+
+# This should be used to complete all option names.
+
+compgen "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters
new file mode 100644
index 000000000..0e8c548f7
--- /dev/null
+++ b/Completion/Core/_parameters
@@ -0,0 +1,8 @@
+#autoload
+
+# This should be used to complete parameter names if you need some of the
+# extra options of compadd. It first tries to complete only non-local
+# parameters. All arguments are given to compadd.
+
+compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }" ||
+ compadd "$@" - "${(@)${(@)${(@f)$(typeset)}%%\=*}##* }"
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
new file mode 100644
index 000000000..83b6e8a09
--- /dev/null
+++ b/Completion/Core/_path_files
@@ -0,0 +1,311 @@
+#autoload
+
+# Utility function for in-path completion.
+# Supported arguments are: `-f', `-/', `-g <patterns>', `-J <group>',
+# `-V <group>', `-W paths', `-X explanation', and `-F <ignore>'. All but
+# the last have the same syntax and meaning as for `complist'. The
+# `-F <ignore>' option may be used to give a list of suffixes either by
+# giving the name of an array or literally by giving them in a string
+# surrounded by parentheses. Files with one of the suffixes thus given
+# are treated like files with one of the suffixes in the `fignore' array
+# in normal completion.
+#
+# This function uses the helper functions `_match_test' and `_match_pattern'.
+
+# First see if we should generate matches for the global matcher in use.
+
+_match_test _path_files || return
+
+# Yes, so...
+
+local nm prepaths str linepath realpath donepath patstr prepath testpath rest
+local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt
+local addpfx addsfx expl
+
+setopt localoptions nullglob rcexpandparam globdots extendedglob
+unsetopt markdirs globsubst shwordsplit nounset
+
+prepaths=('')
+ignore=()
+group=()
+sopt='-'
+gopt=''
+pats=()
+addpfx=()
+addsfx=()
+expl=()
+
+# Get the options.
+
+while getopts "P:S:W:F:J:V:X:f/g:" opt; do
+ case "$opt" in
+ P) addpfx=(-P "$OPTARG")
+ ;;
+ S) addsfx=(-S "$OPTARG")
+ ;;
+ W) tmp1="$OPTARG"
+ if [[ "$tmp1[1]" = '(' ]]; then
+ prepaths=( ${^=tmp1[2,-2]}/ )
+ else
+ prepaths=( ${(P)=${tmp1}} )
+ (( ! $#prepaths )) && prepaths=( ${tmp1}/ )
+ fi
+ (( ! $#prepaths )) && prepaths=( '' )
+ ;;
+ F) tmp1="$OPTARG"
+ if [[ "$tmp1[1]" = '(' ]]; then
+ ignore=( ${^=tmp1[2,-2]}/ )
+ else
+ ignore=( ${(P)${tmp1}} )
+ fi
+ (( $#ignore )) && ignore=(-F "( $ignore )")
+ ;;
+ [JV]) group=("-$opt" "$OPTARG")
+ ;;
+ X) expl=(-X "$OPTARG")
+ ;;
+ f) sopt="${sopt}f"
+ pats=("$pats[@]" '*')
+ ;;
+ /) sopt="${sopt}/"
+ pats=("$pats[@]" '*(-/)')
+ ;;
+ g) gopt='-g'
+ pats=("$pats[@]" ${=OPTARG})
+ ;;
+ esac
+done
+
+# If we were given no file selection option, we behave as if we were given
+# a `-f'.
+
+if [[ "$sopt" = - ]]; then
+ if [[ -z "$gopt" ]]; then
+ sopt='-f'
+ pats=('*')
+ else
+ unset sopt
+ fi
+fi
+
+# str holds the whole string from the command line with a `*' between
+# the prefix and the suffix.
+
+str="${PREFIX:q}*${SUFFIX:q}"
+
+# If the string began with a `~', the quoting turned this into `\~',
+# remove the slash.
+
+[[ "$str" = \\\~* ]] && str="$str[2,-1]"
+
+# We will first try normal completion called with `complist', but only if we
+# weren't given a `-F' option.
+
+if (( ! $#ignore )); then
+ # First build an array containing the `-W' option, if there is any and we
+ # want to use it. We don't want to use it if the string from the command line
+ # is a absolute path or relative to the current directory.
+
+ if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then
+ tmp1=()
+ else
+ tmp1=(-W "( $prepaths )")
+ fi
+
+ # Now call complist.
+
+ nm=$NMATCHES
+ if [[ -z "$gopt" ]]; then
+ complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt
+ else
+ complist "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" "$tmp1[@]" $sopt -g "$pats"
+ fi
+
+ # If this generated any matches, we don't want to do in-path completion.
+
+ [[ -nmatches nm ]] || return
+
+ # No `-F' option, so we want to use `fignore'.
+
+ ignore=(-F fignore)
+fi
+
+# Now let's have a closer look at the string to complete.
+
+if [[ "$str[1]" = \~ ]]; then
+ # It begins with `~', so remember anything before the first slash to be able
+ # to report it to the completion code. Also get an expanded version of it
+ # (in `realpath'), so that we can generate the matches. Then remove that
+ # prefix from the string to complete, set `donepath' to build the correct
+ # paths and make sure that the loop below is run only once with an empty
+ # prefix path by setting `prepaths'.
+
+ linepath="${str%%/*}/"
+ eval realpath\=$linepath
+ str="${str#*/}"
+ donepath=''
+ prepaths=( '' )
+else
+ # If the string does not start with a `~' we don't remove a prefix from the
+ # string.
+
+ liniepath=''
+ realpath=''
+
+ if [[ "$str[1]" = / ]]; then
+ # If it is a absolut path name, we remove the first slash and put it in
+ # `donepath' meaning that we treat it as the path that was already handled.
+ # Also, we don't use the paths from `-W'.
+
+ str="$str[2,-1]"
+ donepath='/'
+ prepaths=( '' )
+ else
+ # The common case, we just use the string as it is, unless it begins with
+ # `./' or `../' in which case we don't use the paths from `-W'.
+
+ [[ "$str" = (.|..)/* ]] && prepaths=( '' )
+ donepath=''
+ fi
+fi
+
+# First we skip over all pathname components in `str' which really exist in
+# the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and
+# `lib5'. Pathname components skipped this way are taken from `str' and added
+# to `donepath'.
+
+while [[ "$str" = */* ]] do
+ [[ -e "$realpath$donepath${str%%/*}" ]] || break
+ donepath="$donepath${str%%/*}/"
+ str="${str#*/}"
+done
+
+# Now build the glob pattern by calling `_match_pattern'.
+patstr="$str"
+matchflags=""
+_match_pattern _path_files patstr matchflags
+
+# We almost expect the pattern to have changed `..' into `*.*.', `/.' into
+# `/*.', and probably to contain two or more consecutive `*'s. Since these
+# have special meaning for globbing, we remove them. But before that, we
+# add the pattern for matching any characters before a slash.
+
+patstr="$patstr:gs-/-*/-:gs/*.*.//:gs-/*.-/.-:gs/**/*/"
+
+# Finally, generate the matches. First we loop over all the paths from `-W'.
+# Note that in this loop `str' is used as a modifyable version of `patstr'
+# and `testpath' is a modifyable version of `donepath'.
+
+for prepath in "$prepaths[@]"; do
+ str="$patstr"
+ testpath="$donepath"
+
+ # The second loop tests the components of the path in `str' to get the
+ # possible matches.
+
+ while [[ "$str" = */* ]] do
+ # `rest' is the pathname after the first slash that is left. In `tmp1'
+ # we get the globbing matches for the pathname component currently
+ # handled.
+
+ rest="${str#*/}"
+ tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)"
+ tmp1=( $~tmp1 )
+
+ if [[ $#tmp1 -eq 0 ]]; then
+ # If this didn't produce any matches, we don't need to test this path
+ # any further, so continue with the next `-W' path, if any.
+
+ continue 2
+ elif [[ $#tmp1 -gt 1 ]]; then
+ # If it produced more than one match, we want to remove those which
+ # don't have possible following pathname components matching the
+ # rest of the string we are completing. (The case with only one
+ # match is handled below.)
+ # In `collect' we will collect those of the produced pathnames that
+ # have a matching possible path-suffix. In `suffixes' we build an
+ # array containing strings build from the rest of the string to
+ # complete and the glob patterns we were given as arguments.
+
+ collect=()
+ suffixes=( $rest$^pats )
+ suffixes=( "${(@)suffixes:gs.**.*.}" )
+
+ # In the loop the prefixes from the `tmp1' array produced above and
+ # the suffixes we just built are used to produce possible matches
+ # via globbing.
+
+ for i in $tmp1; do
+ tmp2=( ${~i}/${~matchflags}${~suffixes} )
+ [[ $#tmp2 -ne 0 ]] && collect=( $collect $i )
+ done
+
+ # If this test showed that none of the matches from the glob in `tmp1'
+ # has a possible sub-path matching what's on the line, we give up and
+ # continue with the next `-W' path.
+
+ if [[ $#collect -eq 0 ]]; then
+ continue 2
+ elif [[ $#collect -ne 1 ]]; then
+ # If we have more than one possible match, this means that the
+ # pathname component currently handled is ambiguous, so we give
+ # it to the completion code.
+ # First we build the full path prefix in `tmp1'.
+
+ tmp1="$prepath$realpath$testpath"
+
+ # Now produce all matching pathnames in `collect'.
+
+ collect=( ${~collect}/${~matchflags}${~suffixes} )
+
+ # And then remove the common path prefix from all these matches.
+
+ collect=( ${collect#$tmp1} )
+
+ # Finally, we add all these matches with the common (unexpanded)
+ # pathprefix (the `-p' option), the path-prefix (the `-W' option)
+ # to allow the completion code to test file type, and the path-
+ # suffix (the `-s' option). We also tell the completion code that
+ # these are file names and that `fignore' should be used as usual
+ # (the `-f' and `-F' options).
+
+ for i in $collect; do
+ compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$tmp1" -s "/${i#*/}" -f "$ignore[@]" - "${i%%/*}"
+ done
+
+ # We have just finished handling all the matches from above, so we
+ # can continue with the next `-W' path.
+
+ continue 2
+ fi
+ # We reach this point if only one of the path prefixes in `tmp1'
+ # has a existing path-suffix matching the string from the line.
+ # In this case we accept this match and continue with the next
+ # path-name component.
+
+ tmp1=( "$collect[1]" )
+ fi
+ # This is also reached if the first globbing produced only one match
+ # in this case we just continue with the next pathname component, too.
+
+ tmp1="$tmp1[1]"
+ testpath="$testpath${tmp1##*/}/"
+ str="$rest"
+ done
+
+ # We are here if all pathname components except the last one (which is still
+ # not tested) are unambiguous. So we add matches with the full path prefix,
+ # no path suffix, the `-W' we are currently handling, all the matches we
+ # can produce in this directory, if any.
+
+ tmp1="$prepath$realpath$testpath"
+ suffixes=( $str$^pats )
+ suffixes=( "${(@)suffixes:gs.**.*.}" )
+ tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
+ if [[ $#tmp2 -eq 0 && "$sopt" = */* ]]; then
+ [[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]"
+ compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -f - "$linepath$testpath"
+ else
+ compadd "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" - ${(@)tmp2#$tmp1}
+ fi
+done
diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts
new file mode 100644
index 000000000..c1cda2b9a
--- /dev/null
+++ b/Completion/Core/_sep_parts
@@ -0,0 +1,171 @@
+#autoload
+
+# This function can be used to separately complete parts of strings
+# where each part may be one of a set of matches and different parts
+# have different sets.
+# Arguments are alternatingly arrays and separator strings. Arrays may
+# be given by name or literally as words separated by white space in
+# parentheses, e.g.:
+#
+# _sep_parts '(foo bar)' @ hosts
+#
+# This will make this function complete the strings in the array
+# `friends'. If the string on the line contains a `@', the substring
+# after it will be completed from the array `hosts'. Of course more
+# arrays may be given, each preceded by another separator string.
+#
+# This function understands the `-J group', `-V group', and
+# `-X explanation' options.
+#
+# This function does part of the matching itself and calls the functions
+# `_match_test' and `_match_pattern' for this.
+
+local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
+local matchflags opt group expl nm=$compstate[nmatches]
+
+# Test if we should use this function for the global matcher in use.
+
+_match_test _sep_parts || return 1
+
+# Get the options.
+
+group=()
+expl=()
+while getopts "J:V:X:" opt; do
+ case "$opt" in
+ [JV]) group=("-$opt" "$OPTARG");;
+ X) expl=(-X "$OPTARG");;
+ esac
+done
+shift OPTIND-1
+
+# Get the string from the line.
+
+str="$PREFIX$SUFFIX"
+[[ $#compstate[pattern_match] -ne 0 ]] || str="$str:q"
+prefix=""
+
+# Walk through the arguments to find the longest unambiguous prefix.
+
+while [[ $# -gt 1 ]]; do
+ # Get the next array and separator.
+ arr="$1"
+ sep="$2"
+
+ if [[ "$arr[1]" == '(' ]]; then
+ tmparr=( ${=arr[2,-2]} )
+ arr=tmparr
+ fi
+ # Is the separator on the line?
+ [[ "$str" != *${sep}* ]] && break
+
+ # Build a pattern matching the possible matches and get all these
+ # matches in an array.
+
+ test="${str%%${sep}*}"
+ [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
+
+ matchflags=""
+ _match_pattern _sep_parts test matchflags
+ [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+ test="${matchflags}${test}"
+ testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
+ testarr=( "${(@)testarr:#}" )
+
+ # If there are no matches we give up. If there is more than one
+ # match, this is the part we will complete.
+ (( $#testarr )) || return 1
+ [[ $#testarr -gt 1 ]] && break
+
+ # Only one match, add it to the prefix and skip over it in `str',
+ # continuing with the next array and separator.
+ prefix="${prefix}${testarr[1]}${sep}"
+ str="${str#*${sep}}"
+ shift 2
+done
+
+# Get the array to work upon.
+arr="$1"
+if [[ "$arr[1]" == '(' ]]; then
+ tmparr=( ${=arr[2,-2]} )
+ arr=tmparr
+fi
+if [[ $# -le 1 || "$str" != *${2}* ]]; then
+ # No more separators, build the matches.
+
+ test="$str"
+ [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
+
+ matchflags=""
+ _match_pattern _sep_parts test matchflags
+ [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+ test="${matchflags}${test}"
+ testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
+ testarr=( "${(@)testarr:#}" )
+fi
+
+[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return 1
+
+# Now we build the suffixes to give to the completion code.
+shift
+matchers=()
+suffixes=("")
+autosuffix=()
+
+while [[ $# -gt 0 && "$str" == *${1}* ]]; do
+ # Remove anything up to the the suffix.
+ str="${str#*${1}}"
+
+ # Again, we get the string from the line up to the next separator
+ # and build a pattern from it.
+ if [[ $# -gt 2 ]]; then
+ test="${str%%${3}*}"
+ else
+ test="$str"
+ fi
+
+ [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
+
+ matchflags=""
+ _match_pattern _sep_parts test matchflags
+ [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+ test="${matchflags}${test}"
+
+ # We incrementally add suffixes by appending to them the seperators
+ # and the strings from the next array that match the pattern we built.
+
+ arr="$2"
+ if [[ "$arr[1]" == '(' ]]; then
+ tmparr=( ${=arr[2,-2]} )
+ arr=tmparr
+ fi
+ tmparr=( "${(@M)${(@P)arr}:#${~test}*}" )
+ tmparr=( "${(@)tmparr:#}" )
+ suffixes=("${(@)^suffixes[@]}${1}${(@)^tmparr}")
+
+ # We want the completion code to generate the most specific suffix
+ # for us, so we collect matching specifications that allow partial
+ # word matching before the separators on the fly.
+ matchers=("$matchers[@]" "r:|${1:q}=*")
+ shift 2
+done
+
+# If we were given at least one more separator we make the completion
+# code offer it by appending it as a autoremovable suffix.
+(( $# )) && autosuffix=(-qS "$1")
+
+# If we have collected matching specifications, we build an array
+# from it that can be used as arguments to `compadd'.
+[[ $#matchers -gt 0 ]] && matchers=(-M "$matchers")
+
+# Add the matches for each of the suffixes.
+for i in "$suffixes[@]"; do
+ compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \
+ -i "$IPREFIX" -p "$prefix" -s "$i" - "$testarr[@]"
+done
+
+# This sets the return value to indicate that we added matches (or not).
+
+[[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/_set_options b/Completion/Core/_set_options
new file mode 100644
index 000000000..5f634a2cd
--- /dev/null
+++ b/Completion/Core/_set_options
@@ -0,0 +1,7 @@
+#autoload
+
+# Complete all set options. This relies on `_main_complete' to store the
+# names of the options that were set when it was called in the array
+# `_set_options'.
+
+compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options
diff --git a/Completion/Core/_unset_options b/Completion/Core/_unset_options
new file mode 100644
index 000000000..c5150c2e5
--- /dev/null
+++ b/Completion/Core/_unset_options
@@ -0,0 +1,7 @@
+#autoload
+
+# Complete all unset options. This relies on `_main_complete' to store the
+# names of the options that were set when it was called in the array
+# `_set_options'.
+
+compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options
diff --git a/Completion/Core/compdump b/Completion/Core/compdump
new file mode 100644
index 000000000..8be096f50
--- /dev/null
+++ b/Completion/Core/compdump
@@ -0,0 +1,89 @@
+# This is a file to be sourced to dump the definitions for new-style
+# completion defined by 'compinit' in the same directory. The output
+# should be directed into the "compinit.dump" in the same directory as
+# compinit. If you rename init, just stick .dump onto the end of whatever
+# you have called it and put it in the same directory. This is handled
+# automatically if you invoke compinit with the option -d.
+#
+# You will need to update the dump every time you add a new completion.
+# To do this, simply remove the .dump file, start a new shell, and
+# create the .dump file as before. Again, compinit -d handles this
+# automatically.
+#
+# It relies on KSH_ARRAYS not being set.
+
+# Print the number of files used for completion. This is used in compinit
+# to see if auto-dump should re-dump the dump-file.
+
+_d_file=${COMPDUMP-${0:h}/compinit.dump}
+
+typeset -U _d_files
+_d_files=( ${^~fpath}/_*~*~(N:t) )
+
+print "#files: $#_d_files" > $_d_file
+
+unset _d_files
+
+# First dump the arrays _comps and _patcomps. The quoting hieroglyphyics
+# ensure that a single quote inside a variable is itself correctly quoted.
+
+print "_comps=(" >> $_d_file
+for _d_f in ${(ok)_comps}; do
+ print -r - "'${_d_f//\'/'\\''}'" "'${_comps[$_d_f]//\'/'\\''}'"
+done >> $_d_file
+print ")" >> $_d_file
+
+print "\n_patcomps=(" >> $_d_file
+for _d_f in "$_patcomps[@]"; do
+ print -r - "'${_d_f//\'/'\\''}'"
+done >> $_d_file
+print ")" >> $_d_file
+
+print >> $_d_file
+
+# Now dump the key bindings. We dump all bindings for zle widgets
+# whose names start with a underscore.
+# We need both the zle -C's and the bindkey's to recreate.
+
+_d_bks=()
+zle -lL |
+ while read -rA _d_line; do
+ if [[ ${_d_line[5]} = _* ]]; then
+ print -r - ${_d_line}
+ _d_bks=($_d_bks ${_d_line[3]})
+ fi
+ done >> $_d_file
+bindkey |
+ while read -rA _d_line; do
+ if [[ ${_d_line[2]} = (${(j.|.)~_d_bks}) ]]; then
+ print -r "bindkey '${_d_line[1][2,-2]}' ${_d_line[2]}"
+ fi
+ done >> $_d_file
+
+print >> $_d_file
+
+
+# Autoloads: whence -w produces "_d_foo: function", so look for
+# all functions beginning with `_'.
+
+_d_als=($(whence -wm '_*' | sort |
+while read -rA _d_line; do
+ [[ ${_d_line[2]} = function ]] && print -r - ${_d_line[1]%:}
+done))
+
+# print them out: about five to a line looks neat
+
+while (( $#_d_als )); do
+ print -n autoload
+ for (( _i = 0; _i < 5; _i++ )); do
+ if (( $#_d_als )); then
+ print -n " $_d_als[1]"
+ shift _d_als
+ fi
+ done
+ print
+done >> $_d_file
+
+print >> $_d_file
+
+unset _d_line _d_zle _d_bks _d_als _d_f _f_file
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
new file mode 100644
index 000000000..ec5867838
--- /dev/null
+++ b/Completion/Core/compinit
@@ -0,0 +1,269 @@
+# 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