From 904b939cbd81a542303da2c58288b95b153106f5 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:17:36 +0000 Subject: zsh-3.1.5-pws-10 --- Completion/Core/_comp_parts | 147 +++++++++++++++++++ Completion/Core/_compalso | 13 ++ Completion/Core/_files | 26 ++++ Completion/Core/_main_complete | 48 +++++++ Completion/Core/_normal | 54 +++++++ Completion/Core/_path_files | 311 +++++++++++++++++++++++++++++++++++++++++ Completion/Core/compdump | 89 ++++++++++++ Completion/Core/compinit | 269 +++++++++++++++++++++++++++++++++++ 8 files changed, 957 insertions(+) create mode 100644 Completion/Core/_comp_parts create mode 100644 Completion/Core/_compalso create mode 100644 Completion/Core/_files create mode 100644 Completion/Core/_main_complete create mode 100644 Completion/Core/_normal create mode 100644 Completion/Core/_path_files create mode 100644 Completion/Core/compdump create mode 100644 Completion/Core/compinit (limited to 'Completion/Core') 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/_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/_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/_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/_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 ', `-J ', +# `-V ', `-W paths', `-X explanation', and `-F '. All but +# the last have the same syntax and meaning as for `complist'. The +# `-F ' 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' 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/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 ' +# 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 is given +# +# `#defpatcomp ' +# this defines a function that should be called to generate +# matches for commands whose name matches ; note +# that only one pattern may be given +# +# `#defkeycomp