react-shell/src/CommandHandler.php

66 lines
1.7 KiB
PHP

<?php
namespace NoccyLabs\React\Shell;
use Evenement\EventEmitterInterface;
use Evenement\EventEmitterTrait;
use React\EventLoop\Loop;
class CommandHandler implements EventEmitterInterface
{
use EventEmitterTrait;
private array $commands = [];
private bool $allowAbbreviatedCommands = false;
public function setAllowAbbreviatedCommands(bool $allow): self
{
$this->allowAbbreviatedCommands = $allow;
return $this;
}
public function getAllowAbbreviatedCommands(): bool
{
return $this->allowAbbreviatedCommands;
}
public function add(string $command, callable $handler, array $signature=[]): self
{
$this->commands[$command] = [ 'handler' => $handler, 'signature' => $signature ];
return $this;
}
public function __invoke(array $line, Shell $shell)
{
$this->execute($line, $shell);
}
public function execute(array $line, Shell $shell)
{
$command = array_shift($line);
if ($this->allowAbbreviatedCommands) {
$candidates = array_filter(
array_keys($this->commands),
fn($c)=>str_starts_with($c,$command)
);
if (count($candidates)>1) {
$this->emit("candidates", [ $candidates, $shell ]);
return;
}
if (count($candidates)==1) {
$command = array_shift($candidates);
}
}
if (!array_key_exists($command, $this->commands)) {
$this->emit("command", [ $command, $line, $shell ]);
return;
}
Loop::futureTick(fn() => call_user_func($this->commands[$command]['handler'], $line, $shell));
}
}