终端的魔法书:解锁 PHP CLI 菜单的交互艺术

在数字时代的魔法世界中,命令行界面(CLI)就像一本古老的魔法书,等待着程序员用代码书写咒语。而 php-school/cli-menu 库,则是一支强大的魔法笔,让开发者在终端中绘制出优雅、交互式的菜单,宛如在黑白画布上挥洒彩色魔法。本文将带你深入探索这个 PHP 库的奥秘,从基础设置到高级定制,解锁终端交互的无限可能。无论你是初学者还是资深开发者,这篇文章都将以通俗易懂的方式,带你领略 CLI 菜单的魅力。

注解:CLI(Command Line Interface)是程序员与计算机交互的经典方式,通过文本命令操作,简洁高效。php-school/cli-menu 是一个 PHP 库,专门用于在终端中创建交互式菜单,类似于游戏中的选择界面,但运行在命令行环境中。


🚀 从零开始:点亮你的第一个 CLI 菜单

想象一下,你是一位刚学会魔法的新手巫师,手持一根简单的魔杖,准备召唤你的第一个魔法光芒。php-school/cli-menu 的快速入门就像这样简单而充满惊喜。以下是一个基础菜单的代码示例:

<?php
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;

require_once(__DIR__ . '/../vendor/autoload.php');

$itemCallable = function (CliMenu $menu) {
    echo $menu->getSelectedItem()->getText();
};

$menu = (new CliMenuBuilder)
    ->setTitle('Basic CLI Menu')
    ->addItem('First Item', $itemCallable)
    ->addItem('Second Item', $itemCallable)
    ->addItem('Third Item', $itemCallable)
    ->addLineBreak('-')
    ->setBorder(1, 2, 'yellow')
    ->setPadding(2, 4)
    ->setMarginAuto()
    ->build();

$menu->open();

运行这段代码,终端会弹出一个整洁的菜单,包含三个可选项和一个退出按钮。选择任意选项,终端会打印出该选项的文本。这个简单的例子就像在终端中点亮了一盏魔法灯,照亮了交互式编程的可能性。

注解CliMenuBuilder 是菜单的构建工具,类似一个魔法配方表,你可以通过链式调用添加标题、选项、样式等。addItem 方法为菜单添加可选择项,每个项都绑定一个回调函数(callable),在用户选择时触发。

基本菜单

🎨 定制你的魔法画布:菜单外观的艺术

CLI 菜单不仅是一个功能工具,更是一个可以自由涂鸦的画布。php-school/cli-menu 提供了丰富的样式选项,让你的菜单既实用又美观。以下是几个关键的定制方法:

🖼️ 标题与分隔线:为菜单命名

一个好的标题能让菜单更具吸引力。你可以为菜单设置标题,并用分隔线装饰:

$menu = (new CliMenuBuilder)
    ->setTitle('One Menu to Rule Them All!')
    ->setTitleSeparator('*-')
    ->build();

这里的 setTitleSeparator 会将 *- 重复填充整个菜单宽度,宛如在标题下画了一条华丽的魔法线。

🌈 色彩魔法:点亮终端

终端支持多种颜色,从经典的红、绿、蓝到 256 色扩展。以下代码将菜单前景色设为绿色,背景色设为黑色:

$menu = (new CliMenuBuilder)
    ->setForegroundColour('green')
    ->setBackgroundColour('black')
    ->build();

如果你的终端支持 256 色,可以使用颜色代码(如 230)进一步定制:

$menu = (new CliMenuBuilder)
    ->setForegroundColour('40', 'yellow')
    ->setBackgroundColour('92', 'magenta')
    ->build();

注解:256 色代码可在 颜色代码表 中找到。如果终端不支持 256 色,库会自动回退到指定的默认颜色(如 yellowmagenta),确保兼容性。

256 色边框

📏 尺寸与布局:控制菜单边界

菜单的宽度、边距和内边距可以精确调整。例如,设置宽度为 1000(若终端宽度不足,会自动适应):

$menu = (new CliMenuBuilder)
    ->setWidth(1000)
    ->build();

内边距(padding)和边距(margin)则让内容更舒适:

