2012-03-05 2 views
10

Я проверил optcomplete, работая с модулем optparse. Его пример - простой файл, поэтому я мог бы заставить его работать. Я также тестировал его с помощью модуля argparse, поскольку предыдущий устарел. Но я действительно не понимаю, как и кем программа python вызывается на вкладках. Я подозреваю, что bash вместе с линией shebang и модуль argparse (или optparse) задействованы в некотором роде. Я пытался понять это (теперь я буду читать исходный код).Как argpse (и устаревший optparse) реагируют на нажатие клавиши «tab» после имени программы python в bash?

У меня есть более сложная структура программы, которая включает оболочку вокруг фрагмента кода, который обрабатывает аргументы. Его экземпляр argparse.ArgumentParser() и звонки на add_argument(), которые переклассифицированы в другой промежуточный модуль, чтобы избежать дублирования кода, и обертка вокруг вызываемого - находятся внутри функции.

Я хочу понять, как работает эта закладка между bash и python (или, в этом отношении, любой другой интерпретатор, такой как perl).

ПРИМЕЧАНИЕ: У меня есть справедливое понимание завершения bash (которое я узнал только сейчас), и я думаю, что понимаю, что bash (только) выполнено по заказу.

Примечание: Я читал другие подобные вопросы SO, и никто на самом деле не ответить на этот Q.

Edit: Here функция Баш.
я уже понял, как модуль питона узнает о словах, набранных в командной строке, читая os.environ значения переменных

$COMP_WORDS 
$COMP_CWORD 
$COMP_LINE 
$COMP_POINT 
$COMPREPLY 

Эти переменные имеют значения только на вкладке печати. Мой вопрос в том, как запускается модуль python?

+0

Документы 'optcomplet' говорят:« Вам также необходимо указать функцию Bash, а затем сообщить Bash, чтобы вызвать завершение оппонента для конкретных программ, которые его используют: «. Если вы это сделали, почему вы все еще спрашиваете, как это работает? Должно быть очевидно, что вам просто нужно сообщить bash, какую программу вызывать, если запрашивается завершение. –

+0

Извините, я неправильно понял, что я читал. Я добавлю для этого ответ. –

ответ

14

Чтобы понять, что здесь происходит, давайте посмотрим, что эта функция Баш на самом деле делает:

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, чтобы представить выбор пользователю. Магия не задействована :)

+0

Эй, спасибо большое, на самом деле я заметил, что $ 1, когда я прочитал ваш комментарий и пошел на страницу, чтобы получить ссылку.Затем меня поразило то, что я уже знал, но никогда не использовалось, поскольку я никогда не писал сценарий bash - первый доллар - первый arg.-: S. Мне было глупо, что я этого раньше не понимал. – 0xc0de

+0

+1 для приятного и ясного примера :) – 0xc0de