Adding subcommand to help output.

Subcommands can be shell methods or tasks.  Both should support additional parsers.  Which is not complete yet.
This commit is contained in:
mark_story 2010-10-10 01:23:20 -04:00
parent 278f699fda
commit 56339e05f3
2 changed files with 109 additions and 3 deletions

View file

@ -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
*
@ -214,6 +221,33 @@ class ConsoleOptionParser {
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.
*
@ -278,6 +312,20 @@ class ConsoleOptionParser {
$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) {
@ -296,7 +344,7 @@ class ConsoleOptionParser {
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) {
@ -319,6 +367,9 @@ class ConsoleOptionParser {
*/
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 = '';
@ -371,7 +422,20 @@ class ConsoleOptionParser {
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'];
}
/**

View file

@ -234,6 +234,19 @@ class ConsoleOptionParserTest extends CakeTestCase {
$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.
*
@ -296,7 +309,7 @@ TEXT;
*
* @return void
*/
function testDescriptionAndEpilog() {
function testHelpDescriptionAndEpilog() {
$parser = new ConsoleOptionParser('mycommand', false);
$parser->description('Description text')
->epilog('epilog text')
@ -323,4 +336,33 @@ epilog text
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.');
}
}