内置补全
默认completion for git clone (转载于下方)为 --*
提供制表符补全选项:
_git_clone ()
{
case "$cur" in
--*)
__gitcomp_builtin clone
return
;;
esac
}
bash-completion 1.x(旧 bash)
(具体实例,macos high sierra + brew 安装了 bash-completion/git)
在 bash-completion 1.x 世界中,为了覆盖它,我会(在 .bashrc
/.bash_profile
中)定义我自己的 _git_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 h<tab><tab>g<tab>
)
$ git clone https://github.com/
//github.com/git/git //github.com/python/cpython
$ git clone https://github.com/git/git
bash-completion 2.x
(具体实例:stock ubuntu bionic (18.04))
在 bash-completion 2.x 中,模型被翻转为动态加载的配置。这意味着当git
选项卡完成, __load_completion
触发,在安装的路径中找到 git 完成并获取它。
定义我自己的 _git_clone
.bashrc
中的完成函数/.bash_profile
现在没用了,因为它被动态来源的完成文件破坏了。
我可以自己定义git
完成 this directory :
local -a dirs=( ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions )
(例如 ~/.local/share/bash-completion/completions/git.bash
)。然而,这会关闭所有其他 git
完成!
如何定制 clone
此模型下的选项卡完成工作(并让默认完成继续工作)?
Not Acceptable 解决方案:
- 修改系统打包文件:
/usr/share/bash-completion/completions/git
.此文件由apt
管理.
最佳答案
official FAQ bash-completion 包含非常有趣的信息。
首先,如果您 100% 确定您的 $BASH_COMPLETION_USER_DIR
和 $XDG_DATA_HOME
环境变量是空的,那么您在原始问题中指定的是添加您的代码的好地方自己的 bash 完成脚本:
~/.local/share/bash-completion/completions/git
要注意 .bash
扩展名不是必需的。
事实上,由于 /etc/profile.d/bash_completion.sh
文件加载了 bash 完成脚本。
如果您在 .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 定义。
编辑:ENDLESS_LOOP_SAFEGUARD
技巧允许在 bash 完成第一次加载 git 部分时避免无限循环。
如果需要,您可以获得用法:
complete --help
complete: complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...] Specify how arguments are to be completed by Readline.
For each NAME, specify how arguments are to be completed. If no options are supplied, existing completion specifications are printed in a way that allows them to be reused as input.
Options:
-p print existing completion specifications in a reusable format -r remove a completion specification for each NAME, or, if no NAMEs are supplied, all completion specifications -D apply the completions and actions as the default for commands without any specific completion defined -E apply the completions and actions to "empty" commands -- completion attempted on a blank line
When completion is attempted, the actions are applied in the order the uppercase-letter options are listed above. The -D option takes precedence over -E.
Exit Status: Returns success unless an invalid option is supplied or an error occurs.
然后,也只有那时,您可以定义任何您想要的,包括您覆盖 git clone bash 完成的旧方法:
# 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 reload:
_completion_loader git
这样,您将永远不会丢失您的零钱,因为您让包文件保持原样;并且仍然可以使用您自己的函数增强任何现有的 bash-completion。
编辑:
关于你对 _completion_loader
function => 的恐惧,但是在检查了源代码之后,这个函数自提交以来就存在 cad3abfc7 , of 2015-07-15 20:53:05
所以我想它应该保持向后兼容,但不能保证是真的。我将编辑我的答案以提出一些替代方案
作为替代方案,这应该是另一种获取您自己的 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
关于bash - 覆盖 git clone 的 bash 补全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51972474/