From 04a89199d02a3ee6c4b3d89a6c782bdb0a4f1bc8 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:20:19 +0000 Subject: zsh-3.1.5-pws-12 --- Completion/Core/_sep_parts | 171 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 Completion/Core/_sep_parts (limited to 'Completion/Core/_sep_parts') 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] ]] -- cgit 1.4.1