mcrumm/pecan

基于 Symfony Console Shell 的基于事件驱动的、非阻塞的 ReactPHP shell。

v1.0 2014-03-24 02:23 UTC

This package is not auto-updated.

Last update: 2024-09-14 15:17:12 UTC


README

基于 ReactPHP 的事件驱动、非阻塞 shell。

Pecan (/pɪˈkɑːn/) 提供了对在 Symfony Console 组件中提供的 shell 的非阻塞替代方案。此外,Pecan 还包括一个基本的、与框架无关的 shell 组件 Drupe,可以用作构建自定义 shell 的基础。

Drupe

Pecan\Drupe 是一个用于构建事件驱动控制台组件的独立组件。我喜欢将其视为没有 Shell 的 Pecan。

start() 中传递 EventLoopInterface 以监听输入。

$loop  = \React\EventLoop\Factory::create();
$shell = new \Pecan\Drupe();

// $shell->start() returns $loop to allow this chaining.
$shell->start($loop)->run();

Drupe 事件

  • running - Shell 正在运行。
  • data - 从 STDIN 接收到数据。
  • error - 表示 I/O 问题。
  • close - Shell 已关闭。

Pecan\Shell 扩展 Drupe 以提供对标准 Symfony\Component\Console\Application 的事件驱动包装。它可以作为 Symfony\Component\Console\Shell 的替代品。

注意:为了保持与 Symfony Console 类似的流程,在 Pecan\Shell 上调用 $shell->run() 将启动事件循环,因此请确保它最后被调用。

壳事件

Shell 发射与 Drupe 相同的事件。

Readline

Pecan\Readline 提供了一个从 STDIN 逐行读取输入的接口。此组件深受 NodeJS Readline 组件 的启发,并努力与它保持一致。

Readline 事件

  • line - 已从 STDIN 读取一行。
  • pause - 从流中读取已暂停。
  • resume - 从流中读取已恢复。
  • error - 输入流遇到错误。
  • close - 输入流已关闭。

控制台

Pecan\Console\Console 提供了一个与 STDOUTSTDERR 交互的标准接口。它深受 NodeJS 控制台组件 的启发,并从 Symfony 控制台组件 中借鉴了一些功能。

输出

输出类扩展了基本的控制台输出。 StreamOutput 包装单个流资源,而 ConsoleOutput 包含了 STDOUTSTDERR 流。

  • StreamOutputInterface
  • ConsoleOutputInterface
  • PecanOutput

使用 Pecan

将 Drupe 作为独立 shell 使用

use Pecan\Drupe;

$loop   = \React\EventLoop\Factory::create();
$shell  = new Drupe();

// Example one-time callback to write the initial prompt.
// This resumes reading from STDIN and kicks off the shell.
$shell->once('running', function (Drupe $shell) {
    $shell->setPrompt('drupe> ')->prompt();
});

// Example callback for the data event.
// By convention, any call to write() will be followed by a call to prompt() 
// once the data has been written to the output stream.
$shell->on('data', function ($line, Drupe $shell) {

    $command = (!$line && strlen($line) == 0) ? false : rtrim($line);

    if ('exit' === $command || false === $command) {
        $shell->close();
    } else {
        $shell->writeln(sprintf(PHP_EOL.'// in: %s', $line));
    }

});

// Example callback for the close event.
$shell->on('close', function ($code, Drupe $shell) {
    $shell->writeln([
        '// Goodbye.',
        sprintf('// Shell exits with code %d', $code),
    ]);
});

$shell->start($loop)->run();

在 Symfony Console 应用中使用 Shell

这是一个将任何接收到的输入回显并退出的 shell。

// Pecan\Shell wraps a standard Console Application.
use Symfony\Component\Console\Application;
use Pecan\Shell;

$shell = new Shell(new Application('pecan'));

$shell->on('data', function($line, Shell $shell) {
    $shell->write($line)->then(function($shell) {
        $shell->close();
    });
});

$shell->run();

EventLoopInterface 注入到 Pecan\Shell

除非你将实现 EventLoopInterface 的对象作为其第二个构造函数参数传递给 \Pecan\Shell,否则 Shell 将从事件循环工厂中获取一个。如果你想将 Pecan 集成到现有的 ReactPHP 项目中,请记住这一点。

use Symfony\Component\Console\Application;
use Pecan\Shell;

$loop  = \React\EventLoop\Factory::create();

// Do other things requiring $loop...

$shell = new Shell(new Application('pecan'), $loop);

// We must still let the shell run the EventLoop.
$shell->run();

示例 exit 回调

// Example callback for the exit event.
$shell->on('exit', function($code, \Pecan\Shell $shell) {
    $shell->emit('output', [
        [
            'Goodbye.',
            sprintf('// Shell exits with code %d', $code)
        ],
        true
    ]);
});