$menu = (new CliMenuBuilder)
    ->setPadding(10, 5) // 上下 10,左右 5
    ->setMarginAuto() // 自动居中
    ->build();

注解:内边距影响内容与边框的距离,边距影响菜单与终端边缘的距离。setMarginAuto 会根据终端宽度自动计算边距,让菜单居中显示。

🖌️ 边框设计:CSS 风格的魔法

边框可以像 CSS 一样灵活设置,支持不同宽度和颜色:

$menu = (new CliMenuBuilder)
    ->setBorder(3, 4, 5, 6, 'red') // 上 3,左 4,下 5,右 6
    ->build();

这种细致的控制让菜单看起来像一件精心雕刻的艺术品。

🚪 退出按钮:优雅的告别

默认情况下,菜单包含一个退出按钮,你可以自定义其文本:

$menu = (new CliMenuBuilder)
    ->setExitButtonText("Don't you want me baby?")
    ->build();

如果不需要退出按钮,可以完全移除:

$menu = (new CliMenuBuilder)
    ->disableDefaultItems()
    ->build();

🛠️ 菜单项的魔法道具:多样化的交互

菜单的核心在于其项(items),它们就像魔法道具,每种类型都有独特的功能。以下是主要项类型及其用法:

可选项:触发动作的按钮

可选项(Selectable Item)是菜单的基础,点击后会执行绑定的回调函数:

$menu = (new CliMenuBuilder)
    ->addItem('The Item Text', function (CliMenu $menu) {
        echo 'I am alive!';
    })
    ->build();

你可以批量添加多个可选项:

$callable = function (CliMenu $menu) { echo 'I am alive!'; };
$menu = (new CliMenuBuilder)
    ->addItems([
        ['Item 1', $callable],
        ['Item 2', $callable],
        ['Item 3', $callable],
    ])
    ->build();

☑️ 复选框:多选的魔法

复选框项(Checkbox Item)允许用户切换选中状态,适合需要多选的场景:

