簡體   English   中英

git 在 zsh 中完成:__git_func_wrap:3::未找到

[英]git completion in zsh: __git_func_wrap:3: : not found

運行brew install git時會自動安裝git-completion.zshgit-completion.bash

❯ ls -l /usr/local/share/zsh/site-functions/_git
lrwxr-xr-x 56 quanta  7 Jul 18:54 /usr/local/share/zsh/site-functions/_git -> ../../../Cellar/git/2.27.0/share/zsh/site-functions/_git

❯ ls -l /usr/local/share/zsh/site-functions/git-completion.bash
lrwxr-xr-x 71 quanta  7 Jul 18:54 /usr/local/share/zsh/site-functions/git-completion.bash -> ../../../Cellar/git/2.27.0/share/zsh/site-functions/git-completion.bash

/usr/local/share/zsh/site-functions包含在fpath中:

❯ echo $fpath
/usr/local/share/zsh-completions
/usr/local/share/zsh/site-functions
/usr/share/zsh/site-functions
/usr/share/zsh/5.7.1/functions

由於某些原因,有時當我輸入git reba並按tab時:

❯ git reba
__git_func_wrap:3: : not found
__git_func_wrap:3: : not found    

❯ type __git_func_wrap
__git_func_wrap is a shell function from /usr/local/share/zsh/site-functions/git-completion.bash

https://github.com/git/git/blob/master/contrib/completion/git-completion.bash#L3517-L3522

❯ grep -A5 '^__git_func_wrap' /usr/local/share/zsh/site-functions/git-completion.bash
__git_func_wrap ()
{
    local cur words cword prev
    _get_comp_words_by_ref -n =: cur words cword prev
    $1
}

默認完成是什么:

❯ complete -p git
complete -o bashdefault -o default -o nospace -F __git_wrap_tig tig
complete _bash bash

繼續檢查:

❯ type __git_wrap_tig
__git_wrap_tig is a shell function from /usr/local/share/zsh/site-functions/tig-completion.bash

問題是我在 tig -completion.bash中找不到這個 function

tig: stable 2.5.1 (bottled), HEAD
Text interface for Git repositories
https://jonas.github.io/tig/
/usr/local/Cellar/tig/2.5.1 (15 files, 875.9KB) *
  Poured from bottle on 2020-07-06 at 16:01:38
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/tig.rb
==> Dependencies
Required: readline ✔
==> Options
--HEAD
    Install HEAD version
==> Caveats
A sample of the default configuration has been installed to:
  /usr/local/opt/tig/share/tig/examples/tigrc
to override the system-wide default configuration, copy the sample to:
  /usr/local/etc/tigrc

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions

看起來最近有一些變化: https://github.com/jonas/tig/commit/26ab51d28133354bfaa94d064bff37d29b3c30e3

但是__git_wrap_tig function在哪里?

PS:正如我上面所說,這個問題並非每次都會發生。 有時,當我打開一個新選項卡並檢查默認完成時,它只是:

❯ complete -p git
complete _bash bash

git完成按預期工作。


回復@user1934428:

❯ grep '__git_complete ' /usr/local/share/zsh/site-functions/git-completion.bash
__git_complete ()
__git_complete git __git_main
__git_complete gitk __gitk_main
__git_complete git.exe __git_main

又一次調用__git_complete在 tig -completion.bash中:

# we use internal git-completion functions, so wrap _tig for all necessary
# variables (like cword and prev) to be defined
__git_complete tig _tig 

TL;博士

這是git tig定義的問題。

git tig完成。

  • 如果git tig激活,則git tig被破壞。
  • 如果在tig之前激活了git完成,那么它們都被破壞了。

減輕:

安裝舊版本的完成腳本。

/usr/local/share/zsh/site-functions中取消鏈接 _tig 和 tig-completion.bash 並替換為這些舊版本。 下載時將 tig tig-completion.zsh重命名為_tig

