innmind/cli

构建CLI工具的库

3.6.0 2024-03-10 14:45 UTC

README

Build Status codecov Type Coverage

CLI是一个小型库,用于封装构建命令行工具所需的所有信息。这个想法是在阅读ponylang文档时产生的,意识到其他语言使用类似的方法来处理应用程序的入口点,因此我决定为PHP也实现类似的功能。

该方法是有一个main函数作为代码执行的起点。这个函数有一个环境参数,因此不需要全局变量。然而,由于并非所有内容都可以作为参数传递(这将使接口复杂化),可以行使环境权限(正如常规PHP脚本中那样)。

重要:为了正确使用此库,您必须使用vimeo/psalm验证您的代码。

安装

composer require innmind/cli

使用

要开始一个新的CLI工具,您需要以下样板代码

# cli.php
<?php
declare(strict_types = 1);

require 'path/to/composer/autoload.php';

use Innmind\CLI\{
    Main,
    Environment,
};
use Innmind\OperatingSystem\OperatingSystem;

new class extends Main {
    protected function main(Environment $env, OperatingSystem $os): Environment
    {
        //your code here
        return $env;
    }
};

这将直接调用main函数。变量$env让您可以访问3个标准流(stdinstdoutstderr)、传递给cli的参数列表、所有环境变量、工作目录、终端是否交互式以及指定退出状态码的方法。

注意:调用$env->exit(1)不会直接退出您的程序,您必须调用return $env->exit(1);才能使main函数停止。

命令

当构建简单的工具时,直接使用main函数就足够了,但您通常希望在同一个工具中提供多个命令(与参数/选项验证相关联)。此库提供了实现此功能的方法。以下是一个示例

use Innmind\CLI\{
    Commands,
    Command,
    Command\Arguments,
    Command\Options,
    Console,
};

function main(Environment $env, OperatingSystem $os): void
{
    $run = Commands::of(
        new class implements Command {
            public function __invoke(Console $console): Console
            {
                //your code here
            }

            public function usage(): string
            {
                return 'foo';
            }
        }
    );

    return $run($env);
};

在您的终端中,您可以像这样调用此命令:php cli.php foo。但是,由于这里定义了一个单独的命令,您可以简单地调用php cli.php。当然,您可以定义尽可能多的命令。

在这里,命令是一个匿名类,以简化示例,但它可以是一个实现Command的普通类。由于命令只需要实现一个接口,您可以完全控制可以注入到其中的依赖项。这意味着您的命令实例可以来自依赖注入容器。由于接口简单,另一个优点是您可以轻松地对命令进行单元测试。

Command接口要求您实现两个方法:__invokeusage。第一个方法是在它是期望调用的命令时被调用的。方法usage是您定义命令结构的地方,即命令的名称、它的参数/选项列表、其简短描述和完整描述。

要定义您命令的所有属性,它将类似于以下内容

{command name} {optional list of arguments/options}

{short description on a single line}

{full description that can span multiple lines}

当您运行help命令(该命令将列出所有可用命令)时,会显示命令名称和简短描述。只有当您使用额外选项--help调用命令(或误用命令)时,才会显示参数/选项列表和完整描述。

要定义参数,您有3种模式可供选择:

  • 使用foo,您请求一个必需的参数,可以通过这种方式访问:$console->arguments()->get('foo')
  • 使用[bar],您请求一个可选参数,在访问之前必须通过$console->arguments()->contains('bar')来验证其存在。可选参数不能紧跟必需参数之后。
  • 使用...baz,您请求所有额外参数都将作为一个名为baz的列表重新分组,它将提供一个任何长度的Sequence<string>。您只能有一个此类参数,并且必须放在最后,您通过$console->arguments()->pack()来访问。

要定义选项,您有2种模式可供选择:

  • -f|--foo这定义了一个可以通过-f--foo调用的标志,如果您不希望有简短名称,只需定义--foo即可。
  • -f|--foo=这定义了一个需要值的选项,如果您不希望有简短名称,只需定义--foo=即可。它可以通过-f=value-f value--foo=value来调用。