$callable = function (CliMenu $menu) {
    echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
    ->addCheckboxItem('Item 1', $callable)
    ->addCheckboxItem('Item 2', $callable)
    ->build();
复选框

🔘 单选框:唯一选择的魔法

单选框项(Radio Item)确保同一菜单层级内只有一个选项被选中:

$menu = (new CliMenuBuilder)
    ->addRadioItem('Item 1', $callable)
    ->addRadioItem('Item 2', $callable)
    ->build();
单选框

分隔线:整理你的魔法书

分隔线(Line Break Item)用于分隔菜单区域,增强可读性:

$menu = (new CliMenuBuilder)
    ->addLineBreak('<3', 2) // 重复 <3 两次
    ->build();

📜 静态项:不可交互的标题

静态项(Static Item)用于显示不可选择的文本,常用于标题或说明:

$menu = (new CliMenuBuilder)
    ->addStaticItem('AREA 51')
    ->build();

🎨 ASCII 艺术:终端的画作

ASCII 艺术项(Ascii Art Item)让你的菜单充满创意:

$art = <<<ART
        _ __ _
       / |..| \
       \/ || \/
        |_''_|
      PHP SCHOOL
LEARNING FOR ELEPHANTS
ART;
$menu = (new CliMenuBuilder)
    ->addAsciiArt($art, AsciiArtItem::POSITION_CENTER)
    ->build();

注解:如果 ASCII 艺术过宽,终端会显示备用文本(通过第三个参数设置),确保内容适应不同终端尺寸。

ASCII 艺术

📚 子菜单:嵌套的魔法书

子菜单(Sub Menu Item)允许创建嵌套菜单,适合复杂选项:

$menu = (new CliMenuBuilder)
    ->addSubMenu('Super Sub Menu', function (CliMenuBuilder $b) {
        $b->setTitle('Behold the awesomeness')
            ->addItem('This is awesome', function() { print 'Yes!'; });
    })
    ->build();
子菜单

🔄 分割项:并排展示的魔法

分割项(Split Item)将多个选项并排显示,充分利用菜单宽度:

$menu = (new CliMenuBuilder)
    ->setWidth(150)
    ->addSplitItem(function (SplitItemBuilder $b) use ($itemCallable) {
        $b->setGutter(5)
            ->addItem('Item 1', $itemCallable)
            ->addStaticItem('Item 2 - Static');
    })
    ->build();
分割项

🛡️ 动态交互:让菜单活起来

CLI 菜单不仅是一个静态画布,还能通过动态操作变得更加智能。以下是一些高级功能:

🔄 重绘菜单:实时更新

在回调函数中修改菜单样式后,可以调用 redraw 方法刷新显示:

$itemCallable = function (CliMenu $menu) {
    $menu->getStyle()->setBg($menu->getStyle()->getBg() === 'red' ? 'blue' : 'red');
    $menu->redraw();
};

若修改幅度较大(如调整宽度),可传入 true 清空终端后再重绘,避免显示异常。

🗑️ 动态增删项:魔法书的活页

你可以在运行时添加、移除或替换菜单项:

$itemCallable = function (CliMenu $menu) {
    $menu->addItem(new LineBreakItem('-'));
    $menu->redraw();
};

⌨️ 自定义快捷键:加速魔法

通过 addCustomControlMappingenableAutoShortcuts,为菜单项绑定快捷键:

$menu = (new CliMenuBuilder)
    ->enableAutoShortcuts()
    ->addItem('List of [C]lients', function() { echo "Clients!"; })
    ->build();

按下 c 即可触发对应回调,极大提升交互效率。


💬 对话与输入:与用户的魔法对话

php-school/cli-menu 提供对话框和输入框功能,让用户与菜单直接交流。

闪现对话框:短暂的信息魔法

闪现对话框(Flash)用于显示临时消息,按任意键关闭:

$itemCallable = function (CliMenu $menu) {
    $flash = $menu->flash("PHP School FTW!!");
    $flash->getStyle()->setBg('green');
    $flash->display();
};
闪现对话框

确认对话框:需要确认的魔法

确认对话框(Confirm)需要用户选择确认:

$itemCallable = function (CliMenu $menu) {
    $menu->confirm('PHP School FTW!')->display('OK!');
};
确认对话框

✍️ 输入框:捕获用户的心声

输入框支持文本、数字和密码三种类型。例如,文本输入:

$itemCallable = function (CliMenu $menu) {
    $result = $menu->askText()
        ->setPromptText('Enter your name')
        ->setPlaceholderText('Jane Doe')
        ->ask();
    echo $result->fetch();
};
文本输入

密码输入则支持自定义验证:

$itemCallable = function (CliMenu $menu) {
    $result = $menu->askPassword()
        ->setValidator(function ($password) {
            if ($password === 'password') {
                $this->setValidationFailedText('Password is too weak');
                return false;
            }
            return strlen($password) > 20;
        })
        ->ask();
    echo $result->fetch();
};
密码输入

🌟 整合与生态:让魔法更广泛

php-school/cli-menu 支持与主流框架整合,如 Symfony Console 和 Laravel,进一步扩展其应用场景。例如,Laravel 的扩展包 nunomaduro/laravel-console-menu 让开发者在 Artisan 命令中轻松使用 CLI 菜单。


📚 总结:书写你的终端魔法

php-school/cli-menu 是一把通往终端交互世界的魔法钥匙。它不仅提供了简单的菜单创建工具,还通过丰富的样式、动态操作和用户输入功能,让开发者能够打造出既实用又美观的命令行应用。从基础菜单到复杂的嵌套交互,这把钥匙都能帮你打开新的可能性。

无论是为你的 PHP 项目添加一个友好的命令行界面,还是探索终端的艺术潜力,php-school/cli-menu 都是一个值得尝试的工具。现在,拿起你的魔法笔,开始在终端中书写属于你的魔法故事吧!


📖 参考文献

  1. PHP School CLI Menu GitHub 仓库:https://github.com/php-school/cli-menu
  2. 256 色代码表:https://jonasjacek.github.io/colors/
  3. PHP School 工作坊示例代码:https://github.com/php-school/php-workshop
  4. Laravel Console Menu 扩展包:https://github.com/nunomaduro/laravel-console-menu
  5. Symfony Console 整合:https://github.com/RedAntNL/console

发表评论

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网 🐾 DeepracticeX 社区 🐾 老薛主机 🐾 智柴论坛 🐾