From 2c2d0844457eeec17cb3d9d65108ed0822646e99 Mon Sep 17 00:00:00 2001 From: Aloxaf Date: Tue, 10 Mar 2020 13:11:54 +0800 Subject: [PATCH 1/4] Add support of _approximate completer --- fzf-tab.zsh | 58 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/fzf-tab.zsh b/fzf-tab.zsh index 6f7598b8..d5d04c66 100644 --- a/fzf-tab.zsh +++ b/fzf-tab.zsh @@ -8,7 +8,7 @@ zmodload zsh/zutil # thanks Valodim/zsh-capture-completion -compadd() { +_fzf_tab_compadd() { # parse all options local -A apre hpre dscrs _oad expl local -a isfile _opts __ @@ -283,7 +283,7 @@ _fzf_tab_complete() { local choice choices _fzf_tab_curcontext continuous_trigger IN_FZF_TAB=1 - _fzf_tab_orig_main_complete # must run with user options; don't move `emulate -L zsh` above this line + _fzf_tab__main_complete # must run with user options; don't move `emulate -L zsh` above this line IN_FZF_TAB=0 emulate -L zsh -o extended_glob @@ -327,8 +327,9 @@ _fzf_tab_complete() { local -A v=("${(@0)${_fzf_tab_compcap[$choice]}}") local -a args=("${(@ps:\1:)v[args]}") [[ -z $args[1] ]] && args=() # don't pass an empty string + IPREFIX=$v[IPREFIX] PREFIX=$v[PREFIX] SUFFIX=$v[SUFFIX] ISUFFIX=$v[ISUFFIX] \ - builtin compadd "${args[@]:--Q}" -Q -- $v[word] + builtin compadd "${args[@]:--Q}" -U -Q -- $v[word] done compstate[list]= @@ -346,23 +347,44 @@ _fzf_tab_complete() { fi } -zle -C _fzf_tab_complete complete-word _fzf_tab_complete +_fzf_tab_hook() { + if [[ $1 == "-d" ]]; then + functions[$2]=$functions[_fzf_tab_$2] + return + fi + if [[ $functions[$1] == "builtin autoload"* || -z $functions[$1] ]]; then + autoload +XUz $1 + fi + functions[_fzf_tab_$1]=$functions[$1] +} fzf-tab-complete() { # this name must be ugly to avoid clashes local -i _fzf_tab_continue=1 while (( _fzf_tab_continue )); do _fzf_tab_continue=0 - if (( ${+functions[_main_complete]} )); then - # hack: hook _main_complete to trigger fzf-tab - functions[_fzf_tab_orig_main_complete]=${functions[_main_complete]} - function _main_complete() { _fzf_tab_complete } - { - zle .fzf-tab-orig-$_fzf_tab_orig_widget - } always { - functions[_main_complete]=$functions[_fzf_tab_orig_main_complete] - } - fi + + # hook _main_complete to trigger fzf-tab + _fzf_tab_hook _main_complete + function _main_complete() { _fzf_tab_complete } + + # _approximate will also hook compadd + # let it call _fzf_tab_compadd instead of builtin compadd so that fzf-tab can capture result + _fzf_tab_hook _approximate + functions[_fzf_tab__approximate]=${functions[_fzf_tab__approximate]//builtin compadd/_fzf_tab_compadd} + function _approximate() { + unfunction compadd + _fzf_tab__approximate + _fzf_tab_hook -d compadd + } + + { + zle .fzf-tab-orig-$_fzf_tab_orig_widget + } always { + _fzf_tab_hook -d _main_complete + _fzf_tab_hook -d _approximate + } + zle redisplay done } @@ -381,6 +403,9 @@ disable-fzf-tab() { esac unset _fzf_tab_orig_widget _fzf_tab_orig_list_groupded + # unhook compadd so that _approximate can work properply + unfunction compadd + # Don't remove .fzf-tab-orig-$_fzf_tab_orig_widget as we won't be able to reliably # create it if enable-fzf-tab is called again. } @@ -414,14 +439,13 @@ enable-fzf-tab() { fi fi - # Make sure _main_complete has been loaded because we will then hook it. - autoload +X _main_complete - zstyle -t ':completion:*' list-grouped false typeset -g _fzf_tab_orig_list_grouped=$? zstyle ':completion:*' list-grouped false bindkey '^I' fzf-tab-complete + + functions[compadd]=$functions[_fzf_tab_compadd] } toggle-fzf-tab() { From 8b5b195cfeb1ea7564beaec11007cd050b1a9569 Mon Sep 17 00:00:00 2001 From: Aloxaf Date: Tue, 10 Mar 2020 13:28:45 +0800 Subject: [PATCH 2/4] Simplify code --- fzf-tab.zsh | 54 +++++++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/fzf-tab.zsh b/fzf-tab.zsh index d5d04c66..16d003c4 100644 --- a/fzf-tab.zsh +++ b/fzf-tab.zsh @@ -347,44 +347,12 @@ _fzf_tab_complete() { fi } -_fzf_tab_hook() { - if [[ $1 == "-d" ]]; then - functions[$2]=$functions[_fzf_tab_$2] - return - fi - if [[ $functions[$1] == "builtin autoload"* || -z $functions[$1] ]]; then - autoload +XUz $1 - fi - functions[_fzf_tab_$1]=$functions[$1] -} - fzf-tab-complete() { # this name must be ugly to avoid clashes local -i _fzf_tab_continue=1 while (( _fzf_tab_continue )); do _fzf_tab_continue=0 - - # hook _main_complete to trigger fzf-tab - _fzf_tab_hook _main_complete - function _main_complete() { _fzf_tab_complete } - - # _approximate will also hook compadd - # let it call _fzf_tab_compadd instead of builtin compadd so that fzf-tab can capture result - _fzf_tab_hook _approximate - functions[_fzf_tab__approximate]=${functions[_fzf_tab__approximate]//builtin compadd/_fzf_tab_compadd} - function _approximate() { - unfunction compadd - _fzf_tab__approximate - _fzf_tab_hook -d compadd - } - - { - zle .fzf-tab-orig-$_fzf_tab_orig_widget - } always { - _fzf_tab_hook -d _main_complete - _fzf_tab_hook -d _approximate - } - + zle .fzf-tab-orig-$_fzf_tab_orig_widget zle redisplay done } @@ -406,6 +374,9 @@ disable-fzf-tab() { # unhook compadd so that _approximate can work properply unfunction compadd + functions[_main_complete]=$functions[_fzf_tab__main_complete] + functions[_approximate]=${functions[_fzf_tab__approximate]//_fzf_tab_compadd/builtin compadd} + # Don't remove .fzf-tab-orig-$_fzf_tab_orig_widget as we won't be able to reliably # create it if enable-fzf-tab is called again. } @@ -445,7 +416,24 @@ enable-fzf-tab() { zstyle ':completion:*' list-grouped false bindkey '^I' fzf-tab-complete + # make sure they have been loaded because we will then hook it. + autoload +X _main_complete _approximate + + # hook compadd functions[compadd]=$functions[_fzf_tab_compadd] + + # hook _main_complete to trigger fzf-tab + functions[_fzf_tab__main_complete]=$functions[_main_complete] + function _main_complete() { _fzf_tab_complete } + + # _approximate will also hook compadd + # let it call _fzf_tab_compadd instead of builtin compadd so that fzf-tab can capture result + functions[_fzf_tab__approximate]=${functions[_approximate]//builtin compadd/_fzf_tab_compadd} + function _approximate() { + unfunction compadd + _fzf_tab__approximate + functions[compadd]=$functions[_fzf_tab_compadd] + } } toggle-fzf-tab() { From 28c37fae195ccc991fc18de75f4835bb5fd29260 Mon Sep 17 00:00:00 2001 From: Aloxaf Date: Tue, 10 Mar 2020 13:51:03 +0800 Subject: [PATCH 3/4] Fix bug of _complete_help --- README.md | 2 -- README_CN.md | 2 -- fzf-tab.zsh | 16 ++++++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 42919718..59a36c0a 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,6 @@ See [zsh's doc](http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_ You can use C-x h to get possible context for a command: -**NOTE:** This command will break fzf-tab totally, you need to restart zsh to re-enable fzf-tab. - ```zsh ❯ rg -- # Press `C-x h` here tags in context :completion::complete:rg:: diff --git a/README_CN.md b/README_CN.md index 7267679f..3374c5eb 100644 --- a/README_CN.md +++ b/README_CN.md @@ -116,8 +116,6 @@ zstyle 的更多信息详见 [zsh's doc](http://zsh.sourceforge.net/Doc/Release/ 你可以使用 C-x h 来获取补全一个命令时可能的 context。 -**注意:** 这个命令会完全破坏掉 fzf-tab 的加载状态,只能通过重启 zsh 来再次激活。 - ```zsh ❯ rg -- # 按下 `C-x h` tags in context :completion::complete:rg:: diff --git a/fzf-tab.zsh b/fzf-tab.zsh index 16d003c4..abf0b65d 100644 --- a/fzf-tab.zsh +++ b/fzf-tab.zsh @@ -282,9 +282,7 @@ _fzf_tab_complete() { local -Ua _fzf_tab_groups local choice choices _fzf_tab_curcontext continuous_trigger - IN_FZF_TAB=1 _fzf_tab__main_complete # must run with user options; don't move `emulate -L zsh` above this line - IN_FZF_TAB=0 emulate -L zsh -o extended_glob @@ -352,7 +350,12 @@ fzf-tab-complete() { local -i _fzf_tab_continue=1 while (( _fzf_tab_continue )); do _fzf_tab_continue=0 - zle .fzf-tab-orig-$_fzf_tab_orig_widget + IN_FZF_TAB=1 + { + zle .fzf-tab-orig-$_fzf_tab_orig_widget + } always { + IN_FZF_TAB=0 + } zle redisplay done } @@ -417,7 +420,7 @@ enable-fzf-tab() { bindkey '^I' fzf-tab-complete # make sure they have been loaded because we will then hook it. - autoload +X _main_complete _approximate + autoload +XUz _main_complete _approximate # hook compadd functions[compadd]=$functions[_fzf_tab_compadd] @@ -430,9 +433,10 @@ enable-fzf-tab() { # let it call _fzf_tab_compadd instead of builtin compadd so that fzf-tab can capture result functions[_fzf_tab__approximate]=${functions[_approximate]//builtin compadd/_fzf_tab_compadd} function _approximate() { - unfunction compadd + # if not called by fzf-tab, don't do anything with compadd + (( ! IN_FZF_TAB )) || unfunction compadd _fzf_tab__approximate - functions[compadd]=$functions[_fzf_tab_compadd] + (( ! IN_FZF_TAB )) || functions[compadd]=$functions[_fzf_tab_compadd] } } From 8734f4db14cdda5b9e58942aa381c10dbd4e56ac Mon Sep 17 00:00:00 2001 From: Aloxaf Date: Tue, 10 Mar 2020 17:58:47 +0800 Subject: [PATCH 4/4] Fix bug when compleing parameter and add tests `-U` flag causes bug when compleing parameter. But remove it will let _approximate won't work. --- fzf-tab.zsh | 15 +++++++-------- test/fzftab.ztst | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/fzf-tab.zsh b/fzf-tab.zsh index abf0b65d..cae7cca1 100644 --- a/fzf-tab.zsh +++ b/fzf-tab.zsh @@ -327,7 +327,7 @@ _fzf_tab_complete() { [[ -z $args[1] ]] && args=() # don't pass an empty string IPREFIX=$v[IPREFIX] PREFIX=$v[PREFIX] SUFFIX=$v[SUFFIX] ISUFFIX=$v[ISUFFIX] \ - builtin compadd "${args[@]:--Q}" -U -Q -- $v[word] + builtin compadd "${args[@]:--Q}" -Q -- $v[word] done compstate[list]= @@ -377,7 +377,7 @@ disable-fzf-tab() { # unhook compadd so that _approximate can work properply unfunction compadd - functions[_main_complete]=$functions[_fzf_tab__main_complete] + functions -c _fzf_tab__main_complete _main_complete functions[_approximate]=${functions[_fzf_tab__approximate]//_fzf_tab_compadd/builtin compadd} # Don't remove .fzf-tab-orig-$_fzf_tab_orig_widget as we won't be able to reliably @@ -419,24 +419,23 @@ enable-fzf-tab() { zstyle ':completion:*' list-grouped false bindkey '^I' fzf-tab-complete - # make sure they have been loaded because we will then hook it. - autoload +XUz _main_complete _approximate - # hook compadd - functions[compadd]=$functions[_fzf_tab_compadd] + functions -c _fzf_tab_compadd compadd # hook _main_complete to trigger fzf-tab - functions[_fzf_tab__main_complete]=$functions[_main_complete] + functions -c _main_complete _fzf_tab__main_complete function _main_complete() { _fzf_tab_complete } # _approximate will also hook compadd # let it call _fzf_tab_compadd instead of builtin compadd so that fzf-tab can capture result + # make sure _approximate has been loaded. + autoload +XUz _approximate functions[_fzf_tab__approximate]=${functions[_approximate]//builtin compadd/_fzf_tab_compadd} function _approximate() { # if not called by fzf-tab, don't do anything with compadd (( ! IN_FZF_TAB )) || unfunction compadd _fzf_tab__approximate - (( ! IN_FZF_TAB )) || functions[compadd]=$functions[_fzf_tab_compadd] + (( ! IN_FZF_TAB )) || functions -c _fzf_tab_compadd compadd } } diff --git a/test/fzftab.ztst b/test/fzftab.ztst index 0ffa0d26..a7e65f69 100644 --- a/test/fzftab.ztst +++ b/test/fzftab.ztst @@ -152,6 +152,31 @@ >C1:{a} >C2:{b} + comptesteval 'tst_a=1; tst_b=2' + comptest $': $tst_\t' +0:variables +>line: {: $tst_a }{} +>QUERY:{tst_} +>DESCRIPTION:{parameter} +>C1:{tst_a} +>C1:{tst_b} + + comptesteval 'zstyle ":completion:*" completer _complete _approximate' + comptest $': drr1\t' +0:_approximate completer(file) +>line: {: dir1/}{} + + comptest $'ecoh\t' + comptesteval 'zstyle -d ":completion:*" completer' +0:_approximate completer(multiple result) +>line: {echo}{} +>QUERY:{echo} +>DESCRIPTION:{external command} +>DESCRIPTION:{builtin command} +>C2:{echo} +>C2:{echotc} +>C2:{echoti} + %clean zmodload -ui zsh/zpty