Compare commits

...

8 Commits

Author SHA1 Message Date
Chris 08ab24d665 Bugfixes to help command 2017-01-30 12:10:23 +01:00
Chris fdd1814875 Moved onEnter event 2017-01-29 20:31:04 +01:00
Chris 75c624520d Updated examples, added onEnter method to contexts 2017-01-29 20:27:17 +01:00
Chris ec60970b5d Added getContext method to shell 2017-01-28 13:00:26 +01:00
Chris 7c76928c3b Even more tweaks 2017-01-27 04:43:44 +01:00
Chris ff9845e23e Tweaks to help styling 2017-01-27 04:36:23 +01:00
Chris e5b328b822 Spiced up the help 2017-01-27 04:30:50 +01:00
Chris cee82fc740 Added getInput() method for basic async input 2017-01-25 21:49:26 +01:00
5 changed files with 144 additions and 24 deletions

View File

@ -36,9 +36,9 @@ $myShell->setPrompt("test>");
// Create an anonymous context and add a command
$ctx = $myShell->createContext("root");
$ctx->addCommand("hello", function () {
echo "Hello World!\n";
});
$ctx->addCommand("hello", function ($who="World") {
echo "Hello {$who}!\n";
}, [ "help"=>"Say hello", "args"=>"who" ]);
// Run the shell
$myShell->run();

View File

@ -6,21 +6,46 @@ use NoccyLabs\Shell\Shell;
use NoccyLabs\Shell\Context;
$shell = new Shell();
$shell->addListener("prompt", function ($event, $shell) {
$name = $shell->getContextPath();
$shell->setPrompt("shell{$name}> ");
$shell->addListener(Shell::EVT_UPDATE_PROMPT, function ($event) {
$name = $event->shell->getContextPath();
$event->shell->setPrompt("shell{$name}> ");
});
$root = new Context();
$root->addCommand("test", function () {
echo "It works!\n";
});
$root->addCommand("context", function ($name) {
$context = new Context($name);
$context->name = $name;
return $context;
});
$shell->pushContext($root);
class MyContext extends Context
{
public function __construct()
{
// Remember to call the parent constructor if you want to use
// the doccomment syntax to mark commands, as demonstrated
// at the end of this class for the bar command.
parent::__construct();
$this->addCommand("foo",[$this,"foo"],[
'help' => "Foo command"
]);
}
public function onEnter()
{
echo "Entering context!\n";
}
public function foo()
{
echo "Foo!\n";
}
/**
* @command bar
* @args
* @help Bar command
*/
public function bar()
{
echo "Bar!\n";
}
}
$shell->pushContext(new MyContext());
$shell->run();

31
examples/input.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/*
* This example demonstrates how to use events to catch commands that
* have not been handled by any context or builtin.
*
*/
require_once __DIR__."/../vendor/autoload.php";
use NoccyLabs\Shell\Shell;
use NoccyLabs\Shell\Style;
use NoccyLabs\Shell\Context;
$myShell = new Shell();
// Set the initial prompt, not really needed.
$myShell->setPrompt("test>");
// Create an anonymous context and add a command
$ctx = $myShell->createContext("root");
$ctx->addCommand("hello", function () use ($myShell) {
$myShell->getInput("What is your name?", function ($name) use ($myShell) {
echo "Hello, {$name}\n";
$myShell->getInput("Who is your daddy and what does he do?", function ($daddy) {
echo "{$daddy}? Oookay...\n";
});
});
});
// Run the shell
$myShell->run();

View File

@ -66,6 +66,11 @@ class Context
$this->findCommands();
}
public function onEnter()
{
}
protected function findCommands()
{
$refl = new \ReflectionClass(get_called_class());

View File

@ -54,6 +54,18 @@ class Shell
* @var Style The style applied to the input text
*/
protected $input_style = null;
/**
* @var callable The callback to pass the input on to
*/
protected $input_callback = null;
/**
* @var string Question prompt for getInput()
*/
protected $input_prompt = null;
/**
* @var string The prompt before changing to $input_prompt
*/
protected $input_last_prompt = null;
/**
* Constructor
@ -78,6 +90,16 @@ class Shell
}
}
/**
* Return the current context
*
* @return Context The current context
*/
public function getContext()
{
return $this->context;
}
/**
* Push a new primary context, saving the previous contexts on a stack.
*
@ -92,6 +114,7 @@ class Shell
$context->setShell($this);
$this->context = $context;
$this->dispatchEvent(self::EVT_CONTEXT_CHANGED);
$context->onEnter();
}
/**
@ -227,7 +250,7 @@ class Shell
public function setPrompt($text)
{
$this->prompt = $text;
if ($this->lineReader) {
$this->lineReader->setPromptText($text);
}
@ -395,19 +418,30 @@ class Shell
}
}
ksort($ghelp);
printf("Commands in current context:\n");
$_ = function($command,$args,$info) {
printf(" \e[96m%s\e[0m \e[0;3m%s\e[0m \e[30G\e[36m%s\e[0m\n", $command, $args, $info);
};
printf("\e[1mCommands:\e[0m\n");
foreach ($help as $command=>$info) {
printf(" %-20s %s\n", $command, $info);
if (strpos($command," ")!==false) {
list($command,$args) = explode(" ",$command,2);
} else $args=null;
$_($command, $args,$info);
}
if (count($ghelp)) {
printf("\nImported from parent contexts:\n");
foreach ($ghelp as $command=>$info) {
printf(" %-20s %s\n", $command, $info);
printf("\e[1mCommands from parent contexts:\e[0m\n");
if (strpos($command," ")!==false) {
list($command,$args) = explode(" ",$command,2);
} else $args=null;
if (!array_key_exists($command,$ghelp)) continue;
$_($command, $args,$info);
}
}
printf("\nGlobal commands:\n");
printf(" %-20s %s\n", "exit", "Leave the shell");
printf(" %-20s %s\n", "..", "Discard the current context and go to parent");
printf("\e[1mGlobal commands:\e[0m\n");
$_("exit", null, "Leave the shell");
$_(".", null, "Show the context tree");
$_("..", null, "Discard the current context and go to parent");
break;
case 'exit':
$this->stop();
@ -532,6 +566,31 @@ class Shell
return $event;
}
public function getInput($prompt, callable $callback)
{
$this->addListener(Shell::EVT_UPDATE_PROMPT, [ $this, "onInputPrompt" ], $prompt);
$this->addListener(Shell::EVT_BEFORE_COMMAND, [ $this, "onInputHandler" ], $this->prompt, $callback);
}
public function onInputPrompt(Event $e, $prompt)
{
$this->setPrompt($prompt);
$e->stopPropagation();
$this->removeListener(Shell::EVT_UPDATE_PROMPT, [ $this, "onInputPrompt" ], $prompt);
}
public function onInputHandler(Event $e, $last_prompt, $callback)
{
// Restore the prompt
$this->setPrompt($last_prompt);
// Remove the listeners and compose the result string
$this->removeListener(Shell::EVT_BEFORE_COMMAND, [ $this, "onInputHandler" ], $last_prompt, $callback);
$input = trim($e->command." ".join(" ",$e->args));
$e->stopPropagation();
// Call the callback
call_user_func($callback, $input);
}
/**
* Stop the shell; calling this method will cause the main run() to return.
*