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 --- ChangeLog | 5 +- Completion/Base/Completer/.distfiles | 17 +++- Completion/Base/Completer/_user_expand | 141 +++++++++++++++++++++++++++++++++ Doc/Zsh/compsys.yo | 43 ++++++++-- 4 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 Completion/Base/Completer/_user_expand diff --git a/ChangeLog b/ChangeLog index 31f4d6a45..7438d1e81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2009-03-25 Peter Stephenson + * 26783: Doc/Zsh/compsys.yo, Completion/Base/Completer/.distfiles, + Completion/Base/Completer/_user_expand: new _user_expand completer. + * Jon Strait: 26778, 26781: Doc/Zsh/mod_pcre.yo, Src/Modules/pcre.c: a couple of extra options for PCRE matching. @@ -11490,5 +11493,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4637 $ +* $Revision: 1.4638 $ ***************************************************** 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 diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 3bd5f008a..f7e47b1e1 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -202,6 +202,13 @@ to tt(fpath) as necessary. To force a check of exactly the directories currently named in tt(fpath), set tt(_compdir) to an empty string before calling tt(compaudit) or tt(compinit). +findex(bashcompinit) +The function tt(bashcompinit) compatibility with bash's programmable +completion system. When run it will define the functions, tt(compgen) and +tt(complete) which correspond to the bash builtins with the same names. +It will then be possible to use completion specifications and functions +written for bash. + subsect(Autoloaded files) cindex(completion system, autoloaded functions) @@ -3096,13 +3103,35 @@ tt(COMPLETE_IN_WORD) option is set; otherwise, the cursor will be moved to the end of the current word before the completion code is called and hence there will be no suffix. ) -findex(bashcompinit) -item(tt(bashcompinit))( -This function provides compatibility with bash's programmable completion -system. When run it will define the functions, tt(compgen) and -tt(complete) which correspond to the bash builtins with the same names. -It will then be possible to use completion specifications and functions -written for bash. +findex(_user_expand) +item(tt(_user_expand))( +This completer behaves similarly to the tt(_expand) completer but +instead performs expansions defined by users. The styles tt(add-space) and +tt(sort) styles specific to the tt(_expand) completer are usable with +tt(_user_expand) in addition to other styles handled more generally by +the completion system. The tag tt(all-expansions) is also available. + +The expansion depends on the array style tt(user-expand) being defined +for the current context; remember that the context for completers is less +specific than that for contextual completion as the full context has not +yet been determined. Elements of the array may have one of the following +forms: +startsitem() +sitem(tt($)var(hash))( +var(hash) is the name of an associative array. Note this is not a full +parameter expression, merely a tt($), suitably quoted to prevent immediate +expansion, followed by the name of an associative array. If the trial +expansion word matches a key in var(hash), the resulting expansion is the +corresponding value. +) +sitem(var(_func))( +var(_func) is the name of a shell function whose name must begin with +tt(_) but is not otherwise special to the completion system. The function +is called with the trial word as an argument. If the word is to be +expanded, the function should set the array tt(reply) to a list of +expansions. The return status of the function is irrelevant. +) +endsitem() ) enditem() -- cgit 1.4.1