From c183ca22de6667c7e24b591cfed19dd41936ca82 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 28 Oct 2013 17:05:57 -0300 Subject: [PATCH] Adapted Valodim's capture completion script to implement a simple completion service --- autosuggestions.zsh | 4 +- completion-service-init.zsh | 116 ++++++++++++++++++++++++++++++++++++ completion-service.zsh | 28 +++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 completion-service-init.zsh create mode 100755 completion-service.zsh diff --git a/autosuggestions.zsh b/autosuggestions.zsh index dd69a4e..7b62de9 100644 --- a/autosuggestions.zsh +++ b/autosuggestions.zsh @@ -146,11 +146,13 @@ paused-autosuggest-self-insert() { } autosuggest-first-completion() { + local cursor=$CURSOR zle .complete-word || return 1 + CURSOR=$cursor } show-suggestion() { - [[ $LBUFFER == '' ]] && return + [[ -n $ZLE_DISABLE_AUTOSUGGEST || $LBUFFER == '' ]] && return # TODO need a way to reset HISTNO so .history-beginning-search-backward # will always retrieve the last matching history entry # unset HISTNO diff --git a/completion-service-init.zsh b/completion-service-init.zsh new file mode 100644 index 0000000..6b997f7 --- /dev/null +++ b/completion-service-init.zsh @@ -0,0 +1,116 @@ +# Based on: +# https://github.com/Valodim/zsh-capture-completion/blob/master/.zshrc + +# no prompt! +PROMPT= + +# load completion system +autoload compinit +compinit + +# never run a command +bindkey '\C-m' .kill-buffer +bindkey '\C-j' .kill-buffer +bindkey '\C-i' complete-word + +# send an emtpy line before completions are output +empty-line() { + print + # handler needs to reinsert itself after being called + compprefuncs+=empty-line +} +compprefuncs+=empty-line + +# send a line with null-byte after completions are output +null-line() { + print $'\0' + # handler needs to reinsert itself after being called + comppostfuncs+=null-line +} +comppostfuncs+=null-line + +zstyle ':completion:*' completer _complete +# never group stuff! +zstyle ':completion:*' list-grouped false +# don't insert tab when attempting completion on empty line +zstyle ':completion:*' insert-tab false +# no list separator, this saves some stripping later on +zstyle ':completion:*' list-separator '' +# dont use matchers +zstyle -d ':completion:*' matcher-list + +# we use zparseopts +zmodload zsh/zutil + +# override compadd (this our hook) +compadd () { + + # check if any of -O, -A or -D are given + if [[ ${@[1,(i)(-|--)]} == *-(O|A|D)\ * ]]; then + # if that is the case, just delegate and leave + builtin compadd "$@" + return $? + fi + + # be careful with namespacing here, we don't want to mess with stuff that + # should be passed to compadd! + typeset -a __hits __dscr __tmp + + # do we have a description parameter? + # note we don't use zparseopts here because of combined option parameters + # with arguments like -default- confuse it. + if (( $@[(I)-d] )); then # kind of a hack, $+@[(r)-d] doesn't work because of line noise overload + # next param after -d + __tmp=${@[$[${@[(i)-d]}+1]]} + # description can be given as an array parameter name, or inline () array + if [[ $__tmp == \(* ]]; then + eval "__dscr=$__tmp" + else + __dscr=( "${(@P)__tmp}" ) + fi + fi + + # capture completions by injecting -A parameter into the compadd call. + # this takes care of matching for us. + builtin compadd -A __hits -D __dscr "$@" + + # JESUS CHRIST IT TOOK ME FOREVER TO FIGURE OUT THIS OPTION WAS SET AND WAS MESSING WITH MY SHIT HERE + setopt localoptions norcexpandparam extendedglob + + # extract prefixes and suffixes from compadd call. we can't do zsh's cool + # -r remove-func magic, but it's better than nothing. + typeset -A apre hpre hsuf asuf + zparseopts -E P:=apre p:=hpre S:=asuf s:=hsuf + + # append / to directories? we are only emulating -f in a half-assed way + # here, but it's better than nothing. + integer dirsuf=0 + # don't be fooled by -default- >.> + if [[ -z $hsuf && "${${@//-default-/}% -# *}" == *-[[:alnum:]]#f* ]]; then + dirsuf=1 + fi + + # just drop + [[ -n $__hits ]] || return + + # this is the point where we have all matches in $__hits and all + # descriptions in $__dscr! + + # display all matches + local dsuf dscr + for i in {1..$#__hits}; do + + # add a dir suffix? + (( dirsuf )) && [[ -d $__hits[$i] ]] && dsuf=/ || dsuf= + # description to be displayed afterwards + # (( $#__dscr >= $i )) && dscr=" -- ${${__dscr[$i]}##$__hits[$i] #}" || dscr= + + print $IPREFIX$apre$hpre$__hits[$i]$dsuf$hsuf$asuf$dscr + + done + + unset __hits __dscr __tmp +} + +# signal the daemon we are ready for input +print $'\0' diff --git a/completion-service.zsh b/completion-service.zsh new file mode 100755 index 0000000..8092e09 --- /dev/null +++ b/completion-service.zsh @@ -0,0 +1,28 @@ +#!/bin/zsh +# Based on: +# https://github.com/Valodim/zsh-capture-completion/blob/master/capture.zsh + +zmodload zsh/zpty +setopt noglob + +zpty z ZLE_DISABLE_AUTOSUGGEST=1 zsh -i + +# Source the init script +zpty -w z "source '${0:a:h}/completion-service-init.zsh'" + +read-to-null() { + while zpty -r z chunk; do + [[ $chunk == *$'\0'* ]] && break + print -n $chunk + done +} + +# wait for ok from shell +read-to-null &> /dev/null + +while read prefix &> /dev/null; do + zpty -w -n z $prefix$'\t' + zpty -r z chunk &> /dev/null # read empty line before completions + read-to-null + zpty -w z $'\n' +done