用文件名支持Git bash-completion?

时间:2011-05-17 17:06:29

标签: git bash bash-completion

是否有支持文件名完成的bash-completion脚本?我主要使用mercurial,我可以输入:

hg diff test/test_<tab>

它将显示/完成所有修改过的测试文件。它适用于大多数子命令,即hg add <tab><tab>仅列出未跟踪的文件。这真的很方便。

来自git contrib seams的bash脚本不支持此功能。有没有其他选择,或者你如何在命令行上使用git?

编辑2015

git-completion.bash支持自~1.8.2

以来的完整文件名完成

4 个答案:

答案 0 :(得分:13)

那么,让我们看看Mercurial bash完成脚本是如何做到的。

这是important part

_hg_status()
{
    local files="$(_hg_cmd status -n$1 .)"
    local IFS=$'\n'
    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
}

它被称为here

_hg_command_specific()
{
    case "$cmd" in 
    [...]
    diff)
        _hg_status "mar"
    ;;
    [...]
    esac
    return 0
}

因此,它只是调用hg status -nmar,并将输出用作完成文件列表。

我认为将类似内容修补到git completion script中并不太难 - 我们必须在此处修改__git_diff以不执行纯文件名+分支完成,而是调用{{1}而不是。


命令

git status

(对于git status --porcelain | grep '^.[^ ?]' | cut -b 4- )和

git diff --cached

(对于git status --porcelain | grep '^[^ ?]' | cut -b 4- )似乎输出正确的东西(如果没有重命名)。

但是,当它们传播到HEAD以外的任何东西时,它们都没用。

更通用的方法是使用

git diff

其中git diff --relative --name-only [--cached] [commit1] [commit2]] commit1(可能commit2)来自已经给定的diff命令行。


我在bash中实现了上述概念,并修补了--cached。如果您不想更改git-completion.bash,请将这两个功能添加到某个bash文件中,并在原始git-completion.bash之后将其提取。它现在应该使用像

这样的命令
git-completion.bash

submitted this作为git邮件列表的补丁,让我们看看这是什么结果。 (我会在那里得到反馈时更新这个答案。)

git diff -- <tab>
git diff --cached -- <tab>
git diff HEAD^^ -- <tab>
git diff origin/master master -- <tab>

更新:在此表单中看起来不需要此修补程序,因为当前完成文件的方式对于想要检查某些子目录中是否有更改的人更有用(例如,差异输出可能是空的)。如果链接到某个配置变量(默认为当前行为),则可能会被接受。此外,缩进应该适应标准(参见Junio C Hamano的回答)。

我可能会再接受一次,但不能在不久的将来保证这一点。如果其他人想要这样做,请随意接受我的代码,更改并再次提交。

答案 1 :(得分:3)

这为我解决了git diff <tab>问题,将以下内容放在 .bashrc 中:

alias gid='git diff'
__gdiff () {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts=$(git status --porcelain | grep '^.[^ ?]' | cut -b 4-)

    case "${prev}" in
        gid)
            COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
            ;;
    esac
}
complete -F __gdiff gid

然后执行gid <tab>而不是git diff <tab>。它可能会简化,但似乎可以作为快速解决方案。

答案 2 :(得分:0)

不是你想要的答案,但我想告诉你,很快鱼(友好的交互式shell)将为你提供开箱即用的git文件名完成支持。目前它即将推出2.3.0版本。

https://github.com/fish-shell/fish-shell/issues/901
https://github.com/fish-shell/fish-shell/pull/2364
https://github.com/fish-shell/fish-shell/commit/c5c59d4acb00674bc37198468b5978f69484c628

如果您的状态如下:

$ git status
modified: ../README.md
$ git add <tab>
:/README.md 

enter image description here

您也可以输入README并点击标签,如果它是唯一匹配,它会为您插入。 Friggin很好!

答案 3 :(得分:0)

自2011年以来,作为OP评论,Git支持完整的文件名完成,因为~1.8.2。

但是使用Git 2.18(2018年第二季度),提供路径列表的shell完成(在contrib/中)已经有所优化。

commit 78a2d21Clemens Buchacher (drizzd)(2018年4月4日) Junio C Hamano -- gitster --合并于commit 3a940e9,2018年4月25日)

  

completion:提高ls-files过滤效果

     

ls-files的输出中删除除最左边路径以外的所有路径   组件,然后我们消除重复。我们在while循环中执行此操作,   当迭代次数很多时,这是一个性能瓶颈   (例如linux.git中的60000个文件)。

$ COMP_WORDS=(git status -- ar) COMP_CWORD=3; time _git

real    0m11.876s
user    0m4.685s
sys     0m6.808s
  

使用cut命令替换循环可提高性能   显著:

$ COMP_WORDS=(git status -- ar) COMP_CWORD=3; time _git

real    0m1.372s
user    0m0.263s
sys     0m0.167s
  

使用Msys2 bash进行测量,Gys用于测量   视窗。

     

过滤ls-files输出时,我们注意不要触及绝对值   路径。这是多余的,因为ls-files永远不会输出绝对值   路径。删除不必要的操作。

此问题最初报告为Git for Windows issue 1533