Для автозаполнения опции щелчка, состоящей из двух строк, в которой вторая строка зависит от первой, вам не нужны две функции завершения. Вам просто нужен способ определить, какая из двух строк в данный момент завершается. Для опции с именем --opt
мы можем заполнить тип (str, str)
, например:
Код:
def get_opts(ctx, args, incomplete):
""" auto complete for option "opt"
:param ctx: The current click context.
:param args: The list of arguments passed in.
:param incomplete: The partial word that is being completed, as a
string. May be an empty string '' if no characters have
been entered yet.
:return: list of possible choices
"""
opts = {
'foo1': ('bar11', 'bar21', 'bar31'),
'foo2': ('bar12', 'bar22', 'bar32'),
'fox3': ('bar13', 'bar23', 'bar33'),
}
if args[-1] == '--opt':
possible_choices = opts.keys()
elif args[-1] in opts:
possible_choices = opts[args[-1]]
else:
possible_choices = ()
return [arg for arg in possible_choices if arg.startswith(incomplete)]
Используя автозаполнение
Вы можете передать autocompletion
Функция для щелчка, например:
@click.option('--opt', type=(str, str), autocompletion=get_opts)
Как это работает?
Функция autocompletion
передает список args
. При завершении опции мы можем найти имя нашей опции в args
. В этом случае мы можем искать --opt
в аргументах, чтобы получить привязку к позиции, завершающей ли мы первую или вторую строку. Затем мы возвращаем строку, которая соответствует уже введенному символу.
Код теста:
import click
@click.command()
@click.option('--opt', type=(str, str), autocompletion=get_opts)
@click.argument('arg')
def cli(opt, arg):
"""My Great Cli"""
if __name__ == "__main__":
commands = (
('--opt', 2, 'foo1 foo2 fox3'),
('--opt f', 2, 'foo1 foo2 fox3'),
('--opt fo', 2, 'foo1 foo2 fox3'),
('--opt foo', 2, 'foo1 foo2'),
('--opt fox', 2, 'fox3'),
('--opt foz', 2, ''),
('--opt foo2 b', 3, 'bar12 bar22 bar32'),
('--opt foo2 bar1', 3, 'bar12'),
('--opt foo2 baz', 3, ''),
)
import os
import sys
from unittest import mock
from click._bashcomplete import do_complete
failed = []
for cmd_args in commands:
cmd_args_with_arg = (
'arg ' + cmd_args[0], cmd_args[1] + 1, cmd_args[2])
for cmd in (cmd_args, cmd_args_with_arg):
with mock.patch('click._bashcomplete.echo') as echo:
os.environ['COMP_WORDS'] = 'x ' + cmd[0]
os.environ['COMP_CWORD'] = str(cmd[1])
do_complete(cli, 'x', False)
completions = [c[0][0] for c in echo.call_args_list]
if completions != cmd[2].split():
failed.append(completions, cmd[2].split())
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
if failed:
for fail in failed:
print('Got {}, expected {}'.format(completions, cmd[2].split()))
else:
print('All tests passed')
Результаты теста:
Click Version: 7.0
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
All tests passed