#compdef -k complete-word \C-x\C-r # This allows an on-the-fly choice of completions. On typing the key # sequence given above, you will be prompted for a string of arguments. If # this string begins with `_', it will be taken as the name of a function to # evaluate to generate the completions; unambiguous strings in the function # name are automatically completed. # # Else it is taken to be a set of arguments for compadd to generate a list # of choices. The possibilities are the same as the flags for generating # completions given in the zshcompwid manual page. Note the arguments are # verbatim: include minus signs, spaces, quotes, etc. # # On subsequent calls, the same completion will be re-performed. To # force a new type of completion to be read, supply a numeric argument. # # For example, # % bindkey | grep rever # Completion: -b # % bindkey | grep reverse-menu-complete _ # # Global variables used: # _read_comp Last completion string read from user # emulate -L zsh setopt localoptions extendedglob nobadpattern # xtrace promptsubst # local PS4='%N:%i:$((#key))> ' if [[ ${+NUMERIC} = 0 && -n $_read_comp ]]; then if [[ $_read_comp = _* ]]; then eval $_read_comp else eval "compadd $_read_comp" fi return fi _read_comp= local key search str str2 newch funcs funcs2 exact msg list integer pos msg="Completion: " zle -R $msg if ! read -k key; then zle -cR '' return 1 fi while [[ '#key' -ne 10 && '#key' -ne 13 ]]; do if [[ '#key' -eq 0 && '#key' -eq 3 || '#key' -eq 7 ]]; then zle -cR '' return 1 fi if [[ ( '#key' -eq 8 || '#key' -eq 127 ) && -n $str ]]; then # delete character str="$str[1,-2]" exact= list=() elif [[ '#key' -eq 21 ]]; then # ^U: delete line str= exact= list=() elif [[ '#key' -eq 4 && $str = _[^\ ]# && $str != *' '* ]]; then # ^D: list completions list=(${$(whence -m "$str*" 2>/dev/null)%: function}) elif [[ ( -n $exact && $key != ' ' ) || '#key & 127' -lt 32 ]]; then # If we've got an exact function, only allow a space after it. # Don't try to insert non-printing characters. if [[ -n $ZBEEP ]]; then print -nb $ZBEEP elif [[ -o beep ]]; then print -n "\a" fi list=() else str="$str$key" if [[ $str = _[^\ ]# ]]; then # Rudimentary completion for function names. # Allow arguments, i.e. don't do this after we've got a space. funcs=(${$(whence -m "$str*" 2>/dev/null)%: function}) if [[ -o autolist && $#str -gt 1 ]]; then list=($funcs) else list=() fi if (( $#funcs == 1 )); then # Exact match; prompt the user for a newline to confirm str=$funcs[1] exact=" (Confirm)" elif (( $#funcs == 0 )); then # We can't call zle beep, because this isn't a zle widget. if [[ -n $ZBEEP ]]; then print -nb $ZBEEP elif [[ -o beep ]]; then print -n "\a" fi str="$str[1,-2]" list=() else # Add characters to the string until a name doesn't # match any more, then backtrack one character to get # the longest unambiguous match. str2=$str pos=$#str2 while true; do (( pos++ )) newch=${funcs[1][pos]} [[ -z $newch ]] && break str2=$str2$newch funcs2=(${funcs##$str2*}) (( $#funcs2 )) && break str=$str2 done fi else exact= fi fi if (( $#list )); then zle -R "$msg$str$exact" $list else zle -cR "$msg$str$exact" fi if ! read -k key; then zle -cR '' return 1 fi done if [[ -z $str ]]; then # string must be non-zero return 1 elif [[ $str = _* ]] && ! whence ${str%% *} >& /dev/null; then # a function must be known to the shell return 1 else # remember the string for re-use _read_comp=$str fi zle -cR '' if [[ $str = _* ]]; then eval $str else eval "compadd $str" fi