简体   繁体   English

如何使Git别名的制表符完成行为像现有命令一样?

[英]How can I make tab completion for my Git alias behave like an existing command?

I am writing a shell script to add a "review" sub command to git, to make it easier to do code reviews. 我正在编写一个shell脚本,向git添加“ review”子命令,以使其更容易进行代码审查。 It's basically a fancy wrapper for git diff and git difftool commands, but requires less typing. git difftool ,它是git diffgit difftool命令的精美包装器,但所需的键入较少。

Some example usages: 一些示例用法:

# Lists added, deleted, renamed and modified files between master and current branch
git review master -l

# Opens difftool for files modified between master and current branch
git review -m

I would like to enable branch auto completion in my shell script, but cannot for the life of me figure out how to do it. 我想在我的shell脚本中启用分支自动完成功能,但是我一生都无法解决如何做到这一点。 Here is what I'm really after: 这是我真正追求的:

git review ma<tab><tab>

And then it should behave like git checkout ma<tab><tab> . 然后,它的行为应类似于git checkout ma<tab><tab>

My shell script: 我的shell脚本:

#!/bin/env bash

function print_usage {
    echo "Usage: git review <branch> <-a|-d|-m|-l> [-- paths/to filter/by]"
    echo ""
    echo "    -a: Only review added files"
    echo "    -d: Only review delete files"
    echo "    -m: Only review modified files"
    echo "    -l: List files and and type of modification"
}

if [ -z "$1" ] || [ -z "$2" ]; then
    print_usage
    exit 1
fi

git_branch=$1
review_command=$2
path_filters=""

shift
shift

if [ "$1" = "--" ]; then
    path_filters="$@"
fi

case $review_command in
    "-a")
        echo "Reviewing added files..."

        if [ -z "$path_filters" ]; then
            git difftool $git_branch -- $(git diff --name-status $git_branch | grep -E '^A' | awk '{print $2}')
        else
            git difftool $git_branch -- $(git diff --name-status $git_branch -- $path_filters | grep -E '^A' | awk '{print $2}')
        fi
        ;;
    "-d")
        echo "Reviewing deleted files..."

        if [ -z "$path_filters" ]; then
            git difftool $git_branch -- $(git diff --name-status $git_branch | grep -E '^D' | awk '{print $2}')
        else
            git difftool $git_branch -- $(git diff --name-status $git_branch -- $path_filters | grep -E '^D' | awk '{print $2}')
        fi
        ;;
    "-m")
        echo "Reviewing modified files..."

        if [ -z "$path_filters" ]; then
            git difftool $git_branch -- $(git diff --name-status $git_branch | grep -E '^M' | awk '{print $2}')
        else
            git difftool $git_branch -- $(git diff --name-status $git_branch -- $path_filters | grep -E '^M' | awk '{print $2}')
        fi
        ;;
    "-l")
        echo "Differences between $git_branch and $(git mybranch)..."

        if [ -z "$path_filters" ]; then
            git diff --name-status $git_branch
        else
            git diff --name-status $git_branch -- $path_filters
        fi
        ;;
esac

echo ""
echo "Review finished."

Really, since I'm in the process of typing the command in, I doubt my shell script will have anything to do with the solution. 确实,由于我正在输入命令,因此我怀疑我的shell脚本是否与解决方案有关。

Some other useful info: 其他一些有用的信息:

  • Windows 10 Windows 10
  • Git v2.18.0.windows.1 Git v2.18.0.windows.1
  • Shell: GNU bash, version 4.4.19(2)-release (x86_64-pc-msys) Shell:GNU bash,版本4.4.19(2)-发行版(x86_64-pc-msys)

Is there a way to add git branch auto completion to a custom git extension command? 有没有一种方法可以将git分支自动完成功能添加到自定义git扩展命令中?


An interesting related question for Linux: custom git command autocompletion . Linux的一个有趣的相关问题: 自定义git命令autocompletion

Using an alias 使用别名

Let's assume a minimal version of your script, something like 让我们假设您的脚本的最低版本,例如

#!/usr/bin/env bash

git diff "$1"

This is executable and somewhere in your $PATH . 这是可执行文件,位于$PATH Let's call it gitreview . 我们称之为gitreview

To get an alias for it, you add it like this in your .gitconfig : 要为其获取别名,可以在.gitconfig像这样添加它:

[alias]
    review =  "!f() { gitreview \"$@\"; }; f"

This gets you completion for review when you enter git . 当您输入git时,这将使您完成review Now, to make it behave the same as git checkout , you can use a null command, like this: 现在,要使其行为与git checkout相同,可以使用null命令,如下所示:

review =  "!f() { : git checkout ; gitreview \"$@\"; }; f"

and it'll complete the same as git checkout ! 它将完成与git checkout相同的操作! Notice that the blank between checkout and ; 请注意, checkout;之间的空白; is required. 是必须的。


This is mentioned in the comments of git-completion.bash : git-completion.bash 的注释中提到:

# If you use complex aliases of form '!f() { ... }; f', you can use the null
# command ':' as the first command in the function body to declare the desired
# completion style.  For example '!f() { : git commit ; ... }; f' will
# tell the completion to use commit completion.  This also works with aliases
# of form "!sh -c '...'".  For example, "!sh -c ': git commit ; ... '".

Using an external command 使用外部命令

Alternatively, you can make your script a proper external command by naming it git-review and leave it somewhere in your $PATH . 另外,您可以通过将脚本命名为git-review并将其放在$PATH某个位置,从而使脚本成为适当的外部命令。 To get completion for it (assuming you have both Bash and Git completion), add this to your ~/.bash_completion file (just create it if it doesn't exist): 要获得完成(假设您同时具有Bash和Git完成),请将其添加到~/.bash_completion文件中(如果不存在,请创建它):

_git_review() { _git_checkout; }

Git completion (for Git 2.18 or newer) checks for completion functions that are named _git_$command , and by doing this, you say "just call _git_checkout instead". Git完成(对于Git 2.18或更高版本)检查名为_git_$command完成功能,然后您说“只调用_git_checkout ”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM