在 bash 中,argparse(和已弃用的 optparse)如何响应 python 程序名称之后的“tab"按键? [英] How does argparse (and the deprecated optparse) respond to 'tab' keypress after python program name, in bash?

查看:20
本文介绍了在 bash 中,argparse(和已弃用的 optparse)如何响应 python 程序名称之后的“tab"按键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经测试了 optcompleteoptparse 模块一起工作.它的例子是一个简单的文件,所以我可以让它工作.我还使用 argparse 模块对其进行了测试,因为不推荐使用前一个模块.但我真的不明白在按 Tab 键时 Python 程序是如何以及由谁调用的.我怀疑 bash 连同 shebang 行和 argparse(或 optparse)模块以某种方式参与.我一直在尝试解决这个问题(现在要阅读源代码).

I have tested optcomplete working with the optparse module. Its example is a simple file so I could get that working. I also tested it using the argparse module as the prior one is deprecated. But I really do not understand how and by whom the python program gets called on tab presses. I suspect bash together with the shebang line and the argparse (or optparse) module are involved in some way. I have been trying to figure this out (now gonna read the source code).

我有一个稍微复杂一点的程序结构,其中包括处理参数的代码段的包装器.它的 argparse.ArgumentParser() 实例化和对 add_argument() 的调用 - 它们被超类到另一个中间模块中以避免重复代码,并且正在调用它的包装器 - 在里面一个函数.

I have a little more complex program structure, which includes a wrapper around the piece of code which handles the arguments. Its argparse.ArgumentParser() instantiation and calls to add_argument() - which are superclassed into another intermediate module to avoid duplicating code, and wrapper around that is being called - are inside a function.

我想了解这个选项卡完成在 bash 和 python 之间的工作方式(或者就此而言任何其他解释器,如 perl).

I want to understand the way this tab completion works between bash and python (or for that matter any other interpretor like perl).

注意:我对 bash 补全(我刚刚学到的)有一定的了解,而且我认为我了解 bash(仅)自定义补全.

NOTE: I have a fair understanding of bash completion (which I learned just now), and I think I understand the bash(only) custom completion.

注意:我已经阅读了其他类似的 SO 问题,但没有人真正回答这个问题.

NOTE: I have read other similar SO questions, and none really answer this Q.

这里是 bash 函数.
我已经了解 python 模块如何通过读取变量的 os.environ

Here is the bash function.
I already understood how the python module gets to know about words typed in the command line, by reading os.environ values of variables

$COMP_WORDS
$COMP_CWORD
$COMP_LINE
$COMP_POINT
$COMPREPLY

这些变量只有在按 Tab 键时才有值.我的问题是如何触发 python 模块?

These variables have values only on tab press. My question is how does the python module gets triggered?

推荐答案

要了解这里发生了什么,让我们检查一下 bash 函数实际上做了什么:

To understand what's happening here, let's check what that bash function actually does:

COMPREPLY=( $( \
    COMP_LINE=$COMP_LINE  COMP_POINT=$COMP_POINT \
    COMP_WORDS="${COMP_WORDS[*]}"  COMP_CWORD=$COMP_CWORD \
    OPTPARSE_AUTO_COMPLETE=1 $1 ) )

看到最后的$1了吗?这意味着它实际上调用了我们要执行的带有特殊环境变量集的 Python 文件!为了跟踪正在发生的事情,让我们准备一个小脚本来拦截 optcomplete.autocomplete 的作用:

See the $1 at the end? That means that it actually calls the Python file we want to execute with special environment variables set! To trace what's happening, let's prepare a little script to intercept what optcomplete.autocomplete does:

#!/usr/bin/env python2
import os, sys
import optparse, optcomplete
from cStringIO import StringIO

if __name__ == '__main__':    
    parser = optparse.OptionParser()

    parser.add_option('-s', '--simple', action='store_true',
                      help="Simple really simple option without argument.")

    parser.add_option('-o', '--output', action='store',
                      help="Option that requires an argument.")

    opt = parser.add_option('-p', '--script', action='store',
                            help="Option that takes python scripts args only.")
    opt.completer = optcomplete.RegexCompleter('.*\.py')

    # debug env variables
    sys.stderr.write("\ncalled with args: %s\n" % repr(sys.argv))
    for k, v in sorted(os.environ.iteritems()):
        sys.stderr.write("  %s: %s\n" % (k, v))

    # setup capturing the actions of `optcomplete.autocomplete`
    def fake_exit(i):
      sys.stderr.write("autocomplete tried to exit with status %d\n" % i)
    sys.stdout = StringIO()
    sys.exit = fake_exit

    # Support completion for the command-line of this script.
    optcomplete.autocomplete(parser, ['.*\.tar.*'])

    sys.stderr.write("autocomplete tried to write to STDOUT:\n")
    sys.stderr.write(sys.stdout.getvalue())
    sys.stderr.write("\n")

    opts, args = parser.parse_args()

当我们尝试自动完成它时,这给了我们以下内容:

This gives us the following when we try to autocomplete it:

$ ./test.py [tab]
called with args: ['./test.py']
  ...
  COMP_CWORD: 1
  COMP_LINE: ./test.py 
  COMP_POINT: 10
  COMP_WORDS: ./test.py 
  ...
  OPTPARSE_AUTO_COMPLETE: 1
  ...
autocomplete tried to exit with status 1
autocomplete tried to write to STDOUT:
-o -h -s -p --script --simple --help --output

所以 optcomplete.autocomplete 只是读取环境,准备匹配,将它们写入 STDOUT 并退出.结果 -o -h -s -p --script --simple --help --output 然后被放入一个 bash 数组 (COMPREPLY=( ... )) 并返回到 bash 以向用户呈现选择.不涉及魔法:)

So optcomplete.autocomplete just reads the environment, prepares the matches, writes them to STDOUT and exits. The result -o -h -s -p --script --simple --help --output is then put into a bash array (COMPREPLY=( ... )) and returned to bash to present the choices to the user. No magic involved :)

这篇关于在 bash 中,argparse(和已弃用的 optparse)如何响应 python 程序名称之后的“tab"按键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