Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Adding subcommand to help output.
Subcommands can be shell methods or tasks.  Both should support additional parsers.  Which is not complete yet.
  • Loading branch information
markstory committed Oct 14, 2010
1 parent 278f699 commit 56339e0
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 3 deletions.
68 changes: 66 additions & 2 deletions cake/console/console_option_parser.php
Expand Up @@ -67,6 +67,13 @@ class ConsoleOptionParser {
*/
protected $_args = array();

/**
* Subcommands for this Shell.
*
* @var array
*/
protected $_subcommands = array();

/**
* Construct an OptionParser so you can define its behavior
*
Expand Down Expand Up @@ -214,6 +221,33 @@ public function addArgument($name, $params = array()) {
return $this;
}

/**
* Append a subcommand to the subcommand list.
* Subcommands are usually methods on your Shell, but can also be used to document
* Tasks
*
* ### Params
*
* - `help` - Help text for the subcommand.
* - `parser` - A ConsoleOptionParser for the subcommand. This allows you to create method
* specific option parsers. When help is generated for a subcommand, if a parser is present
* it will be used.
*
* @param string $name Name of the subcommand
* @param array $params Array of params, see above.
* @return $this.
*/
public function addSubcommand($name, $params = array()) {
$defaults = array(
'name' => $name,
'help' => '',
'parser' => null
);
$options = array_merge($defaults, $params);
$this->_subcommands[$name] = $options;
return $this;
}

/**
* Gets the arguments defined in the parser.
*
Expand Down Expand Up @@ -278,6 +312,20 @@ public function help() {
$out[] = '<info>Usage:</info>';
$out[] = $this->_generateUsage();
$out[] = '';
if (!empty($this->_subcommands)) {
$out[] = '<info>Subcommands:</info>';
$out[] = '';
$max = 0;
foreach ($this->_subcommands as $description) {
$max = (strlen($description['name']) > $max) ? strlen($description['name']) : $max;
}
$max += 2;
foreach ($this->_subcommands as $description) {
$out[] = $this->_subcommandHelp($description, $max);
}
$out[] = '';
}

if (!empty($this->_options)) {
$max = 0;
foreach ($this->_options as $description) {
Expand All @@ -296,7 +344,7 @@ public function help() {
foreach ($this->_args as $description) {
$max = (strlen($description['name']) > $max) ? strlen($description['name']) : $max;
}
$max += 1;
$max += 2;
$out[] = '<info>Arguments:</info>';
$out[] = '';
foreach ($this->_args as $description) {
Expand All @@ -319,6 +367,9 @@ public function help() {
*/
protected function _generateUsage() {
$usage = array('cake ' . $this->_command);
if (!empty($this->_subcommands)) {
$usage[] = '[subcommand]';
}
foreach ($this->_options as $definition) {
$name = empty($definition['short']) ? '--' . $definition['name'] : '-' . $definition['short'];
$default = '';
Expand Down Expand Up @@ -371,7 +422,20 @@ protected function _argumentHelp($definition, $width) {
if (!$definition['required']) {
$optional = ' <comment>(optional)</comment>';
}
return sprintf('%s %s%s', $name, $definition['help'], $optional);
return sprintf('%s%s%s', $name, $definition['help'], $optional);
}

/**
* Generate help for a single subcommand.
*
* @return string
*/
protected function _subcommandHelp($definition, $width) {
$name = $definition['name'];
if (strlen($name) < $width) {
$name = str_pad($name, $width, ' ');
}
return $name . $definition['help'];
}

/**
Expand Down
44 changes: 43 additions & 1 deletion cake/tests/cases/console/console_option_parser.test.php
Expand Up @@ -234,6 +234,19 @@ function testPositionalArgNotEnough() {
$parser->parse(array('one'));
}

/**
* test setting a subcommand up.
*
* @return void
*/
function testSubcommand() {
$parser = new ConsoleOptionParser();
$result = $parser->addSubcommand('initdb', array(
'help' => 'Initialize the database'
));
$this->assertEquals($parser, $result, 'Adding a subcommand is not chainable');
}

/**
* test getting help with defined options.
*
Expand Down Expand Up @@ -296,7 +309,7 @@ function testHelpWithOptionsAndArguments() {
*
* @return void
*/
function testDescriptionAndEpilog() {
function testHelpDescriptionAndEpilog() {
$parser = new ConsoleOptionParser('mycommand', false);
$parser->description('Description text')
->epilog('epilog text')
Expand All @@ -323,4 +336,33 @@ function testDescriptionAndEpilog() {
TEXT;
$this->assertEquals($expected, $result, 'Help is wrong.');
}

/**
* test that help() outputs subcommands.
*
* @return void
*/
function testHelpSubcommand() {
$parser = new ConsoleOptionParser('mycommand', false);
$parser->addSubcommand('method', array('help' => 'This is another command'))
->addOption('test', array('help' => 'A test option.'));

$result = $parser->help();
$expected = <<<TEXT
<info>Usage:</info>
cake mycommand [subcommand] [-h] [--test]
<info>Subcommands:</info>
method This is another command
<info>Options:</info>
--help, -h Display this help.
--test A test option.
TEXT;
$this->assertEquals($expected, $result, 'Help is not correct.');

}
}

0 comments on commit 56339e0

Please sign in to comment.