diff --git a/fzf-tab.zsh b/fzf-tab.zsh index 0761058..5f3b3c4 100644 --- a/fzf-tab.zsh +++ b/fzf-tab.zsh @@ -88,14 +88,7 @@ builtin unalias -m '[^+]*' fi # tell zsh that the match is successful - builtin compadd -U -qS '' -R -ftb-remove-space '' -} - -# when insert multi results, a whitespace will be added to each result -# remove left space of our fake result because I can't remove right space -# FIXME: what if the left char is not whitespace: `echo $widgets[\t` --ftb-remove-space() { - [[ $LBUFFER[-1] == ' ' ]] && LBUFFER[-1]='' + builtin compadd "$@" } -ftb-zstyle() { @@ -103,7 +96,6 @@ builtin unalias -m '[^+]*' } -ftb-complete() { - local -a _ftb_compcap local -Ua _ftb_groups local choice choices _ftb_curcontext continuous_trigger print_query accept_line bs=$'\2' nul=$'\0' local ret=0 @@ -131,6 +123,16 @@ builtin unalias -m '[^+]*' fi ;; *) + + if (( ! _ftb_continue_last )) \ + && [[ $compstate[insert] == *"unambiguous" ]] \ + && [[ "$compstate[unambiguous]" != "$PREFIX" ]]; then + compstate[list]= + compstate[insert]=unambiguous + _ftb_finish=1 + return 0 + fi + -ftb-generate-query # sets `_ftb_query` -ftb-generate-header # sets `_ftb_headers` -ftb-zstyle -s print-query print_query || print_query=alt-enter @@ -152,9 +154,10 @@ builtin unalias -m '[^+]*' compstate[list]= compstate[insert]= if (( $#choices[1] > 0 )); then - compstate[insert]='2' + compstate[insert]='1' [[ $RBUFFER == ' '* ]] || compstate[insert]+=' ' fi + _ftb_finish=1 return $ret fi choices[1]=() @@ -175,7 +178,17 @@ builtin unalias -m '[^+]*' fi choices[1]=() - for choice in "$choices[@]"; do + _ftb_choices=("${(@)choices}") + + compstate[list]= + compstate[insert]= + + return $ret +} + +_fzf-tab-apply() { + local choice bs=$'\2' + for choice in "$_ftb_choices[@]"; do local -A v=("${(@0)${_ftb_compcap[(r)${(b)choice}$bs*]#*$bs}}") local -a args=("${(@ps:\1:)v[args]}") [[ -z $args[1] ]] && args=() # don't pass an empty string @@ -184,14 +197,12 @@ builtin unalias -m '[^+]*' done compstate[list]= - compstate[insert]= - if (( $#choices == 1 )); then - compstate[insert]='2' + if (( $#_ftb_choices == 1 )); then + compstate[insert]='1' [[ $RBUFFER == ' '* ]] || compstate[insert]+=' ' - elif (( $#choices > 1 )); then + elif (( $#_ftb_choices > 1 )); then compstate[insert]='all' fi - return $ret } fzf-tab-debug() { @@ -221,11 +232,14 @@ fzf-tab-complete() { # NOTE: MacOS Terminal doesn't support civis & cnorm echoti civis >/dev/tty 2>/dev/null while (( _ftb_continue )); do + local _ftb_choices=() _ftb_compcap=() _ftb_finish=0 _ftb_continue=0 local IN_FZF_TAB=1 { - zle .fzf-tab-orig-$_ftb_orig_widget - ret=$? + zle .fzf-tab-orig-$_ftb_orig_widget || ret=$? + if (( ! ret && ! _ftb_finish )); then + zle _fzf-tab-apply || ret=$? + fi } always { IN_FZF_TAB=0 } @@ -249,6 +263,9 @@ fzf-tab-dummy() { } zle -N fzf-tab-debug zle -N fzf-tab-complete zle -N fzf-tab-dummy +# this is registered as a completion widget +# so that we can have a clean completion list to only insert the results user selected +zle -C _fzf-tab-apply complete-word _fzf-tab-apply disable-fzf-tab() { emulate -L zsh -o extended_glob diff --git a/test/fzftab.ztst b/test/fzftab.ztst index 98028f3..b4aad4e 100644 --- a/test/fzftab.ztst +++ b/test/fzftab.ztst @@ -60,6 +60,20 @@ >C1:{file1} >C1:{file2} + comptest $': d\t' +0:unambiguous prefix +>line: {: dir}{} + + comptesteval '_tst() { compadd /home /usr /lib; compstate[insert]=menu }' + comptest $'tst \t' +0:force list +>line: {tst /home }{} +>QUERY:{/} +>C0:{/home} +>C0:{/lib} +>C0:{/usr} + + comptesteval 'zstyle ":completion:*" menu true' comptest $': d\t' 0:prefix >line: {: dir1/}{} @@ -108,8 +122,8 @@ 0:warnings >line: {: asd}{} >WARN:{`file'} ->WARN:{`file'} -# FIXME:why two warnings? + +# enclose ' for syntax highlight comptesteval "touch 'abc def'" comptest $': ./a\t' @@ -148,7 +162,6 @@ comptest $'git add dir1\t' 0:add empty word >line: {git add dir1/}{} -# FIXME:why two warnings? comptesteval "zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*'" comptesteval "touch vim.coc" diff --git a/test/select b/test/select index d06d4e9..60c88b6 100755 --- a/test/select +++ b/test/select @@ -2,8 +2,12 @@ zmodload zsh/zutil -local -A headers range query +local -A headers range query expect +# -h: lines of headers +# -n: selection index, if it is QUERY, query string will be used +# -q: query string +# -e: expect key zparseopts -E h:=headers n:=range q:=query e:=expect print -r -- "${query//\"/}"