覆盖git克隆的bash完成 内置完成
默认设置(如下所示)为覆盖git克隆的bash完成 内置完成,bash,git,bash-completion,Bash,Git,Bash Completion,默认设置(如下所示)为-*选项提供选项卡完成: _git_clone () { case "$cur" in --*) __gitcomp_builtin clone return ;; esac } bash完成1.x(旧bash) (对于具体实例,macos high sierra+brew安装了bash completion/git) 在bash completion 1.x世界中,要覆盖此功能,我将(在.bashr
-*
选项提供选项卡完成:
_git_clone ()
{
case "$cur" in
--*)
__gitcomp_builtin clone
return
;;
esac
}
bash完成1.x(旧bash)
(对于具体实例,macos high sierra+brew安装了bash completion/git)
在bash completion 1.x世界中,要覆盖此功能,我将(在.bashrc
/.bash\u profile
中)定义自己的\u git\u clone
完成函数:
# https://github.com/scop/bash-completion/blob/d2f14a7/bash_completion#L498
__ltrim_colon_completions() {
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
# Remove colon-word prefix from COMPREPLY items
local colon_word=${1%"${1##*:}"}
local i=${#COMPREPLY[*]}
while [[ $((--i)) -ge 0 ]]; do
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
done
fi
}
_git_clone() {
case "$cur" in
--*)
__gitcomp_builtin clone
return
;;
*)
argc=0
for word in "${words[@]}"; do
case "$word" in
git|clone|--*)
continue
;;
*)
argc=$((argc + 1))
;;
esac
done
if [ $argc -le 1 ]; then
__gitcomp "https://github.com/git/git https://github.com/python/cpython"
__ltrim_colon_completions "$cur"
fi
;;
esac
}
这非常有效:
(我在这里输入的序列是git clone hg)
bash完成2.x
(举一个具体的例子:股票ubuntu bionic(18.04))
在bash completion 2.x中,模型被转换为动态加载的配置。这意味着当“git
已完成”选项卡时,激发,在其安装的路径上查找git完成并将其来源
在.bashrc
/.bash\u profile
中定义我自己的\u git\u clone
完成函数现在是无用的,因为它会被动态来源的完成文件破坏
我可以在以下位置定义自己的git
完成:
(例如~/.local/share/bash completion/completions/git.bash
)。但是,这会关闭所有其他的git
completion
如何使自定义的克隆选项卡完成在此模型下工作(并使默认完成继续工作)
不可接受的解决方案:
- 修改系统打包文件:
/usr/share/bash completion/completions/git
。此文件由apt
管理
在您的.bashrc
/.bash\u配置文件中,您可以在重新定义git克隆的完成之前,强制加载git
的默认完成:
if ! complete -p git &> /dev/null
then
# Instead of hardcoding the name of the dynamic completion loader
# function, you can obtain it by parsing the output of 'complete -p -D'
_completion_loader git
fi
_git_clone() {
COMPREPLY=("My own completion for 'git clone'")
}
编辑
上述方法的一个可延迟加载版本(不急于加载git
的默认bash完成)如下所示:
bash完成过程包含非常有趣的信息
首先,如果您100%确定您的$BASH\u COMPLETION\u USER\u DIR
和$XDG\u DATA\u HOME
环境变量为空,那么您在原始问题中指定的是添加自己的BASH完成脚本的好地方:
~/.local/share/bash-completion/completions/git
需要注意的是,.bash
不需要扩展
事实上,bash完成脚本是通过/etc/profile.d/bash_completion.sh
文件加载的
如果在.bashrc
文件中执行某些操作,可能会破坏加载链中的某些内容
尽管如此,如果覆盖现有的完成函数,仍然需要确保加载顺序正确。
因此,加载第一个bash完成脚本是必需的,以确保一切顺利结束。
您可以轻松地执行此操作,在~/.local/share/bash completion/completions/git
文件的开头添加此初始指令:
# Ensures git bash-completion is loaded before overriding any function (be careful to avoid endless loop).
! complete -p git &> /dev/null && [ ${ENDLESS_LOOP_SAFEGUARD:-0} -eq 0 ] && ENDLESS_LOOP_SAFEGUARD=1 BASH_COMPLETION_USER_DIR=/dev/null _completion_loader git
首先检查是否已经加载git bash completion,如果不是这样,则加载所有bash completion git定义。
编辑:当bash completion第一次加载git部分时,无止境循环保护
技巧允许避免无止境循环
如果需要,您可以获得以下用法:
complete --help
完成:完成[-abcdefgjksuv][-pr][-DE][-o
选项][A操作][G globpat][W单词列表][F函数][C
命令][X filterpat][P前缀][S后缀][名称…]
指定Readline如何完成参数
对于每个名称,指定如何完成参数。如果没有选择
现有竣工规范的打印方式如下:
允许将它们重新用作输入
选项:
-p以可重复使用的格式打印现有的完成规范
-r删除每个名称的完成规范,如果没有,则删除
提供名称,所有完工规范
-D将完成和操作应用为命令的默认值
没有定义任何特定的完成
-E将完成和操作应用于“空”命令--
试图在空行上完成
尝试完成时,将按照
上面列出了大写字母选项。-D选项需要
优先于-E
退出状态:
返回成功,除非提供了无效选项或发生错误
然后,也只有这样,您才能定义您想要的任何内容,包括覆盖git clone bash completion的旧方法:
# Ensures git bash-completion is loaded before overriding any function (be careful to avoid endless loop).
! complete -p git &> /dev/null && [ ${ENDLESS_LOOP_SAFEGUARD:-0} -eq 0 ] && ENDLESS_LOOP_SAFEGUARD=1 BASH_COMPLETION_USER_DIR=/dev/null _completion_loader git
# https://github.com/scop/bash-completion/blob/d2f14a7/bash_completion#L498
__ltrim_colon_completions() {
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
# Remove colon-word prefix from COMPREPLY items
local colon_word=${1%"${1##*:}"}
local i=${#COMPREPLY[*]}
while [[ $((--i)) -ge 0 ]]; do
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
done
fi
}
_git_clone() {
case "$cur" in
--*)
__gitcomp_builtin clone
return
;;
*)
argc=0
for word in "${words[@]}"; do
case "$word" in
git|clone|--*)
continue
;;
*)
argc=$((argc + 1))
;;
esac
done
if [ $argc -le 1 ]; then
__gitcomp "https://github.com/git/git https://github.com/python/cpython"
__ltrim_colon_completions "$cur"
fi
;;
esac
}
每次执行更改并希望检查结果时,只需请求git的bash completion重载:
_completion_loader git
这样,你就永远不会失去你的改变,因为你让包文件原封不动;并且仍然可以使用您自己的函数增强任何现有的bash完成
编辑:
关于你对\u completion\u loader
function=>的恐惧,但是在检查了源代码之后,这个函数自提交后就存在了,日期是2015-07-15 20:53:05
,所以我想它应该保持向后兼容,但不保证是真的。我将编辑我的答案,提出一些备选方案
作为替代方案,这应该是获得自己的git完成定义的另一种方式(放在自己脚本的开头):
自己调用\uuuu load\u completion
,然后像以前一样重写?@o11c调用双下划线函数感觉非常脆弱这感觉像是一种黑客行为——我想新的延迟加载系统是为了防止像这样潜在的昂贵的急加载?但是它确实可以工作(在shell启动时有一个明显的停顿)。您还没有真正解释它的工作原理,或者如何“解析complete-p-D
”的输出@AnthonySottile*如何“解析complete-p-D
”的输出*该注释是为了防止您在
complete --help
# Ensures git bash-completion is loaded before overriding any function (be careful to avoid endless loop).
! complete -p git &> /dev/null && [ ${ENDLESS_LOOP_SAFEGUARD:-0} -eq 0 ] && ENDLESS_LOOP_SAFEGUARD=1 BASH_COMPLETION_USER_DIR=/dev/null _completion_loader git
# https://github.com/scop/bash-completion/blob/d2f14a7/bash_completion#L498
__ltrim_colon_completions() {
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
# Remove colon-word prefix from COMPREPLY items
local colon_word=${1%"${1##*:}"}
local i=${#COMPREPLY[*]}
while [[ $((--i)) -ge 0 ]]; do
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
done
fi
}
_git_clone() {
case "$cur" in
--*)
__gitcomp_builtin clone
return
;;
*)
argc=0
for word in "${words[@]}"; do
case "$word" in
git|clone|--*)
continue
;;
*)
argc=$((argc + 1))
;;
esac
done
if [ $argc -le 1 ]; then
__gitcomp "https://github.com/git/git https://github.com/python/cpython"
__ltrim_colon_completions "$cur"
fi
;;
esac
}
_completion_loader git
# Ensures git bash-completion is loaded before overriding any function
# Be careful to avoid endless loop with dedicated $ENDLESS_LOOP_SAFEGUARD environment variable.
if ! complete -p git &> /dev/null && [ ${ENDLESS_LOOP_SAFEGUARD:-0} -eq 0 ]; then
# Trick: define $BASH_COMPLETION_USER_DIR environment variable here to ensure bash-completion rule are loaded once.
export BASH_COMPLETION_USER_DIR=/usr/share
complete -D git
unset BASH_COMPLETION_USER_DIR
ENDLESS_LOOP_SAFEGUARD=1 complete -D git
fi