壳牌完工¶
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)"
把这个加入 ~/.zshrc
:
eval "$(_FOO_BAR_COMPLETE=zsh_source foo-bar)"
把这个加入 ~/.config/fish/completions/foo-bar.fish
:
_FOO_BAR_COMPLETE=fish_source foo-bar | source
这与用于下面激活脚本方法的文件相同。对于菲什来说,使用这种方法可能总是更容易。
使用 eval
意味着每次启动Shell时都会调用和评估该命令,这可能会延迟Shell的响应能力。为了加快速度,请将生成的脚本写入文件,然后获取该文件。您可以提前生成文件并将它们与您的程序一起分发,以节省您的用户一步。
将脚本保存在某个地方。
_FOO_BAR_COMPLETE=bash_source foo-bar > ~/.foo-bar-complete.bash
将文件来源于 ~/.bashrc
.
. ~/.foo-bar-complete.bash
将脚本保存在某个地方。
_FOO_BAR_COMPLETE=zsh_source foo-bar > ~/.foo-bar-complete.zsh
将文件来源于 ~/.zshrc
.
. ~/.foo-bar-complete.zsh
将脚本保存到 ~/.config/fish/completions/foo-bar.fish
:
_FOO_BAR_COMPLETE=fish_source foo-bar > ~/.config/fish/completions/foo-bar.fish
修改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
,但它可以是完成脚本可以打开的另一个值。例如, file
或 dir
可以告诉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