例子:
我在Mac上使用bash v3.2.17,正在使用通过具有bash_completion变体的macports安装的git。
当我键入git checkout m<tab>
。例如,我完成了master
。
但是,我有一个别名git checkout
,gco
。当我输入时gco m<tab>
,我没有自动完成分支名称。
理想情况下,我希望自动补全可以神奇地为我的所有别名工作。可能吗?失败的话,我想为每个别名手动自定义它。那么,我该怎么办?
例子:
我在Mac上使用bash v3.2.17,正在使用通过具有bash_completion变体的macports安装的git。
当我键入git checkout m<tab>
。例如,我完成了master
。
但是,我有一个别名git checkout
,gco
。当我输入时gco m<tab>
,我没有自动完成分支名称。
理想情况下,我希望自动补全可以神奇地为我的所有别名工作。可能吗?失败的话,我想为每个别名手动自定义它。那么,我该怎么办?
Answers:
如以上评论所述,
complete -o default -o nospace -F _git_checkout gco
将不再起作用。但是,__git_complete
git-completion.bash中有一个函数可以用来为别名设置完成,如下所示:
__git_complete gco _git_checkout
__git_complete g __git_main
以使代码完成对所有git命令起作用。
git-completion.bash
从<your git install folder>/etc/bash-completion.d/
到~/.git-completion.bash
步骤2)添加source ~/.git-completion.bash
到您的.bash_profile
步骤3)添加__git_complete gco _git_checkout
在你的.bash_profile上述行之后的任何地方。步骤4)重新启动Shell,享受您的别名自动完成!:)
我也遇到了这个问题,并提出了这个代码片段。这将自动为您完成所有别名。在声明所有(或任何)别名后运行它。
# wrap_alias takes three arguments:
# $1: The name of the alias
# $2: The command used in the alias
# $3: The arguments in the alias all in one string
# Generate a wrapper completion function (completer) for an alias
# based on the command and the given arguments, if there is a
# completer for the command, and set the wrapper as the completer for
# the alias.
function wrap_alias() {
[[ "$#" == 3 ]] || return 1
local alias_name="$1"
local aliased_command="$2"
local alias_arguments="$3"
local num_alias_arguments=$(echo "$alias_arguments" | wc -w)
# The completion currently being used for the aliased command.
local completion=$(complete -p $aliased_command 2> /dev/null)
# Only a completer based on a function can be wrapped so look for -F
# in the current completion. This check will also catch commands
# with no completer for which $completion will be empty.
echo $completion | grep -q -- -F || return 0
local namespace=alias_completion::
# Extract the name of the completion function from a string that
# looks like: something -F function_name something
# First strip the beginning of the string up to the function name by
# removing "* -F " from the front.
local completion_function=${completion##* -F }
# Then strip " *" from the end, leaving only the function name.
completion_function=${completion_function%% *}
# Try to prevent an infinite loop by not wrapping a function
# generated by this function. This can happen when the user runs
# this twice for an alias like ls='ls --color=auto' or alias l='ls'
# and alias ls='l foo'
[[ "${completion_function#$namespace}" != $completion_function ]] && return 0
local wrapper_name="${namespace}${alias_name}"
eval "
function ${wrapper_name}() {
let COMP_CWORD+=$num_alias_arguments
args=( \"${alias_arguments}\" )
COMP_WORDS=( $aliased_command \${args[@]} \${COMP_WORDS[@]:1} )
$completion_function
}
"
# To create the new completion we use the old one with two
# replacements:
# 1) Replace the function with the wrapper.
local new_completion=${completion/-F * /-F $wrapper_name }
# 2) Replace the command being completed with the alias.
new_completion="${new_completion% *} $alias_name"
eval "$new_completion"
}
# For each defined alias, extract the necessary elements and use them
# to call wrap_alias.
eval "$(alias -p | sed -e 's/alias \([^=][^=]*\)='\''\([^ ][^ ]*\) *\(.*\)'\''/wrap_alias \1 \2 '\''\3'\'' /')"
unset wrap_alias
let COMP_CWORD+=$num_alias_arguments
某些原因,该行在Mac OS X上不起作用。((COMP_CWORD+=$num_alias_arguments))
尽管用修复固定了它
wrap_alias
别名定义中的双引号引起了窒息,我想对于多命令别名(alias 'foo=bar; baz'
)并没有多大意义,因此我在| grep -v '[";|&]'
后面加上了一个多余的内容alias -p
。同样,对于数百个别名定义,它会有点慢,但是我很高兴地确认,使用echo
代替eval
输出并将其输出到缓存文件中(然后可以eval
一次性编辑)可以很好并且非常快。
wrap_alias
需要设置完成,因此我不得不移到代码source /etc/bash_completion
前面wrap_alias
。
let COMP_CWORD+=$num_alias_arguments
至let \"COMP_CWORD+=$num_alias_arguments\"
。
在git-completion.bash
其中一行:
complete -o default -o nospace -F _git git
查看该行(和_git函数),可以将此行添加到您的.bash_profile
:
complete -o default -o nospace -F _git_checkout gco
我将g ='git'用作别名,并结合git别名输入类似
$ g co <branchname>
对于我的特定用例,最简单的解决方法是在git-completion中添加一行。
在此行的正下方:
__git_complete git _git
我添加了以下行来处理我的单个“ g”别名:
__git_complete g _git
git-completion
或该行/etc/bash_completion.d/git
,但是我complete -o default -o nospace -F _git g
在别名中添加之后.bash_aliases
,它就起作用了!
/etc/bash-completion.d/
或在中新编辑文件/usr/share/bash-completion/
,则每次使用包管理器更新该文件时,所做的更改都会丢失。
该论坛页面显示了一个解决方案。
将这些行放入您的.bashrc
或.bash_profile
:
# Author.: Ole J
# Date...: 23.03.2008
# License: Whatever
# Wraps a completion function
# make-completion-wrapper <actual completion function> <name of new func.>
# <command name> <list supplied arguments>
# eg.
# alias agi='apt-get install'
# make-completion-wrapper _apt_get _apt_get_install apt-get install
# defines a function called _apt_get_install (that's $2) that will complete
# the 'agi' alias. (complete -F _apt_get_install agi)
#
function make-completion-wrapper () {
local function_name="$2"
local arg_count=$(($#-3))
local comp_function_name="$1"
shift 2
local function="
function $function_name {
((COMP_CWORD+=$arg_count))
COMP_WORDS=( "$@" \${COMP_WORDS[@]:1} )
"$comp_function_name"
return 0
}"
eval "$function"
}
# and now the commands that are specific to this SO question
alias gco='git checkout'
# we create a _git_checkout_mine function that will do the completion for "gco"
# using the completion function "_git"
make-completion-wrapper _git _git_checkout_mine git checkout
# we tell bash to actually use _git_checkout_mine to complete "gco"
complete -o bashdefault -o default -o nospace -F _git_checkout_mine gco
此解决方案类似于balshetzer的脚本,但只有该解决方案对我有效。(balshetzer的脚本在使用某些别名时出现问题。)
-bash: eval: line 28: unexpected EOF while looking for matching '''
-bash: eval: line 29: syntax error: unexpected end of file
"
引号function
应引为\"
。这可能会吃掉您的'
报价中的某处。
另一种选择是使用~/.bash_completion
文件。要创建gco
别名,git checkout
只需将其放入其中:
_xfunc git __git_complete gco _git_checkout
然后,~/.bashrc
您只需要输入别名本身:
alias gco='git checkout'
两行。而已。
说明:
这些~/bash_completion
获取来自主bash_completion脚本末尾。我在gentoo中找到了主要脚本/usr/share/bash-completion/bash_completion
。
该_xfunc git
位负责git-completion
为您寻找文件,因此您无需放入任何其他内容~/.bashrc
。
接受的答案要求您.git-completion.sh
从~/.bashrc
我认为很me脚的文件中复制并获取它。
PS:我仍在尝试弄清楚如何不将整个git-completion
脚本提供到我的bash环境中。如果找到方法,请发表评论或编辑。
_xfunc git
需要?
source ~/.git-completion.sh
我_xfunc
不为我做。仅在.NET中感觉更好,更干净~/.bash_completion
。没有_xfunc
(或采购)__git_complete
功能将不存在。
~/.bash_completion
文件-该_xfunc
行对我有效.bashrc
。
您只需要找到 complete
命令并复制具有别名的行即可。
我有alias d-m="docker-machine"
。换句话说,d-m
应为的别名docker-machine
。
因此,在Mac上(通过brew),完成文件位于中cd `brew --prefix`/etc/bash_completion.d/
。
就我而言,我编辑了名为的文件docker-machine
。
一直到底部:
complete -F _docker_machine docker-machine
所以我刚刚添加了另一行,并加上了别名:
complete -F _docker_machine docker-machine
complete -F _docker_machine d-m
docker
别名为)的最佳解决方案d
。虽然对于问题中的示例,git checkout
别名gco
为更复杂。
首先,查找原始的完成命令。例:
$ complete | grep git
complete -o bashdefault -o default -o nospace -F __git_wrap__git_main git
现在将它们添加到您的启动脚本中(例如〜/ .bashrc):
# copy the original statement, but replace the last command (git) with your alias (g)
complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g
# load dynamically loaded completion functions (may not be required)
_completion_loader git
该_completion_loader
行可能不是必需的。但是在某些情况下,仅在键入命令并TAB
第一次按下后才动态加载完成功能。因此,如果您未使用原始命令,并尝试使用别名+ TAB
,则可能会收到诸如“ bash:complete:function'_docker'not found”的错误。
这个问题有很多答案,像我一样,我打赌很多困惑的读者。就我而言,我还要求将点文件在具有不同版本Git的多个平台上工作。我也没有,alias g=git
但是有g
定义为一个函数。
为了实现这一点,我不得不将这里的不同答案组合成一个解决方案。尽管这已经重申了答案,但我认为我的船上有人可能会像我初次提出该问题时那样会发现此汇编有用。
假设使用的是旧版本和较新版本的Git,Ubuntu默认设置以及brew install git
在MacOS上。在后一种情况下,bash不会处理brew安装的完成项(稍后我会诊断)。
# Alias g to git
g() {
if [[ $# > 0 ]]; then
git "$@"
else
git status -sb
fi
}
# Preload git completion in Ubuntu which is normally lazy loaded but we need
# the __git_wrap__git_main function available for our completion.
if [[ -e /usr/share/bash-completion/completions/git ]]; then
source /usr/share/bash-completion/completions/git
elif [[ -e /usr/local/etc/bash_completion.d/git-completion.bash ]]; then
source /usr/local/etc/bash_completion.d/git-completion.bash
fi
if command_exists __git_complete; then
__git_complete g _git
elif command_exists __git_wrap__git_main; then
complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g
fi
如果您使用alias g='git'
,我在这行代码中添加.bash_aliases
complete -o default -o nospace -F _git g