Python单击(str,str)选项的自动完成

2024-04-26 03:41:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python和Click编写一个CLI工具。其中一个命令有一个选项type=(str, str)),其用法如下:command subcommand --option foo bar。你知道吗

对于第一个参数(foo)有几个选项可供选择,对于第一个参数的每个选项,第二个参数(bar)有几个选项可供选择。所以第二个参数的选择取决于第一个参数的选择!你知道吗

问题是:如何使用support that Click提供的代码编写自动补全?你知道吗

特别是:

  • 我需要两个完成函数吗,每个参数一个?你知道吗
  • 第二个函数如何选择第一个参数?你知道吗
  • 如何为一个选项定义两个完成函数?你知道吗
  • 或者,我可以为两个参数使用一个函数吗?那会是什么样子?你知道吗

Tags: 工具函数命令用法参数clifootype
1条回答
网友
1楼 · 发布于 2024-04-26 03:41:38

要自动完成两个字符串(其中第二个字符串依赖于第一个字符串)的单击选项,不需要两个完成函数。您只需要一种方法来确定两个字符串中的哪一个当前正在完成。对于名为 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中找到我们的选项名。在本例中,我们可以在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

相关问题 更多 >