要了解这里发生了什么,让我们检查一下 bash 函数的实际作用:
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:
#!/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()
当我们尝试自动完成它时,这给了我们以下信息:
$ ./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 以将选择呈现给用户。不涉及魔法:)