git 在 zsh 中完成:__git_func_wrap:3: : 未找到
git completion in zsh: __git_func_wrap:3: : not found
当 运行 brew install git
: 时自动安装 git-completion.zsh
和 git-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
}
默认补全是什么:
❯ 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
中找不到这个函数
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
功能在哪里?
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
在您的评论中,您写道,您已经安装了来自 https://github.com/git/git/blob/master/contrib/completion/git-completion.bash , but for zsh, the correct sources should be the ones at https://github.com/git/git/blob/master/contrib/completion/git-completion.zsh
的完成系统
根据安装说明:git-completion.zsh 必须来自 .zshrc。 bash 版本必须可以从中访问。
TL;DR
这是 tig
完成定义的问题,而不是 git
完成定义的问题。
在 tig
上激活完成会中断 git
上的完成。
- 如果
tig
在 git
之后被激活,那么 tig
完成工作并且 git
完成被破坏。
- 如果
tig
完成在git
之前激活,那么它们都坏了。
缓解措施:
安装旧版本的完成脚本。
取消链接 _tig 和 tig-completion.bash in /usr/local/share/zsh/site-functions
并替换为这些旧版本。下载时将tig-completion.zsh
重命名为_tig
。
- https://raw.githubusercontent.com/jonas/tig/91912eb97da4f6907015dab41ef9bba315730854/contrib/tig-completion.zsh
- https://raw.githubusercontent.com/jonas/tig/c72aa4dab21077231a97dcca8e3821d7b35fe7db/contrib/tig-completion.bash
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“变坏了”。我其实有三个状态
- 初始状态。在职的。
complete
未定义。
% which complete
- 在为
complete
创建定义的第一个 Tab 完成后仍在工作
% 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
}
- 不工作。
complete
函数定义引用 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: 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
}
研究
完成()函数:
取消设置完整功能 unset -f complete
并不能神奇地修复它。我想这可能会让我无法完成 git?
虚拟环境
我跳进跳出虚拟环境,并认为这是相关的,但是跳进跳出并手动设置 VIRTUAL_ENV 等的受控示例并没有流血并影响完成系统。
分心,无关
局部变量
进一步挖掘我发现在第三种情况下设置了很多局部变量,“坏shell”。
我删除了这些局部变量,但没有任何积极影响:
% unset REPLY
% unset __git_repo_path
% unset __tig_commands
% unset __tig_options
% unset _ack_raw_types
% unset $_cmd_variant
% unset _cmd_variant
tig
进步了!我可以通过在 tig 上调用完成从状态 1 移动到状态 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 完成相关的中断状态:
% 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*
site-functions git 的 Brew 来源,tig
- tig 版本 2.5.1 的 tig 完成数
- git 从 git 版本 2.28.0
完成
% 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
Tig 在 /usr/local/share/zsh/site-functions
中完成
_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 e
e=$(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=
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
函数包含:
__git_complete ()
{
local wrapper="__git_wrap"
eval "$wrapper () { __git_func_wrap ; }"
}
tig的新代码是这样调用的:
__git_complete tig _tig
此代码有效地创建了一个名为 __git_wrap_tig
的包装器。
__git_wrap_tig { __git_func_wrap _tig }
但是,这些函数并不是要被 Zsh 补全使用的。
Zsh 补全(最新版本 here)旨在自行获取 bash 补全,然后直接调用 __tig_main
,绕过任何包装器。
问题是主要的 tig 函数 必须 被调用 __tig_main
,而不是 _tig
。我已发送 a patch 来修复此问题以及其他与官方 git 完成的差异。
如果您安装所有最新的相关文件:
进入您的 fpath
(例如 ~/.zsh/
),它应该可以正常工作。
brew install git
: 时自动安装 git-completion.zsh
和 git-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
}
默认补全是什么:
❯ 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
中找不到这个函数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
功能在哪里?
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
在您的评论中,您写道,您已经安装了来自 https://github.com/git/git/blob/master/contrib/completion/git-completion.bash , but for zsh, the correct sources should be the ones at https://github.com/git/git/blob/master/contrib/completion/git-completion.zsh
的完成系统根据安装说明:git-completion.zsh 必须来自 .zshrc。 bash 版本必须可以从中访问。
TL;DR
这是 tig
完成定义的问题,而不是 git
完成定义的问题。
在 tig
上激活完成会中断 git
上的完成。
- 如果
tig
在git
之后被激活,那么tig
完成工作并且git
完成被破坏。 - 如果
tig
完成在git
之前激活,那么它们都坏了。
缓解措施:
安装旧版本的完成脚本。
取消链接 _tig 和 tig-completion.bash in /usr/local/share/zsh/site-functions
并替换为这些旧版本。下载时将tig-completion.zsh
重命名为_tig
。
- https://raw.githubusercontent.com/jonas/tig/91912eb97da4f6907015dab41ef9bba315730854/contrib/tig-completion.zsh
- https://raw.githubusercontent.com/jonas/tig/c72aa4dab21077231a97dcca8e3821d7b35fe7db/contrib/tig-completion.bash
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“变坏了”。我其实有三个状态
- 初始状态。在职的。
complete
未定义。% which complete
- 在为
complete
创建定义的第一个 Tab 完成后仍在工作% 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 }
- 不工作。
complete
函数定义引用 bashcomplete () { 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 }
研究
完成()函数:
取消设置完整功能 unset -f complete
并不能神奇地修复它。我想这可能会让我无法完成 git?
虚拟环境
我跳进跳出虚拟环境,并认为这是相关的,但是跳进跳出并手动设置 VIRTUAL_ENV 等的受控示例并没有流血并影响完成系统。
分心,无关
局部变量
进一步挖掘我发现在第三种情况下设置了很多局部变量,“坏shell”。
我删除了这些局部变量,但没有任何积极影响:
% unset REPLY
% unset __git_repo_path
% unset __tig_commands
% unset __tig_options
% unset _ack_raw_types
% unset $_cmd_variant
% unset _cmd_variant
tig
进步了!我可以通过在 tig 上调用完成从状态 1 移动到状态 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 完成相关的中断状态:
% 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*
site-functions git 的 Brew 来源,tig
- tig 版本 2.5.1 的 tig 完成数
- git 从 git 版本 2.28.0 完成
% 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
Tig 在 /usr/local/share/zsh/site-functions
中完成
_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 e e=$(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= 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
函数包含:
__git_complete ()
{
local wrapper="__git_wrap"
eval "$wrapper () { __git_func_wrap ; }"
}
tig的新代码是这样调用的:
__git_complete tig _tig
此代码有效地创建了一个名为 __git_wrap_tig
的包装器。
__git_wrap_tig { __git_func_wrap _tig }
但是,这些函数并不是要被 Zsh 补全使用的。
Zsh 补全(最新版本 here)旨在自行获取 bash 补全,然后直接调用 __tig_main
,绕过任何包装器。
问题是主要的 tig 函数 必须 被调用 __tig_main
,而不是 _tig
。我已发送 a patch 来修复此问题以及其他与官方 git 完成的差异。
如果您安装所有最新的相关文件:
进入您的 fpath
(例如 ~/.zsh/
),它应该可以正常工作。