# Autoload this function, run `zle -N ' and bind # to a key. # This allows incremental completion of a word. After starting this # command, a list of completion choices can be shown after every character # you type, which you can delete with ^h or DEL. RET will accept the # completion so far. You can hit TAB to do normal completion, ^g to # abort back to the state when you started, and ^d to list the matches. # # This works best with the new function based completion system. # # Configuration keys: # # incremental_prompt # Prompt to show in status line during icompletion. The sequence `%u' # is replaced by the unambiguous part of all matches if there is any # and it is different from the word on the line. A `%s' is replaced # with `-no match-', `-no prefix-', or an empty string if there is # no completion matching the word on the line, if the matches have # no common prefix different from the word on the line or if there is # such a common prefix, respectively. The sequence `%c' is replaced # by the name of the completer function that generated the matches # (without the leading underscore). Finally, `%n' is replaced by the # number of matches generated, `%a' is replaced by an empty string # if the matches are in the normal set (i.e. the one without file names # with one of the suffixes from `fignore') and with ` -alt-' if the # matches are in the alternate set, and if the `incremental_list' key # (see below) is set, `%l' is replaced by `...' if the list of matches # is too long to fit on the screen and with an empty string otherwise. # # incremental_stop # Pattern matching keys which will cause icompletion to stop and the # key to be re-executed. # # incremental_break # Pattern matching keys which will cause icompletion to stop and the # key to be discarded. # # incremental_completer # Set of completers, like the `completer' key for normal completion. # # incremental_list # If set to a non-empty string, the matches will be listed on every # key-press. # The main widget function. incremental-complete-word() { emulate -L zsh unsetopt autolist menucomplete automenu # doesn't work well local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word local lastl lastr wid twid num alt post toolong [[ -n "$compconfig[incremental_completer]" ]] && set ${(s.:.)compconfig[incremental_completer]} pmpt="${compconfig[incremental_prompt]-incremental (%c): %u%s %l}" if [[ -n "$compconfig[incremental_list]" ]]; then wid=list-choices post=( icw-list-helper ) else wid=complete-word post=() fi comppostfuncs=( "$post[@]" ) zle $wid "$@" LBUFFER="$lbuf" RBUFFER="$rbuf" num=$_lastcomp[nmatches] if (( ! num )); then num="${_lastcomp[alternate_nmatches]}" alt=' -alt-' fi if (( ! num )); then word='' state='-no match-' elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then word='' state='-no prefix-' else word="${_lastcomp[unambiguous]}" state='' fi zle -R "${${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}//\\%l/$toolong}" read -k key while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' && '#key' -ne '#\\C-g' ]]; do twid=$wid if [[ "$key" = ${~compconfig[incremental_stop]} ]]; then zle -U "$key" return elif [[ "$key" = ${~compconfig[incremental_break]} ]]; then return elif [[ '#key' -eq '#\\C-h' || '#key' -eq '#\\C-?' ]]; then [[ $#LBUFFER -gt $#l ]] && LBUFFER="$LBUFFER[1,-2]" elif [[ '#key' -eq '#\\t' ]]; then zle complete-word "$@" lbuf="$LBUFFER" rbuf="$RBUFFER" elif [[ '#key' -eq '#\\C-d' ]]; then twid=list-choices else LBUFFER="$LBUFFER$key" fi lastl="$LBUFFER" lastr="$RBUFFER" [[ "$twid" = "$wid" ]] && comppostfuncs=( "$post[@]" ) toolong='' zle $twid "$@" LBUFFER="$lastl" RBUFFER="$lastr" num=$_lastcomp[nmatches] if (( ! num )); then num="${_lastcomp[alternate_nmatches]}" alt=' -alt-' else alt='' fi if (( ! num )); then word='' state='-no match-' elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then word='' state='-no prefix-' else word="${_lastcomp[unambiguous]}" state='' fi zle -R "${${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}//\\%l/$toolong}" read -k key done if [[ '#key' -eq '#\\C-g' ]]; then LBUFFER="$lbuf" RBUFFER="$rbuf" fi zle -Rc } # Helper function used as a completion post-function used to make sure that # the list of matches in only shown if it fits on the screen. icw-list-helper() { # +1 for the status line we will add... if [[ compstate[list_lines]+BUFFERLINES+1 -gt LINES ]]; then compstate[list]='list explanations' if [[ compstate[list_lines]+BUFFERLINES+1 -gt LINES ]]; then compstate[list]='' compstate[force_list]=yes fi toolong='...' fi } incremental-complete-word "$@"