test.py的自动完成功能,如git <tab>

时间:2017-07-20 15:17:24

标签: python bash

当我使用tab发出git时,它可以自动完成一个列表,我想编写一个test.py,当我输入test.py后跟tab,它可以自动完成,并在测试中定义一个给定的列表.py,有可能吗?

$ git [tab]  
add                 branch              column              fetch               help                mv                  reflog              revert              stash               
am                  bundle              commit              filter-branch       imap-send           name-rev            relink              rm                  status              
annotate            checkout            config              format-patch        init                notes               remote              send-email          submodule           
apply               cherry              credential          fsck                instaweb            p4                  repack              shortlog            subtree             
archive             cherry-pick         describe            gc                  log                 pull                replace             show                tag                 
bisect              clean               diff                get-tar-commit-id   merge               push                request-pull        show-branch         whatchanged         
blame               clone               difftool            grep                mergetool           rebase              reset               stage 

2 个答案:

答案 0 :(得分:1)

您正在寻找的方法是:readline.set_completer。此方法与bash shell的readline交互。实施起来很简单。示例:https://pymotw.com/2/readline/

答案 1 :(得分:1)

这不是git二进制文件本身的一个功能,它是bash完成'hack',因此与Python per-se 无关,但是从那以后你已经标记了它,让我们添加一点点扭曲。假设我们创建一个知道其可接受参数的脚本 - test.py

#!/usr/bin/env python

import sys

# let's define some sample functions to be called on passed arguments
def f1():
    print("F1 called!")

def f2():
    print("F2 called!")

def f3():
    print("F3 called!")

def f_invalid():  # a simple invalid placeholder function
    print("Invalid command!")

def f_list():  # a function to list all valid arguments
    print(" ".join(sorted(arguments.keys())))

if __name__ == "__main__":  # make sure we're running this as a script
    arguments = {  # a simple argument map, use argparse or similar in a real world use
        "arg1": f1,
        "arg2": f2,
        "arg3": f3,
        "list_arguments": f_list
    }
    if len(sys.argv) > 1:
        for arg in sys.argv[1:]:  # loop through all arguments
            arguments.get(arg, f_invalid)()  # call the mapped or invalid function
    else:
        print("At least one argument required!")

注意:确保在脚本(chmod +x test.py)中添加了一个可执行标志,因此它的shebang用于执行,而不是将其作为Python解释器的参数提供。

除了所有样板文件外,重要的参数list_arguments - 它列出了此脚本的所有可用参数,我们将在bash完成脚本中使用此输出指示bash如何自动完成。为此,请创建另一个脚本,我们称之为test-completion.bash

#!/usr/bin/env bash

SCRIPT_NAME=test.py
SCRIPT_PATH=/path/to/your/script
_complete_script()
{
    local cursor options
    options=$(${SCRIPT_PATH}/${SCRIPT_NAME} list_arguments)
    cursor="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(compgen -W "${options}" -- ${cursor}) )
    return 0
}
complete -F _complete_script ${SCRIPT_NAME}

它的作用实际上是每当调用complete上的完成时添加_complete_script test.py函数。 _complete_script函数本身首先调用list_arguments上的test.py来检索其可接受的参数,然后使用compgencomplete创建所需的结构,以便能够打印出来。

要进行测试,您只需将此脚本作为源代码来源:

source test-completion.bash

然后你的bash会表现为:

$ ./test.py [tab]
arg1            arg2            arg3            list_arguments

而且,它完全可以从您的Python脚本中控制 - 无论在list_arguments 命令上打印为什么列表,都将显示为自动完成帮助。

要使更改成为永久更改,您只需将source行添加到.bashrc,或者如果您需要更结构化的解决方案,则可以遵循操作系统的准则。例如,git-flow-completion页面上介绍了几种方法。当然,这假设您实际上已经在系统上安装并启用了bash-autocomplete,但是如果您没有安装,则git自动完成功能将不起作用。

说到git自动完成,你可以通过检查git-completion.bash source来看看它是如何实现的 - 一个警告的词,它不适合胆小的人。