代码之家  ›  专栏  ›  技术社区  ›  anthony sottile

重写git克隆的bash完成

  •  13
  • anthony sottile  · 技术社区  · 6 年前

    竣工

    违约 completion for git clone (以下转载)给出 --* 选项:

    _git_clone ()
    {
        case "$cur" in
        --*)
            __gitcomp_builtin clone
            return
            ;;
        esac
    }
    

    bash completion 1.x(旧bash)

    在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 
    

    重击完成2.x

    (具体例子:stock ubuntu bionic(18.04))

    在bash completion 2.x中,模型被转换为 已加载配置。这意味着当 git 制表符是否完成, __load_completion 激发,在安装的路径处查找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 ). 然而,这会关闭所有其他 完成!

    我该如何定制 clone 此模型下的制表符完成工作(并使默认完成继续工作)?

    不可接受的解决方案:

    • 修改系统打包文件: /usr/share/bash-completion/completions/git . 此文件由管理 apt .
    2 回复  |  直到 5 年前
        1
  •  11
  •   Bsquare ℬℬ    5 年前

    这个 official FAQ bash完成包含非常有趣的信息。

    首先,如果你百分之百确定 $BASH_COMPLETION_USER_DIR $XDG_DATA_HOME 环境变量为空,您在原始问题中指定的内容是添加自己的bash完成脚本的好地方:

    ~/.local/share/bash-completion/completions/git
    

    值得注意 .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
    

    编辑: ENDLESS_LOOP_SAFEGUARD

    如果需要,可以获取用法:

    complete --help
    

    完成:完成[-abcdefgjksuv][-pr][-DE][-o 命令]-X筛选器端口]-P前缀]-S后缀][名称…] 指定Readline如何完成参数。

    已提供,现有竣工规范的打印方式

    选项:

    -以可重用的格式打印现有的完成规范 -r删除每个名称的完成规范,如果没有 提供名称,所有完工规范 -D将completions和actions作为命令的默认值 未定义任何特定完成 -对“空”命令应用完成和操作-- 试图在空行上完成

    上面列出了大写字母选项。D选项采用

    退出状态: 返回成功,除非提供了无效选项或发生错误。

    然后,只有这样,您才能定义您想要的任何内容,包括覆盖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
    }
    

    _completion_loader git
    

    这样,您就永远不会丢失更改,因为您让包文件保持不变;而且仍然可以使用自己的函数增强任何现有的bash完成。

    关于你的恐惧 _completion_loader 函数=>,但在检查了源代码之后,此函数自提交后即存在 cad3abfc7 ,共 2015-07-15 20:53:05 所以我想应该保持向后兼容,但没有保证。我会修改我的答案,提出一些选择

    # 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
    
        2
  •  0
  •   Leon    5 年前

    在你的 .bashrc / .bash_profile git 在重新定义 git clone :

    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'")
    }
    

    上述方法的一个可延迟加载的版本(它不急于为 吉特 )具体如下:

    if ! complete -p git &> /dev/null
    then
        _my_git_clone()
        {
            COMPREPLY=("My own completion for 'git clone'")
        }
    
        # A placeholder for git completion that will load the real
        # completion script on first use     
        _my_git_comp_stub()
        {
            # Remove the old completion handler (which should be this very function)
            complete -r git
    
            # and load the git bash completion
            _completion_loader git
    
            # Rebind _git_clone to our own version
            eval 'function _git_clone() { _my_git_clone "$@"; }'
    
            # Tell the completion machinery to retry the completion attempt
            # using the updated completion handler
            return 124
        }
    
        # Install a lazy loading handler for git completion    
        complete -o bashdefault -o default -o nospace -F _my_git_comp_stub git
    fi