1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
# multicomp() {
# Completes all manner of files given prefixes for each path segment.
# e.g. s/z/s -> src/zsh-2.4/src
#
# Usage: e.g.
# compctl -D -f + -U -K multicomp
#
# Note that exactly matched directories are not expanded, e.g.
# s/zsh-2.4/s<TAB> will not expand to src/zsh-2.4old/src.
# Will expand glob patterns already in the word, but use complete-word,
# not TAB (expand-or-complete), or you will get ordinary glob expansion.
# Requires the -U option to compctl.
# Menucompletion is highly recommended for ambiguous matches.
# Liable to screw up escaped metacharacters royally.
# $fignore is not used: feel free to add your own bit.
emulate -R zsh # Requires zsh 3.0-pre4 or later
local pref head sofar origtop newtop globdir="(-/)" wild
setopt localoptions nullglob rcexpandparam globdots
unsetopt markdirs globsubst shwordsplit nounset
pref="${1}$2"
# Hack to allow programmable completion to select multicomp after a :
# (e.g.
# compctl -D -f -x 's[:]' -U -K multicomp
# )
pref="${pref#:}"
sofar=('')
reply=('')
if [[ "$pref" = \~* ]]; then
# If the string started with ~, save the head and what it will become.
origtop="${pref%%/*}"
newtop=${~origtop}
# Save the expansion as the bit matched already
sofar=($newtop)
pref="${pref#$origtop}"
fi
while [[ -n "$pref" ]]; do
[[ "$pref" = /* ]] && sofar=(${sofar}/) && pref="${pref#/}"
head="${pref%%/*}"
pref="${pref#$head}"
if [[ -n "$pref" && -z $sofar[2] && -d "${sofar}$head" ]]; then
# Exactly matched directory: don't try to glob
reply=("${sofar}$head")
else
[[ -z "$pref" ]] && globdir=
# if path segment contains wildcards, don't add another.
if [[ "$head" = *[\*\?]* ]]; then
wild=
else
wild='*'
fi
reply=(${sofar}"${head}${wild}${globdir}")
reply=(${~reply})
fi
[[ -z $reply[1] ]] && reply=() && break
[[ -n $pref ]] && sofar=($reply)
done
# Restore ~'s in front if there were any.
# There had better not be anything funny in $newtop.
[[ -n "$origtop" ]] && reply=("$origtop"${reply#$newtop})
# }
|