Подтвердить что ты не робот

Выполнение пользовательской вкладки в python argparse

Как получить завершение вкладки оболочки, сотрудничающую с argparse в Python script?

#!/usr/bin/env python
import argparse

def main(**args):
    pass

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('positional', choices=['spam', 'eggs'])
    parser.add_argument('--optional', choices=['foo1', 'foo2', 'bar'])
    args = parser.parse_args()
    main(**vars(args))

С флагом исполняемого файла, установленным в файле .py, ожидаемые результаты должны выглядеть примерно так:

$ ./example.py sp<tab>             
   ->  completes to "./example.py spam"
$ ./example.py --op<tab> 
   ->  completes to "./example.py --optional"
$ ./example.py --optional b<tab>
   ->  completes to "./example.py --optional bar"
$ ./example.py --optional f<tab>   
   ->  completes to "./example.py --optional foo"
       and, additionally, prints  "foo1  foo2"  choices on stdout on a new line
4b9b3361

Ответ 1

Посмотрите argcomplete Андрея Кислюка.

Установите его с помощью:

sudo pip install argcomplete

Импортируйте модуль и добавьте одну строку в свой источник перед вызовом parser.parse_args():

#!/usr/bin/env python

import argparse as ap
import argcomplete

def main(**args):
  pass

if __name__ == '__main__':
  parser = ap.ArgumentParser()
  parser.add_argument('positional', choices=['spam', 'eggs'])
  parser.add_argument('--optional', choices=['foo1', 'foo2', 'bar'])
  argcomplete.autocomplete(parser)
  args = parser.parse_args()
  main(**vars(args))

и чтобы убедиться, что bash знает об этом script, вы используете

eval "$(register-python-argcomplete your_script)"

вы должны поместить эту строку в свой ~/.bashrc или следовать за argcomplete docs и активировать завершение "global".

После этого вы завершаете работу по запросу.

Как это работает, так это то, что линия eval создает функцию _python_argcomlete, которая зарегистрирована с помощью complete. (Запустите register-python-argcomplete your_script, чтобы просто взглянуть на то, что получает значение в bash). Функция автозаполнения ищет переменные среды, установленные механизмом завершения bash, чтобы увидеть, нужно ли ему действовать. Если он действует, он выходит из программы. Если он не действует, это обычный вызов программы, функция которого ничего не делает, и нормальный поток программы продолжается.

Ответ 2

Для автоматического завершения работы вам понадобится функция bash для генерации возможных параметров, а затем вам нужно запустить complete -F <function_name> <program_name>

Лучший способ сделать это - заставить программу сгенерировать функцию завершения на основе собственного алгоритма синтаксического анализа, чтобы избежать дублирования. Однако, быстро взглянув на argparse, я не смог найти способ получить доступ к его внутренней структуре, но я предлагаю вам искать его.

Вот функция bash, которая будет работать для вышеуказанной программы:

function _example_auto() {
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}

    case "$prev" in
    --optional ) 
        COMPREPLY=( $(compgen -W "foo1 foo2 bar" -- $cur) )
        return 0
        ;;
    *)
        COMPREPLY=( $(compgen -W "--optional spam eggs" -- $cur) )
        return 0
        ;;
    esac
}