壳牌完工

Click为Bash(4.4及以上版本)、Zsh和Fish提供选项卡完成支持。还可以添加对其他Shell的支持,并且可以在多个级别上自定义建议。

Shell完成建议命令名称、选项名称以及选择、文件和路径参数类型的值。仅在至少输入破折号时才会列出选项。隐藏的命令和选项不会显示。

$ repo <TAB><TAB>
clone  commit  copy  delete  setuser
$ repo clone -<TAB><TAB>
--deep  --help  --rev  --shallow  -r

实现完成

只有通过入口点(而不是通过 python 命令看到 包装入口点 .安装可执行文件后,使用特殊环境变量调用它将使Click进入完成模式。

要启用Shell完成,用户需要向其Shell注册特殊函数。确切的脚本取决于您使用的shell。单击将在调用时输出它 _{FOO_BAR}_COMPLETE 设置为 {shell}_source . {FOO_BAR} 是收件箱中的可执行文件名称,虚线被虚线替换。环境变量名称必须为大写字母,这是常规做法,但并不严格要求。此约定有助于区分环境变量与常规Shell变量和命令,使脚本和配置文件更具可读性且更容易维护。内置Shell是 bash , zsh ,而且 fish .

为用户提供以下根据您的程序名称自定义的说明。这使用 foo-bar 作为一个例子。

把这个加入 ~/.bashrc :

eval "$(_FOO_BAR_COMPLETE=bash_source foo-bar)"

使用 eval 意味着每次启动Shell时都会调用和评估该命令,这可能会延迟Shell的响应能力。为了加快速度,请将生成的脚本写入文件,然后获取该文件。您可以提前生成文件并将它们与您的程序一起分发,以节省您的用户一步。

将脚本保存在某个地方。

_FOO_BAR_COMPLETE=bash_source foo-bar > ~/.foo-bar-complete.bash

将文件来源于 ~/.bashrc .

. ~/.foo-bar-complete.bash

修改shell配置后,您需要启动一个新的shell以加载更改。

自定义类型完成

创建自定义时 ParamType ,覆盖其 shell_complete() 方法为具有该类型的参数提供shell完成。该方法必须返回 CompletionItem 对象除了值之外,这些对象还保存shell支持可能使用的元数据。内置实现使用 type 指示对路径的特殊处理,以及 help 对于支持在建议旁边显示帮助字符串的shell。

在此示例中,该类型将建议以不完整值开头的环境变量。

class EnvVarType(ParamType):
    name = "envvar"

    def shell_complete(self, ctx, param, incomplete):
        return [
            CompletionItem(name)
            for name in os.environ if name.startswith(incomplete)
        ]

@click.command()
@click.option("--ev", type=EnvVarType())
def cli(ev):
    click.echo(os.environ[ev])

压倒性的价值完成

可以通过提供 shell_complete 功能使用函数而不是类型提供的任何完成。它传递了3个关键字参数:

  • ctx - 当前命令上下文。

  • param - 请求完成的当前参数。

  • incomplete - 正在完成的部分单词。如果尚未输入字符,则可能是空字符串。

它必须返回 CompletionItem 对象,或者作为快捷方式,它可以返回字符串列表。

在本例中,该命令将建议以不完整值开头的环境变量。

def complete_env_vars(ctx, param, incomplete):
    return [k for k in os.environ if k.startswith(incomplete)]

@click.command()
@click.argument("name", shell_complete=complete_env_vars)
def cli(name):
    click.echo(f"Name: {name}")
    click.echo(f"Value: {os.environ[name]}")

添加对Shell的支持

可以为未内置的shell添加支持。请务必检查PyPI以查看是否已经有一个包添加了对您的Shell的支持。该主题技术性很强,您需要查看Click的源代码来研究内置实现。

Shell支持由 ShellComplete 注册到 add_completion_class() .当在完成模式下调用Click时,它会调用 source() 输出完成脚本,或 complete() 以输出完成。Base Class提供了需要实现一些较小部分的默认实现。

首先,您需要弄清楚Shell的完成系统如何工作,并编写一个脚本将其与Click集成。它必须用环境变量调用您的程序 _{FOO_BAR}_COMPLETE 设置为 {shell}_complete 并传递完整参数和不完整值。它如何传递这些值以及Click完成响应的格式取决于您。

在您的子类别中,设置 source_template 到完成剧本。默认实现将执行 % 使用以下变量进行格式化:

  • complete_func - 脚本中定义的完成函数的安全名称。

  • complete_var - 用于传递 {shell}_complete 指令。

  • foo_bar - 正在完成的可执行文件的名称。

示例代码用于合成Shell“My Shell”或简称“mysh”。

from click.shell_completion import add_completion_class
from click.shell_completion import ShellComplete

_mysh_source = """\
%(complete_func)s {
    response=$(%(complete_var)s=mysh_complete %(foo_bar)s)
    # parse response and set completions somehow
}
call-on-complete %(foo_bar)s %(complete_func)s
"""

@add_completion_class
class MyshComplete(ShellComplete):
    name = "mysh"
    source_template = _mysh_source

接下来,实施 get_completion_args() .这必须从完成脚本获取、解析并返回完整参数和不完整值。例如,对于Bash实现, COMP_WORDS dev var包含命令行参数作为字符串,以及 COMP_CWORD dev var包含不完整arg的索引。该方法必须返回 (args, incomplete) tuple。

import os
from click.parser import split_arg_string

class MyshComplete(ShellComplete):
    ...

    def get_completion_args(self):
        args = split_arg_string(os.environ["COMP_WORDS"])

        if os.environ["COMP_PARTIAL"] == "1":
            incomplete = args.pop()
            return args, incomplete

        return args, ""

最后,实施 format_completion() .这被称为格式化每个 CompletionItem 变成一串。例如,Bash实现返回 f"{item.type},{item.value} (it不支持帮助字符串),并且Zsh实现返回每个部分,每个部分之间用白线分隔,用 _ 占位符.这种格式完全取决于您用完成脚本解析的内容。

type 值通常是 plain ,但它可以是完成脚本可以打开的另一个值。例如, filedir 可以告诉Shell处理路径完成,因为Shell在这方面比Click更好。

class MyshComplete(ShellComplete):
    ...

    def format_completion(self, item):
        return f"{item.type}\t{item.value}"

实现这三件事后,新的Shell支持就已经准备好了。如果这些还不够,还有更多部分可以被重写,但这可能不是必要的。

激活指令将再次取决于您的Shell的工作方式。使用以下内容生成完成脚本,然后以某种方式将其加载到shell中。

_FOO_BAR_COMPLETE=mysh_source foo-bar