如何让bash完成与别名一起工作?
例如:
我是一个与Bash v3.2.17的Mac上,我使用通过与bash_completion变种macports安装的git。
当我inputgit checkout m<tab>
。 例如,我把它完成master
。
不过,我有一个git checkout
的别名, gco
。 当我键入gco m<tab>
,我没有得到自动完成的分支名称。
理想情况下,我想自动完成只是神奇地为我的所有别名工作。 可能吗? 否则,我想为每个别名手动定制它。 那么,我怎么去呢?
如上述评论所述,
complete -o default -o nospace -F _git_checkout gco
将不再工作。 但是,在git-completion.bash中有一个__git_complete
函数可以用来设置别名的完成,例如:
__git_complete gco _git_checkout
我遇到了这个问题,并提出了这个代码片段。 这将自动完成所有别名。 在声明所有(或任何)别名后运行它。
# 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
在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别名我input的东西
$ g co <branchname>
对于我的具体使用情况,更简单的解决方法是添加一行到git完成。
在这条线的下面:
__git_complete git _git
我添加了这一行来处理我的单个'g'别名:
__git_complete g _git
理想情况下,我想自动完成只是神奇地为我的所有别名工作。 可能吗?
是的, 完全别名项目是可能的。
此论坛页面显示一个解决scheme。
将这些行放入您的.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
这种解决scheme类似于balshetzer的脚本 ,但只有这一个实际上适合我。 (balshetzer的脚本与我的一些别名有问题。)
你也可以尝试使用Git别名。 例如,在我的~/.gitconfig
文件中,我有一个部分如下所示:
[alias] co = checkout
所以你可以inputgit co m<TAB>
,然后扩展到git co master
,这是git checkout
命令。
还有一个select是使用~/.bash_completion
文件。 为git checkout
创buildgco
别名就把它放在那里:
_xfunc git __git_complete gco _git_checkout
然后在~/.bashrc
你只需要放置别名本身:
alias gco='git checkout'
两行。 而已。
说明:
~/bash_completion
源自主bash_completion脚本的末尾。 在gentoo中,我在/usr/share/bash-completion/bash_completion
find了主脚本。
_xfunc git
位负责为你提供git-completion
文件,所以你不需要在~/.bashrc
任何东西。
被接受的答案要求你复制.git-completion.sh
,并从我find的~/.bashrc
文件中find它。
PS:我仍然想弄清楚如何不把我的bash环境下的整个git-completion
脚本。 请发表评论或编辑,如果你find一个方法。
你只需要findcomplete
命令,并复制具有别名的行。
我有alias dm="docker-machine"
。 换句话说, dm
应该是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 dm