stecman/symfony-console-completion

Symfony Console 组件应用的自动 BASH 完成功能。

v0.13.0 2024-07-05 11:49 UTC

README

Build Status Scrutinizer Code Quality

Latest Stable Version Total Downloads Latest Unstable Version License

本包为基于 Symfony Console 组件的应用程序提供自动(tab)完成功能。无需配置,本包允许完成可用的命令名称及其提供的选项。用户代码可以定义针对参数和选项值的自定义完成行为。

使用 Composer 的零配置使用示例

Composer BASH completion

零配置使用

如果您不需要任何自定义完成行为,您可以简单地将完成命令添加到您的应用程序中

  1. 使用 composer 安装 stecman/symfony-console-completion,通过运行以下命令:

    $ composer require stecman/symfony-console-completion
    
  2. 对于独立的 Symfony Console 应用程序,将 CompletionCommand 实例添加到应用程序的 Application::getDefaultCommands() 方法中

    protected function getDefaultCommands()
    {
       //...
        $commands[] = new \Stecman\Component\Symfony\Console\BashCompletion\CompletionCommand();
       //...
    }

    对于 Symfony 框架应用程序,在 app/config/services.yml 中将 CompletionCommand 注册为服务

    services:
    #...
        console.completion_command:
          class: Stecman\Component\Symfony\Console\BashCompletion\CompletionCommand
          tags:
              -  { name: console.command }
    #...
  3. 通过在终端中运行以下命令之一来注册应用程序的完成功能,将 [program] 替换为您运行应用程序的命令(例如,'composer')

    # BASH ~4.x, ZSH
    source <([program] _completion --generate-hook)
    
    # BASH ~3.x, ZSH
    [program] _completion --generate-hook | source /dev/stdin
    
    # BASH (any version)
    eval $([program] _completion --generate-hook)

    默认情况下,这将为您应用程序的绝对路径注册完成功能,如果程序在您的 PATH 上可用,则将正常工作。您可以使用 --program 选项指定要完成的程序名称,如果您使用别名运行程序,则需要此选项。

  4. 如果您希望自动应用于所有新的 shell 会话,请将步骤 3 中的命令添加到您的 shell 的配置文件(例如,~/.bash_profile~/.zshrc)中

注意:运行时自动使用 SHELL 环境变量检测 shell 类型(ZSH/BASH)。在某些情况下,您可能需要使用 --shell-type 选项显式指定 shell 类型。

当前版本仅支持 Symfony 6 和 PHP 8.x,因为 Symfony 6 中存在向后兼容性中断。对于旧版本的 Symfony 和 PHP,请使用 版本 0.11.0

它如何工作

CompletionCommand--generate-hook 选项生成一个小型 shell 脚本,该脚本将一个函数注册到您的 shell 的完成系统中,作为 shell 和应用程序中的完成命令之间的桥梁。当您请求程序完成(通过按 tab 键,将程序名称作为命令行的第一个单词)时,桥接函数将被运行;将当前命令行内容和光标位置传递给 [program] _completion,并将结果输出反馈给 shell。

定义值完成

默认情况下,不会为选项和参数值返回任何完成结果。有两种方法可以定义值的自定义完成值:扩展 CompletionCommand 或实现 CompletionAwareInterface

实现 CompletionAwareInterface

CompletionAwareInterface 允许命令负责完成其自己的选项和参数值。当完成运行时指定了命令名称(例如,myapp mycommand ...)并且命名的命令实现了此接口,则会自动调用相应的接口方法

class MyCommand extends Command implements CompletionAwareInterface
{
    ...

    public function completeOptionValues($optionName, CompletionContext $context)
    {
        if ($optionName == 'some-option') {
            return ['myvalue', 'other-value', 'word'];
        }
    }

    public function completeArgumentValues($argumentName, CompletionContext $context)
    {
        if ($argumentName == 'package') {
            return $this->getPackageNamesFromDatabase($context->getCurrentWord());
        }
    }
}

此方法生成补全时目前不支持使用 CompletionInterface 实现,这使得在命令之间共享补全行为变得容易。要使用此功能,您需要通过扩展 CompletionCommand 来编写您的值补全。

扩展 CompletionCommand

可以通过扩展 CompletionCommand 并重写 configureCompletion 方法来定义参数和选项值补全

class MyCompletionCommand extends CompletionCommand
{
    protected function configureCompletion(CompletionHandler $handler)
    {
        $handler->addHandlers([
            // Instances of Completion go here.
            // See below for examples.
        ]);
    }
}

Completion

以下代码片段演示了 Completion 类如何与 CompletionHandler 一起工作以及一些可能的配置。这些示例适用于具有签名的应用程序

`myapp (walk|run) [-w|--weather=""] direction`
使用数组的特定命令参数补全
$handler->addHandler(
    new Completion(
        'walk',                    // match command name
        'direction',               // match argument/option name
        Completion::TYPE_ARGUMENT, // match definition type (option/argument)
        [                     // array or callback for results
            'north',
            'east',
            'south',
            'west'
        ]
    )
);

这将为此补全 direction 参数

$ myapp walk [tab]

但不会为此补全

$ myapp run [tab]
非命令特定(全局)参数补全使用函数
$handler->addHandler(
    new Completion(
        Completion::ALL_COMMANDS,
        'direction',
        Completion::TYPE_ARGUMENT,
        function() {
            return range(1, 10);
        }
    )
);

这将为此两个命令补全 direction 参数

$ myapp walk [tab]
$ myapp run [tab]
选项补全

选项处理器的工作方式与参数处理器相同,只是您使用 Completion::TYPE_OPTION 作为类型。

$handler->addHandler(
    new Completion(
        Completion::ALL_COMMANDS,
        'weather',
        Completion::TYPE_OPTION,
        [
            'raining',
            'sunny',
            'everything is on fire!'
        ]
    )
);
同时补全参数和选项

要为匹配指定名称的选项和参数运行补全,您可以使用类型 Completion::ALL_TYPES。结合使用 Completion::ALL_COMMANDS 以及在整个应用程序中保持一致的选项/参数命名,很容易在命令、选项和参数之间共享补全行为。

$handler->addHandler(
    new Completion(
        Completion::ALL_COMMANDS,
        'package',
        Completion::ALL_TYPES,
        function() {
            // ...
        }
    )
);

示例补全

从 Git 仓库补全引用

new Completion(
    Completion::ALL_COMMANDS,
    'ref',
    Completion::TYPE_OPTION,
    function () {
        $raw = shell_exec('git show-ref --abbr');
        if (preg_match_all('/refs\/(?:heads|tags)?\/?(.*)/', $raw, $matches)) {
            return $matches[1];
        }
    }
)

补全文件系统路径

此库提供补全实现 ShellPathCompletion,该实现将路径补全委托给 shell 的内置路径补全行为,而不是在 PHP 中实现它,这样用户就可以从他们的 shell 获得他们期望的路径补全行为。

new Completion\ShellPathCompletion(
    Completion::ALL_COMMANDS,
    'path',
    Completion::TYPE_OPTION
)

行为说明

  • 选项快捷键不作为补全选项提供,但是请求补全(即按 tab 键)在有效的选项快捷键上时将完成。
  • 没有为 --option="value" 风格的选项传递值实现补全,但是 --option value--option "value" 是有效的,并且功能相同。
  • 对于标记为 InputOption::VALUE_OPTIONAL 的选项,始终运行值补全,因为没有方法可以从命令行内容中确定所需的行为(即跳过可选值或为其补全)。