diff --git a/Clim/Context.php b/Clim/Context.php index c182306..9d52cf7 100644 --- a/Clim/Context.php +++ b/Clim/Context.php @@ -107,4 +107,18 @@ public function setResult($result) { $this->result = $result; } + + /** + * @param callable $callable + * @return mixed + */ + public function execute(callable $callable) + { + $options = new Hash($this->options()); + $arguments = new Hash($this->arguments()); + + $result = call_user_func_array($callable, [$options, $arguments]); + if (!is_null($result)) $this->setResult($result); + return $result; + } } diff --git a/Clim/Dispatcher.php b/Clim/Dispatcher.php index 6b4a075..12242b9 100644 --- a/Clim/Dispatcher.php +++ b/Clim/Dispatcher.php @@ -18,6 +18,8 @@ class Dispatcher extends Component implements ArgumentInterface /** @var ContainerInterface $container */ private $container; + /** @var array */ + private $map; /** * @param string $definition * @param array $children @@ -31,17 +33,24 @@ public function __construct($definition, array $children, ContainerInterface $co $this->children = $children; $this->container = $container; + $this->map = []; + foreach (array_keys($this->children) as $key) { + $keys = explode('|', $key); + foreach ($keys as $name) { + $this->map[$name] = $children[$key]; + } + } } public function handle($argument, Parameters $parameters, Context $context) { $this->needDefined(); - if (!array_key_exists($argument, $this->children)) { - throw new \Exception("invalid sub command"); + if (!array_key_exists($argument, $this->map)) { + throw new \Exception("invalid sub command: " . $argument); } - $builder = $this->children[$argument]; + $builder = $this->map[$argument]; $child = new App($this->container); call_user_func($builder, $child); diff --git a/Clim/Runner.php b/Clim/Runner.php index 973a2f2..e102b10 100644 --- a/Clim/Runner.php +++ b/Clim/Runner.php @@ -59,11 +59,8 @@ public function run($argv, Context $context = null) $context->push($this->parameters->next()); } - $options = new Hash($context->options()); - $arguments = new Hash($context->arguments()); - foreach ($this->spec->tasks() as $task) { - call_user_func($task, $options, $arguments); + $context->execute($task); } return $context; diff --git a/tests/unit/DispatchCept.php b/tests/unit/DispatchCept.php index d2a05af..6c60886 100644 --- a/tests/unit/DispatchCept.php +++ b/tests/unit/DispatchCept.php @@ -1,11 +1,12 @@ wantTo('perform dispatch and see the result'); -$app = new Clim\App(['name' => 'Kashiyuka']); +$app = new App(['name' => 'Kashiyuka']); // global option $app->option('--age {AGE|\\d+}'); @@ -34,3 +35,18 @@ $I->willPassArguments($app, ['hello_dispatch', 'bar']); $I->assertOutputEquals($app, "BAR\n"); +$app = new App(); +$app->dispatch('{COMMAND}', [ + 'ls|list' => function (App $app) { + $app->task(function () { + return 'HELLO'; + }); + } +]); + +$context = $app->runner()->run(['ls']); +$I->assertEquals('HELLO', $context->getResult()); + +$context = $app->runner()->run(['list']); +$I->assertEquals('HELLO', $context->getResult()); +