diff --git a/cake/console/console_option_parser.php b/cake/console/console_option_parser.php index 5c4bd1904b5..1bf516c31a3 100644 --- a/cake/console/console_option_parser.php +++ b/cake/console/console_option_parser.php @@ -52,6 +52,13 @@ class ConsoleOptionParser { */ protected $_options = array(); +/** + * Map of short -> long options, generated when using addOption() + * + * @var string + */ + protected $_shortOptions = array(); + /** * Positional argument definitions. * @@ -99,8 +106,24 @@ class ConsoleOptionParser { * can generate a help display for you. You can view the help for shells by using the `--help` or `-h` switch. * */ - public function __construct() { + public function __construct($command = null, $defaultOptions = true) { + $this->_command = $command; + $this->addOption('help', array( + 'short' => 'h', + 'help' => 'Display this help.', + 'boolean' => true + )); + + if ($defaultOptions) { + $this->addOption('verbose', array( + 'short' => 'v', + 'help' => __('Enable verbose output.') + ))->addOption('quiet', array( + 'short' => 'q', + 'help' => __('Enable quiet output.') + )); + } } /** @@ -158,7 +181,7 @@ public function addOption($name, $params = array()) { $options = array_merge($defaults, $params); $this->_options[$name] = $options; if (!empty($options['short'])) { - $this->_options[$options['short']] = $options; + $this->_shortOptions[$options['short']] = $name; } return $this; } @@ -200,6 +223,15 @@ public function arguments() { return $this->_args; } +/** + * Get the defined options in the parser. + * + * @return array + */ + public function options() { + return $this->_options; + } + /** * Parse the argv array into a set of params and args. * @@ -229,6 +261,62 @@ public function parse($argv) { return array($params, $args); } +/** + * Gets formatted help for this parser object. + * Generates help text based on the description, options, arguments and epilog + * in the parser. + * + * @return string + */ + public function help() { + $out = array(); + $out[] = 'Usage:'; + $out[] = 'cake ' . $this->_command . $this->_generateUsage(); + $out[] = ''; + if (!empty($this->_options)) { + $max = 0; + foreach ($this->_options as $description) { + $max = (strlen($description['name']) > $max) ? strlen($description['name']) : $max; + } + $max += 3; + $out[] = 'Options:'; + $out[] = ''; + foreach ($this->_options as $description) { + $out[] = $this->_optionHelp($description, $max); + } + } + return implode("\n", $out); + } + +/** + * Generate the usage for a shell based on its arguments and options. + * + * @return void + */ + protected function _generateUsage() { + + } + +/** + * Generate the usage for a single option. + * + * @return string + */ + protected function _optionHelp($definition, $nameWidth) { + $default = $short = ''; + if (!empty($definition['default']) && $definition['default'] !== true) { + $default = sprintf(__(' (default: %s)'), $definition['default']); + } + if (!empty($definition['short'])) { + $short = ', -' . $definition['short']; + } + $name = sprintf('--%s%s', $definition['name'], $short); + if (strlen($name) < $nameWidth) { + $name = str_pad($name, $nameWidth, ' '); + } + return sprintf('%s %s%s', $name, $definition['help'], $default); + } + /** * Parse the value for a long option out of $this->_tokens. Will handle * options with an `=` in them. @@ -264,7 +352,7 @@ protected function _parseShortOption($option, $params) { array_unshift($this->_tokens, '-' . $flags[$i]); } } - $name = $this->_options[$key]['name']; + $name = $this->_shortOptions[$key]; return $this->_parseOptionName($name, $params); } diff --git a/cake/tests/cases/console/console_option_parser.test.php b/cake/tests/cases/console/console_option_parser.test.php index 2b7863483e4..3b99fa710d7 100644 --- a/cake/tests/cases/console/console_option_parser.test.php +++ b/cake/tests/cases/console/console_option_parser.test.php @@ -222,4 +222,28 @@ function testPositionalArgNotEnough() { $parser->parse(array('one')); } + +/** + * test getting help with defined options. + * + * @return void + */ + function testGetHelpWithOptions() { + $parser = new ConsoleOptionParser('mycommand', false); + $parser->addOption('test', array('short' => 't', 'help' => 'A test option.')) + ->addOption('connection', array('help' => 'The connection to use.', 'default' => 'default')); + + $result = $parser->help(); + $expected = <<Usage: +cake mycommand [-h] [-t] [--connection default] + +Options: + +--help, -h Display this help. +--test, -t A test option. +--connection The connection to use. (default: default) +TEXT; + $this->assertEquals($expected, $result, 'Help does not match'); + } } \ No newline at end of file