Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: _tar uses _multi_parts
- X-seq: zsh-workers 5811
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: Re: _tar uses _multi_parts
- Date: Mon, 15 Mar 1999 12:51:22 +0100 (MET)
- In-reply-to: Bruce Stephens's message of 15 Mar 1999 11:42:32 +0000
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Bruce Stephens wrote:
> Presumably the fix is:
> ! _multi_parts / _tar_cache_list
> ! _sep_parts / _tar_cache_list
Nay! It was just that `_multi_parts' somehow got omitted from the
distribution.
Bye
Sven
diff -u Completion/Core/_multi_parts Completion/Core/_multi_parts
--- Completion/Core/_multi_parts Mon Mar 15 12:49:22 1999
+++ Completion/Core/_multi_parts Mon Mar 15 12:49:41 1999
@@ -0,0 +1,226 @@
+#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 menu origflags mflags
+
+_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'.
+
+if [[ $#compstate[pattern_match] -ne 0 ]]; then
+ patstr="${PREFIX}*${SUFFIX}*"
+else
+ patstr="${PREFIX:q}*${SUFFIX:q}*"
+fi
+orig="${PREFIX}${SUFFIX}"
+
+[[ $compstate[insert] = *menu || -n "$_comp_correct" ||
+ ( $#compstate[pattern_match] -ne 0 &&
+ "$orig" != "${orig:q}" ) ]] && menu=yes
+
+matchflags=""
+_match_pattern _path_files patstr matchflags
+origflags="$matchflags"
+[[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+patstr="${${patstr//$sep/*$sep}//\*##/*}"
+
+# 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'.
+
+ if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
+ mflags="$origflags"
+ else
+ mflags="$matchflags"
+ fi
+
+ pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}"
+ tmp1=( "${(@M)matches:#${~mflags}${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
+ # (and also remove all words not matching the string at all), and
+ # set `patstr' and `orig' to the next component.
+
+ tmp1="${orig%%${sep}*}${sep}"
+ pref="$pref$tmp1"
+ matches=("${(@)${(@)${(@M)matches:#${tmp1}*}#$tmp1}:#}")
+ 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
+if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
+ mflags="$origflags"
+else
+ mflags="$matchflags"
+fi
+tmp1=( "${(@M)matches:#${~mflags}${~pat}}" )
+
+if (( $#tmp1 )); then
+
+ # There are words that are matched, put them into `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, put 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 [[ -n "$menu" ]]; then
+ if [[ "$orig" = *${sep}* ]]; then
+ orig="${sep}${orig#*${sep}}"
+ else
+ orig=''
+ fi
+ for i in "$matches[@]" ; do
+ if [[ "$i" = *${sep}* ]]; then
+ compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
+ -p "$pref" -s "$orig" - "${i%%${sep}*}${sep}"
+ else
+ compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
+ -p "$pref" -s "$orig" - "${i%%${sep}*}"
+ fi
+ done
+ else
+ for i in "$matches[@]" ; do
+ if [[ "$i" = *${sep}* ]]; then
+ compadd -U -i "$IPREFIX" -p "$pref" -s "${i#*${sep}}" \
+ "$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${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.
+
+ if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
+ mflags="$origflags"
+ else
+ mflags="$matchflags"
+ fi
+ tmp1=( "${(@M)matches:#${~mflags}${~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] ]]
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author