asika/symfony-console-completion

Symfony Console 组件应用的自动 BASH 完成功能。这是基于 Symfony 6 的分支。

0.12.3 2022-11-06 05:40 UTC

This package is auto-updated.

Last update: 2024-09-06 09:30:24 UTC


README

本包为基于 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 类型。

工作原理

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的选项,始终运行值自动完成,因为目前无法从命令行内容中确定所需的行为(即跳过可选值或为其完成)。