156 lines
5.4 KiB
Python
156 lines
5.4 KiB
Python
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
|
|
import typer
|
|
|
|
from cli.completion.controller import CompletionCommandController
|
|
from cli.completion.providers import COMPLETION_PROVIDER_GATEWAY, CompletionProviderGateway
|
|
from cli.context import OutputOption
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class CompletionCommandRegistration:
|
|
"""
|
|
completion 子命令注册描述。
|
|
|
|
:param name: 子命令名称
|
|
:param help_text: 子命令帮助文本
|
|
"""
|
|
|
|
name: str
|
|
help_text: str
|
|
|
|
|
|
@dataclass
|
|
class CompletionSubcommandRegistrar:
|
|
"""
|
|
completion 子命令注册器。
|
|
|
|
该对象负责将 `show/install/doctor` 子命令挂载到 completion 应用,
|
|
将 Typer 命令声明细节从构建器主体中拆出。
|
|
|
|
:param completion_provider_gateway: completion 提供器对外网关
|
|
"""
|
|
|
|
completion_provider_gateway: CompletionProviderGateway = field(default_factory=lambda: COMPLETION_PROVIDER_GATEWAY)
|
|
|
|
@staticmethod
|
|
def build_registrations() -> tuple[CompletionCommandRegistration, ...]:
|
|
"""
|
|
返回 completion 子命令注册描述列表。
|
|
|
|
:return: 子命令注册描述元组
|
|
"""
|
|
return (
|
|
CompletionCommandRegistration(name='show', help_text='输出指定 shell 的 completion 脚本'),
|
|
CompletionCommandRegistration(name='install', help_text='安装指定 shell 的 completion 脚本'),
|
|
CompletionCommandRegistration(name='doctor', help_text='检查当前 completion 配置状态'),
|
|
)
|
|
|
|
def register(self, app: typer.Typer, *, controller: CompletionCommandController) -> None:
|
|
"""
|
|
向 completion 应用注册全部子命令。
|
|
|
|
:param app: completion 子应用
|
|
:param controller: completion 命令控制器
|
|
:return: None
|
|
"""
|
|
registrations = {registration.name: registration for registration in self.build_registrations()}
|
|
|
|
@app.command(registrations['show'].name, help=registrations['show'].help_text)
|
|
def show(
|
|
shell: str = typer.Argument(
|
|
...,
|
|
help='shell 名称,如 bash、zsh、fish',
|
|
autocompletion=self.completion_provider_gateway.complete_shell_names,
|
|
),
|
|
) -> None:
|
|
"""
|
|
输出指定 shell 的 completion 脚本。
|
|
|
|
:param shell: shell 名称
|
|
:return: None
|
|
"""
|
|
controller.show(shell)
|
|
|
|
@app.command(registrations['install'].name, help=registrations['install'].help_text)
|
|
def install(
|
|
shell: str | None = typer.Option(
|
|
None,
|
|
'--shell',
|
|
help='shell 名称,默认自动识别当前 shell',
|
|
autocompletion=self.completion_provider_gateway.complete_shell_names,
|
|
),
|
|
output: OutputOption = 'text',
|
|
target_file: Path | None = typer.Option(None, '--target-file', help='completion 脚本目标文件路径'),
|
|
activate: bool = typer.Option(False, '--activate', help='将激活命令写入 shell rc 文件'),
|
|
rc_file: Path | None = typer.Option(None, '--rc-file', help='自定义 shell rc 文件路径'),
|
|
force: bool = typer.Option(False, '--force', help='覆盖已存在且内容不同的目标文件'),
|
|
) -> None:
|
|
"""
|
|
安装指定 shell 的 completion 脚本。
|
|
|
|
:param shell: shell 名称,默认自动识别当前 shell
|
|
:param output: 输出格式
|
|
:param target_file: completion 脚本目标文件路径
|
|
:param activate: 是否写入 shell rc 文件激活命令
|
|
:param rc_file: 自定义 shell rc 文件路径
|
|
:param force: 是否强制覆盖已存在文件
|
|
:return: None
|
|
"""
|
|
controller.install(
|
|
output,
|
|
shell=shell,
|
|
target_file=target_file,
|
|
activate=activate,
|
|
rc_file=rc_file,
|
|
force=force,
|
|
)
|
|
|
|
@app.command(registrations['doctor'].name, help=registrations['doctor'].help_text)
|
|
def doctor(
|
|
output: OutputOption = 'text',
|
|
) -> None:
|
|
"""
|
|
检查当前 completion 配置状态。
|
|
|
|
:param output: 输出格式
|
|
:return: None
|
|
"""
|
|
controller.doctor(output)
|
|
|
|
|
|
@dataclass
|
|
class CompletionCommandBuilder:
|
|
"""
|
|
completion 子应用构建器。
|
|
|
|
该构建器负责装配 `completion` 子应用,并将控制器实例和子命令注册
|
|
细节收口到类式对象协作中。
|
|
|
|
:param completion_subcommand_registrar: completion 子命令注册器
|
|
"""
|
|
|
|
completion_subcommand_registrar: CompletionSubcommandRegistrar = field(
|
|
default_factory=CompletionSubcommandRegistrar
|
|
)
|
|
|
|
def build(self, root_cli: typer.Typer) -> typer.Typer:
|
|
"""
|
|
构建 completion 命令组。
|
|
|
|
:param root_cli: 根 Typer 应用
|
|
:return: completion 子应用
|
|
"""
|
|
app = typer.Typer(
|
|
help='shell completion 相关命令',
|
|
no_args_is_help=True,
|
|
context_settings={'help_option_names': ['-h', '--help']},
|
|
)
|
|
completion_command_controller = CompletionCommandController(root_cli)
|
|
self.completion_subcommand_registrar.register(app, controller=completion_command_controller)
|
|
return app
|
|
|
|
|
|
COMPLETION_COMMAND_BUILDER = CompletionCommandBuilder()
|