From d5c5a1f9874c62f12788cb4f3c08c1926935633c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 25 Mar 2009 13:27:58 +0000 Subject: 26783: new _user_expand completer --- Completion/Base/Completer/.distfiles | 17 +++- Completion/Base/Completer/_user_expand | 141 +++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 Completion/Base/Completer/_user_expand (limited to 'Completion/Base') diff --git a/Completion/Base/Completer/.distfiles b/Completion/Base/Completer/.distfiles index 5fd0e6071..3030142de 100644 --- a/Completion/Base/Completer/.distfiles +++ b/Completion/Base/Completer/.distfiles @@ -1,6 +1,17 @@ DISTFILES_SRC=' .distfiles -_all_matches _correct _history _match _prefix -_approximate _expand _ignored _menu -_complete _expand_alias _list _oldlist +_all_matches +_approximate +_complete +_correct +_expand +_expand_alias +_history +_ignored +_list +_match +_menu +_oldlist +_prefix +_user_expand ' diff --git a/Completion/Base/Completer/_user_expand b/Completion/Base/Completer/_user_expand new file mode 100644 index 000000000..049cc31ef --- /dev/null +++ b/Completion/Base/Completer/_user_expand @@ -0,0 +1,141 @@ +#autoload + +# This completer function is an addition to the _expand completer that +# allows the user to define their own expansions. It does not replace +# the _expand completer. +# +# 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. + +setopt localoptions nonomatch + +[[ _matcher_num -gt 1 ]] && return 1 + +local exp word sort expr expl subd suf=" " asp tmp spec +local -a specs reply + +if [[ "$funcstack[2]" = _prefix ]]; then + word="$IPREFIX$PREFIX$SUFFIX" +else + word="$IPREFIX$PREFIX$SUFFIX$ISUFFIX" +fi + +# In exp we will collect the expansions. + +exp=("$word") + +# Now look for user completions. + +zstyle -a ":completion:${curcontext}" user-expand specs || return 1 + +for spec in $specs; do + case $spec in + ('$'[[:IDENT:]]##) + # Spec is an associative array with explicit keys. + # Surely there's a better way of doing an associative array + # lookup from its name? + eval tmp='${'$spec[2,-1]'[$word]}' + if [[ -n $tmp ]]; then + exp=("$tmp") + break + fi + ;; + + ('_'*) + reply=() + $spec $word + if (( ${#reply} )); then + exp=("${reply[@]}") + break + fi + ;; + esac +done + +[[ $#exp -eq 1 && "$exp[1]" = "$word" ]] && return 1 + +# Now add as matches whatever the user requested. + +zstyle -s ":completion:${curcontext}:" sort sort + +[[ "$sort" = (yes|true|1|on) ]] && exp=( "${(@o)exp}" ) + +if zstyle -s ":completion:${curcontext}:" add-space tmp; then + if [[ "$tmp" != *subst* || "$word" != *\$* || "$exp[1]" = *\$* ]]; then + [[ "$tmp" = *file* ]] && asp=file + [[ "$tmp" = *(yes|true|1|on|subst)* ]] && asp="yes$asp" + fi +else + asp=file +fi + +# If there is only one expansion, add a suitable suffix + +if (( $#exp == 1 )); then + if [[ -d ${exp[1]} && "$exp[1]" != */ ]]; then + suf=/ + elif [[ "$asp" = yes* || + ( "$asp" = *file && -f "${exp[1]}" ) ]]; then + suf=' ' + else + suf= + fi +fi + +if [[ -z "$compstate[insert]" ]] ;then + if [[ "$sort" = menu ]]; then + _description expansions expl expansions "o:$word" + else + _description -V expansions expl expansions "o:$word" + fi + + compadd "$expl[@]" -UQ -qS "$suf" -a exp +else + _tags all-expansions expansions original + + if [[ $#exp -gt 1 ]] && _requested expansions; then + local i j normal space dir + + if [[ "$sort" = menu ]]; then + _description expansions expl expansions "o:$word" + else + _description -V expansions expl expansions "o:$word" + fi + normal=() + space=() + dir=() + + for i in "$exp[@]"; do + j="${i}" + if [[ -d "$j" && "$i" != */ ]]; then + dir=( "$dir[@]" "$i" ) + elif [[ "$asp" = yes* || ( "$asp" = *file && -f "$j" ) ]]; then + space=( "$space[@]" "$i" ) + else + normal=( "$normal[@]" "$i" ) + fi + done + (( $#dir )) && compadd "$expl[@]" -UQ -qS/ -a dir + (( $#space )) && compadd "$expl[@]" -UQ -qS " " -a space + (( $#normal )) && compadd "$expl[@]" -UQ -qS "" -a normal + fi + if _requested all-expansions expl 'all expansions'; then + local disp dstr + + if [[ "${#${exp}}" -ge COLUMNS ]]; then + disp=( -ld dstr ) + dstr=( "${(r:COLUMNS-5:)exp} ..." ) + else + disp=() + fi + [[ -o multios ]] && exp=($exp[1] $compstate[redirect]${^exp[2,-1]}) + compadd "$disp[@]" "$expl[@]" -UQ -qS "$suf" - "$exp" + fi + + _requested original expl original && compadd "$expl[@]" -UQ - "$word" + + compstate[insert]=menu +fi + +return 0 -- cgit 1.4.1