cd /usr/local/share/zsh/site-functions && \
rm -f _tig tig-completion.bash && \
wget -O _tig https://raw.githubusercontent.com/jonas/tig/91912eb97da4f6907015dab41ef9bba315730854/contrib/tig-completion.zsh && \
wget -O tig-completion.bash https://raw.githubusercontent.com/jonas/tig/c72aa4dab21077231a97dcca8e3821d7b35fe7db/contrib/tig-completion.bash

解決方案:

TODO:tig 的文件問題。 這是在jonas/tig#960中實現的新完成腳本的回歸

狀態:

我從 git 選項卡完成工作開始,然后在某個時候 shell “變壞了”。 我實際上有三個狀態

  1. 初始 state。 在職的。 complete未定義。
     % which complete
  2. 在創建完成定義的第一個選項卡complete后仍在工作
    % git <TAB> add -- add file contents to the index bisect -- find by binary search the change that introduced a bug... % which complete complete () { return 0 }
  3. 不工作。 complete的 function 定義參考 bash
     complete () { emulate -L zsh local args void cmd print remove args=("$@") zparseopts -D -a void o: A: G: W: C: F: P: S: X: ab c defgjkuvp=print r=remove if [[ -n $print ]] then printf 'complete %2$s %1$s\n' "${(@kv)_comps[(R)_bash*]#* }" elif [[ -n $remove ]] then for cmd do unset "_comps[$cmd]" done else compdef _bash_complete\ ${(j. .)${(q)args[1,-1-$#]}} "$@" fi }

研究

完成()function:

取消設置完整的 function unset -f complete並不能神奇地修復它。 我認為這可能會讓我無法完成 git?

虛擬環境

我跳進跳出虛擬環境,並認為這是相關的,但是跳進和跳出並手動設置 VIRTUAL_ENV 等的受控示例並沒有溢出並影響完成系統。

分心,不相關

局部變量

進一步挖掘,我發現在第三種情況下設置了很多局部變量,“bad shell”。

我刪除了這些局部變量中的每一個,但沒有任何積極影響:

% unset REPLY
% unset __git_repo_path
% unset __tig_commands
% unset __tig_options
% unset _ack_raw_types
% unset $_cmd_variant
% unset _cmd_variant

泰格

進度:我可以通過在 tig 上調用完成從 state 1 移動到 state 2:

% git <TAB>
add       -- add file contents to the index
bisect    -- find by binary search the change that introduced a bug
...
% tig <TAB>
% git <TAB>
__git_func_wrap:3: : not found

通過首先完成 tig 相關損壞的 state:

% tig <TAB>
__git_complete:5: command not found: complete
% which complete
complete () {
        emulate -L zsh
        local args void cmd print remove
        args=("$@")
        zparseopts -D -a void o: A: G: W: C: F: P: S: X: a b c d e f g j k u v p=print r=remove
        if [[ -n $print ]]
        then
                printf 'complete %2$s %1$s\n' "${(@kv)_comps[(R)_bash*]#* }"
        elif [[ -n $remove ]]
        then
                for cmd
                do
                        unset "_comps[$cmd]"
                done
        else
                compdef _bash_complete\ ${(j. .)${(q)args[1,-1-$#]}} "$@"
        fi
}
% git <TAB>
__git_func_wrap:3: : not found

fpath 和 tig 完成

% echo $fpath
/usr/local/share/zsh/site-functions /usr/share/zsh/site-functions /usr/share/zsh/5.7.1/functions

% for f in $fpath; do ls $f/*tig*; done | cat
/usr/local/share/zsh/site-functions/_tig
/usr/local/share/zsh/site-functions/tig-completion.bash
zsh: no matches found: /usr/share/zsh/site-functions/*tig*
zsh: no matches found: /usr/share/zsh/5.7.1/functions/*tig*

為 git、tig 的站點功能釀造源

  • 來自 tig 版本 2.5.1 的 tig 補全
  • git 版本 2.28.0 的 git 完成
% cd /usr/local/share/zsh/site-functions
% ls -l *tig*
_tig -> ../../../Cellar/tig/2.5.1/share/zsh/site-functions/_tig
tig-completion.bash -> ../../../Cellar/tig/2.5.1/share/zsh/site-functions/tig-completion.bash
% ls -l *git*
_git -> ../../../Cellar/git/2.28.0/share/zsh/site-functions/_git
git-completion.bash -> ../../../Cellar/git/2.28.0/share/zsh/site-functions/git-completion.bash

/usr/local/share/zsh/site-functions中的 Tig 完成

  • _tig
     #compdef tig # # zsh completion wrapper for tig # ============================== # # You need to install this script to zsh fpath with tig-completion.bash. # # The recommended way to install this script is to copy this and tig-completion.bash # to '~/.zsh/_tig' and '~/.zsh/tig-completion.bash' and # then add following to your ~/.zshrc file: # # fpath=(~/.zsh $fpath) _tig () { local ee=$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash if [ -f $e ]; then GIT_SOURCING_ZSH_COMPLETION=y. $e fi e=$(dirname ${funcsourcetrace[1]%:*})/tig-completion.bash if [ -f $e ]; then. $e fi }
  • tig-completion.bash
     #compdef git gitk # zsh completion wrapper for git # # Copyright (c) 2012-2013 Felipe Contreras <felipe.contreras@gmail.com> # # You need git's bash completion script installed somewhere, by default it # would be the location bash-completion uses. # # If your script is somewhere else, you can configure it on your ~/.zshrc: # # zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh # # The recommended way to install this script is to make a copy of it in # ~/.zsh/ directory as ~/.zsh/git-completion.zsh and then add the following # to your ~/.zshrc file: # # fpath=(~/.zsh $fpath) complete () { # do nothing return 0 } zstyle -T ':completion:*:*:git:*' tag-order && \ zstyle ':completion:*:*:git:*' tag-order 'common-commands' zstyle -s ":completion:*:*:git:*" script script if [ -z "$script" ]; then local -a locations local e locations=( $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash '/etc/bash_completion.d/git' # fedora, old debian '/usr/share/bash-completion/completions/git' # arch, ubuntu, new debian '/usr/share/bash-completion/git' # gentoo ) for e in $locations; do test -f $e && script="$e" && break done fi GIT_SOURCING_ZSH_COMPLETION=y. "$script" __gitcomp () { emulate -L zsh local cur_="${3-$cur}" case "$cur_" in --*=);; *) local c IFS=$' \t\n' local -a array for c in ${=1}; do c="$c${4-}" case $c in --*=*|*.);; *) c="$c ";; esac array+=("$c") done compset -P '*[=:]' compadd -Q -S '' -p "${2-}" -a -- array && _ret=0;; esac } __gitcomp_direct () { emulate -L zsh local IFS=$'\n' compset -P '*[=:]' compadd -Q -- ${=1} && _ret=0 } __gitcomp_nl () { emulate -L zsh local IFS=$'\n' compset -P '*[=:]' compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 } __gitcomp_nl_append () { emulate -L zsh local IFS=$'\n' compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 } __gitcomp_file_direct () { emulate -L zsh local IFS=$'\n' compset -P '*[=:]' compadd -f -- ${=1} && _ret=0 } __gitcomp_file () { emulate -L zsh local IFS=$'\n' compset -P '*[=:]' compadd -p "${2-}" -f -- ${=1} && _ret=0 } __git_zsh_bash_func () { emulate -L ksh local command=$1 local completion_func="_git_${command//-/_}" declare -f $completion_func >/dev/null && $completion_func && return local expansion=$(__git_aliased_command "$command") if [ -n "$expansion" ]; then words[1]=$expansion completion_func="_git_${expansion//-/_}" declare -f $completion_func >/dev/null && $completion_func fi } __git_zsh_cmd_common () { local -a list list=( add:'add file contents to the index' bisect:'find by binary search the change that introduced a bug' branch:'list, create, or delete branches' checkout:'checkout a branch or paths to the working tree' clone:'clone a repository into a new directory' commit:'record changes to the repository' diff:'show changes between commits, commit and working tree, etc' fetch:'download objects and refs from another repository' grep:'print lines matching a pattern' init:'create an empty Git repository or reinitialize an existing one' log:'show commit logs' merge:'join two or more development histories together' mv:'move or rename a file, a directory, or a symlink' pull:'fetch from and merge with another repository or a local branch' push:'update remote refs along with associated objects' rebase:'forward-port local commits to the updated upstream head' reset:'reset current HEAD to the specified state' restore:'restore working tree files' rm:'remove files from the working tree and from the index' show:'show various types of objects' status:'show the working tree status' switch:'switch branches' tag:'create, list, delete or verify a tag object signed with GPG') _describe -t common-commands 'common commands' list && _ret=0 } __git_zsh_cmd_alias () { local -a list list=(${${${(0)"$(git config -z --get-regexp '^alias\.')"}#alias.}%$'\n'*}) _describe -t alias-commands 'aliases' list $* && _ret=0 } __git_zsh_cmd_all () { local -a list emulate ksh -c __git_compute_all_commands list=( ${=__git_all_commands} ) _describe -t all-commands 'all commands' list && _ret=0 } __git_zsh_main () { local curcontext="$curcontext" state state_descr line typeset -A opt_args local -a orig_words orig_words=( ${words[@]} ) _arguments -C \ '(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ '(-p --paginate)--no-pager[do not pipe git output into a pager]' \ '--git-dir=-[set the path to the repository]: :_directories' \ '--bare[treat the repository as a bare repository]' \ '(-:)--version[prints the git suite version]' \ '--exec-path=-[path to where your core git programs are installed]:: :_directories' \ '--html-path[print the path where git''s HTML documentation is installed]' \ '--info-path[print the path where the Info files are installed]' \ '--man-path[print the manpath (see `man(1)`) for the man pages]' \ '--work-tree=-[set the path to the working tree]: :_directories' \ '--namespace=-[set the git namespace]' \ '--no-replace-objects[do not use replacement refs to replace git objects]' \ '(-:)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \ '(-): :->command' \ '(-)*:: :->arg' && return case $state in (command) _alternative \ 'alias-commands:alias:__git_zsh_cmd_alias' \ 'common-commands:common:__git_zsh_cmd_common' \ 'all-commands:all:__git_zsh_cmd_all' && _ret=0;; (arg) local command="${words[1]}" __git_dir if (( $+opt_args[--bare] )); then __git_dir='.' else __git_dir=${opt_args[--git-dir]} fi (( $+opt_args[--help] )) && command='help' words=( ${orig_words[@]} ) __git_zsh_bash_func $command;; esac } _git () { local _ret=1 local cur cword prev cur=${words[CURRENT]} prev=${words[CURRENT-1]} let cword=CURRENT-1 if (( $+functions[__${service}_zsh_main] )); then __${service}_zsh_main else emulate ksh -c __${service}_main fi let _ret && _default && _ret=0 return _ret } _git

__git_complete function 包含以下內容:

__git_complete ()
{
    local wrapper="__git_wrap${2}"
    eval "$wrapper () { __git_func_wrap $2 ; }"
}

tig 的新代碼這樣稱呼它:

__git_complete tig _tig 

此代碼有效地創建了一個名為__git_wrap_tig的包裝器。

__git_wrap_tig { __git_func_wrap _tig }

但是,這些函數並不打算由 Zsh 補全使用。

Zsh 補全( 此處為最新版本)旨在自行獲取 bash 補全,然后直接調用__tig_main ,繞過任何包裝器。

問題是主 tig function必須稱為__tig_main ,而不是_tig 我已經發送了一個補丁來修復這個和其他與官方 git 完成的差異。

如果您安裝所有最新的相關文件:

  1. git-completion.bash
  2. git-completion.zsh (作為_git)
  3. tig-completion.bash
  4. tig -completion.zsh (作為_tig)

進入您的fpath (例如~/.zsh/ ),它應該可以正常工作。

在您的評論中,您寫道,您已經從https://github.com/git/git/blob/master/contrib/completion/git-completion.bash安裝了完成系統,但是對於 zsh,正確的來源應該是https://github.com/git/git/blob/master/contrib/completion/git-completion.zsh

根據安裝說明:git-completion.zsh 必須來源於.zshrc。 必須可以從中訪問 bash 版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM