diff --git a/examples/simple.php b/examples/simple.php index 603fe4b..6e02f18 100644 --- a/examples/simple.php +++ b/examples/simple.php @@ -4,6 +4,7 @@ require_once __DIR__."/../vendor/autoload.php"; use NoccyLabs\Shell\Shell; use NoccyLabs\Shell\Command; +use NoccyLabs\Shell\Context; class MyCommand extends Command { @@ -13,6 +14,18 @@ class MyCommand extends Command } } +class MyContext extends Context +{ + /** + * @args + * @help Useful test! + */ + public function test() + { + + } +} + class MyShell extends Shell { @@ -20,7 +33,8 @@ class MyShell extends Shell protected function configure() { - $context = $this->createContext(); + $context = new MyContext(); + $this->pushContext($context); $context->addCommand("hello", function () { echo "world\nthis\nis\na\ntest\n"; }); diff --git a/lib/Context.php b/lib/Context.php index 6264add..4ed996e 100644 --- a/lib/Context.php +++ b/lib/Context.php @@ -8,6 +8,8 @@ class Context protected $commands = []; + protected $commandInfo = []; + protected $data = []; @@ -21,11 +23,42 @@ class Context protected function configure() { // Override this to do setup stuff + $this->findCommands(); } - public function addCommand($command, callable $handler) + protected function findCommands() + { + $refl = new \ReflectionClass(get_called_class()); + foreach ($refl->getMethods() as $method) { + $docblock = $method->getDocComment(); + $lines = array_map(function ($line) { + return trim($line, "*/ \t"); + }, explode("\n", $docblock)); + $info = []; + foreach ($lines as $line) { + if (preg_match("/^@(command|help|args) (.+?)$/", $line, $match)) { + list($void,$key,$value) = $match; + $info[$key] = $value; + } + if (count($info)>0) { + $this->addCommand($method->getName(), [$this, $method->getName()], $info); + } + } + } + } + + public function addCommand($command, callable $handler, array $info=[]) { $this->commands[$command] = $handler; + $this->commandInfo[$command] = $info; + } + + public function setCommandHelp($command, $help) + { + if (!array_key_exists($command, $this->commandInfo)) { + return; + } + $this->commandInfo[$command]['help'] = $help; } public function addCommands(array $commands) @@ -50,6 +83,18 @@ class Context return $this->commands[$command]; } + public function getCommandHelp() + { + $ret = []; + foreach ($this->commands as $command=>$handler) { + $info = $this->commandInfo[$command]; + $args = array_key_exists("args",$info)?$info['args']:""; + $help = array_key_exists("help",$info)?$info['help']:""; + $ret[trim("{$command} {$args}")] = $help; + } + return $ret; + } + public function getName() { return $this->name; diff --git a/lib/Shell.php b/lib/Shell.php index a744f7b..be58842 100644 --- a/lib/Shell.php +++ b/lib/Shell.php @@ -210,11 +210,14 @@ class Shell $this->popContext(); break; case 'help': - echo - "Built in commands:\n". - " . Show current context\n". - " .. Go to parent context\n". - " exit Exit the shell\n"; + $help = $this->context->getCommandHelp(); + printf("Commands in current context:\n\n"); + foreach ($help as $command=>$info) { + printf(" %-20s %s\n", $command, $info); + } + printf("\nGlobal commands:\n\n"); + printf(" %-20s %s\n", "exit", "Leave the shell"); + printf(" %-20s %s\n", "..", "Discard the current context and go to parent"); break; case 'exit': $this->stop();