Code cleanup, better examples, tasks added
This commit is contained in:
@ -132,6 +132,7 @@ class Context
|
||||
$info = $this->commandInfo[$command];
|
||||
$args = array_key_exists("args",$info)?$info['args']:"";
|
||||
$help = array_key_exists("help",$info)?$info['help']:"";
|
||||
$help = $help?:(array_key_exists("descr",$info)?$info['descr']:"");
|
||||
$ret[trim("{$command} {$args}")] = $help;
|
||||
}
|
||||
return $ret;
|
||||
|
@ -13,12 +13,14 @@ class Shell
|
||||
const EVT_UPDATE_PROMPT = "shell.prompt"; // called to update the prompt
|
||||
const EVT_BEFORE_COMMAND = "shell.command.before"; // before a command is executed
|
||||
const EVT_AFTER_COMMAND = "shell.command.after"; // after a command is executed
|
||||
const EVT_NO_COMMAND = "shell.command.missing"; // no such command found
|
||||
const EVT_BAD_COMMAND = "shell.command.bad"; // no such command found
|
||||
const EVT_CONTEXT_CHANGED = "shell.context"; // a new context is activated
|
||||
const EVT_SHELL_START = "shell.start"; // the shell is about to start
|
||||
const EVT_SHELL_STOP = "shell.stop"; // the shell is about to exit
|
||||
const EVT_SHELL_ABORT = "shell.abort"; // the shell was aborted (ctrl-c)
|
||||
const EVT_SHELL_ESCAPE = "shell.escape"; // escape key pressed
|
||||
const EVT_TASK_CREATED = "task.created"; // a task was created
|
||||
const EVT_TASK_DESTROYED = "task.destryed"; // a task was removed or invalidated
|
||||
|
||||
/**
|
||||
* @var LineRead The lineread instance
|
||||
@ -34,10 +36,10 @@ class Shell
|
||||
protected $contextStack = [];
|
||||
/**
|
||||
* @var object[] Created timers
|
||||
*/
|
||||
*/
|
||||
protected $timers = [];
|
||||
/**
|
||||
* @var object[] Running subtasks
|
||||
/**
|
||||
* @var TaskInterface[] Created tasks
|
||||
*/
|
||||
protected $tasks = [];
|
||||
/**
|
||||
@ -186,6 +188,37 @@ class Shell
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a task to be update():d in the main loop.
|
||||
*
|
||||
* @param TaskInterface $task The task to add
|
||||
*/
|
||||
public function addTask(TaskInterface $task)
|
||||
{
|
||||
if ($this->dispatchEvent(self::EVT_TASK_CREATED, [
|
||||
'task' => $task
|
||||
])->isPropagationStopped()) {
|
||||
return;
|
||||
}
|
||||
$this->tasks[] = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a previously added task. This can also be done by the task returning
|
||||
* false from its isValid() method.
|
||||
*
|
||||
* @param TaskInterface $task The task to remove
|
||||
*/
|
||||
public function removeTask(TaskInterface $task)
|
||||
{
|
||||
$this->tasks = array_filter($this->tasks, function ($item) use ($task) {
|
||||
return ($item != $task);
|
||||
});
|
||||
$this->dispatchEvent(self::EVT_TASK_DESTROYED, [
|
||||
'task' => $task
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prompt text
|
||||
*
|
||||
@ -268,7 +301,19 @@ class Shell
|
||||
*/
|
||||
public function executeCommand($command, ...$args)
|
||||
{
|
||||
if ($this->dispatchEvent(self::EVT_BEFORE_COMMAND, [
|
||||
'command' => $command,
|
||||
'args' => $args
|
||||
])->isPropagationStopped()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->executeBuiltin($command, ...$args)) {
|
||||
$this->dispatchEvent(self::EVT_AFTER_COMMAND, [
|
||||
'command' => $command,
|
||||
'args' => $args,
|
||||
'type' => 'builtin'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -278,11 +323,31 @@ class Shell
|
||||
if ($ret instanceof Context) {
|
||||
$this->pushContext($ret);
|
||||
}
|
||||
$this->dispatchEvent(self::EVT_AFTER_COMMAND, [
|
||||
'command' => $command,
|
||||
'args' => $args,
|
||||
'type' => 'command'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Call 'execute' on the current context
|
||||
if ($this->context->execute($command, ...$args)) {
|
||||
$this->dispatchEvent(self::EVT_AFTER_COMMAND, [
|
||||
'command' => $command,
|
||||
'args' => $args,
|
||||
'type' => 'execute'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire the EVT_BAD_COMMAND event and return if the event propagation
|
||||
// has been stopped.
|
||||
$evt = $this->dispatchEvent(self::EVT_BAD_COMMAND, [
|
||||
'command'=>$command,
|
||||
'args'=>$args
|
||||
]);
|
||||
if ($evt->isPropagationStopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -330,12 +395,12 @@ class Shell
|
||||
}
|
||||
}
|
||||
ksort($ghelp);
|
||||
//printf("Commands in current context:\n");
|
||||
printf("Commands in current context:\n");
|
||||
foreach ($help as $command=>$info) {
|
||||
printf(" %-20s %s\n", $command, $info);
|
||||
}
|
||||
if (count($ghelp)) {
|
||||
//printf("\nImported from parent contexts:\n");
|
||||
printf("\nImported from parent contexts:\n");
|
||||
foreach ($ghelp as $command=>$info) {
|
||||
printf(" %-20s %s\n", $command, $info);
|
||||
}
|
||||
@ -411,8 +476,14 @@ class Shell
|
||||
foreach ($this->timers as $timer) {
|
||||
$timer->update();
|
||||
}
|
||||
foreach ($this->tasks as $task) {
|
||||
foreach ($this->tasks as $taskidx=>$task) {
|
||||
$task->update();
|
||||
if (!$task->isValid()) {
|
||||
$this->dispatchEvent(self::EVT_TASK_DESTROYED, [
|
||||
'task' => $task
|
||||
]);
|
||||
unset($this->tasks[$taskidx]);
|
||||
}
|
||||
}
|
||||
if ($buffer) {
|
||||
$this->executeBuffer($buffer);
|
||||
@ -423,11 +494,13 @@ class Shell
|
||||
if (trim($output)) {
|
||||
$this->lineReader->erase();
|
||||
echo rtrim($output)."\n";
|
||||
$this->lineReader->redraw();
|
||||
if ($this->running)
|
||||
$this->lineReader->redraw();
|
||||
}
|
||||
|
||||
if (!$this->context) {
|
||||
$this->stop();
|
||||
break;
|
||||
}
|
||||
|
||||
if ($buffer) {
|
||||
@ -456,6 +529,7 @@ class Shell
|
||||
$data['context'] = $this->context;
|
||||
$event = new Event($type, $data);
|
||||
$this->emitEvent($type, $event);
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
|
10
lib/TaskInterface.php
Normal file
10
lib/TaskInterface.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace NoccyLabs\Shell;
|
||||
|
||||
interface TaskInterface
|
||||
{
|
||||
public function update();
|
||||
|
||||
public function isValid();
|
||||
}
|
Reference in New Issue
Block a user