702 lines
24 KiB
PHP
702 lines
24 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* This package is ported from Python's Optik (http://optik.sourceforge.net/).
|
|
*
|
|
* See the enclosed file LICENSE for license information (BSD). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/bsd.
|
|
*
|
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
|
* @author Mike Naberezny <mike@maintainable.com>
|
|
* @license http://www.horde.org/licenses/bsd BSD
|
|
* @category Horde
|
|
* @package Argv
|
|
*/
|
|
|
|
/**
|
|
* Horde command-line argument parsing package.
|
|
*
|
|
* Class attributes:
|
|
* standardOptionList : [Option]
|
|
* list of standard options that will be accepted by all instances
|
|
* of this parser class (intended to be overridden by subclasses).
|
|
*
|
|
* Instance attributes:
|
|
* usage : string
|
|
* a usage string for your program. Before it is displayed
|
|
* to the user, "%prog" will be expanded to the name of
|
|
* your program ($this->prog or os.path.basename(sys.argv[0])).
|
|
* prog : string
|
|
* the name of the current program (to override
|
|
* os.path.basename(sys.argv[0])).
|
|
* epilog : string
|
|
* paragraph of help text to print after option help
|
|
*
|
|
* optionGroups : [OptionGroup]
|
|
* list of option groups in this parser (option groups are
|
|
* irrelevant for parsing the command-line, but very useful
|
|
* for generating help)
|
|
*
|
|
* allowInterspersedArgs : bool = true
|
|
* if true, positional arguments may be interspersed with options.
|
|
* Assuming -a and -b each take a single argument, the command-line
|
|
* -ablah foo bar -bboo baz
|
|
* will be interpreted the same as
|
|
* -ablah -bboo -- foo bar baz
|
|
* If this flag were false, that command line would be interpreted as
|
|
* -ablah -- foo bar -bboo baz
|
|
* -- ie. we stop processing options as soon as we see the first
|
|
* non-option argument. (This is the tradition followed by
|
|
* Python's getopt module, Perl's Getopt::Std, and other argument-
|
|
* parsing libraries, but it is generally annoying to users.)
|
|
*
|
|
* allowUnknownArgs : bool = false
|
|
* if true, unrecognized arguments will be auto-created, instead
|
|
* of throwing a BadOptionException.
|
|
*
|
|
* ignoreUnknownArgs : bool = false
|
|
* if true, unrecognized arguments will be silently skipped, instead of
|
|
* throwing a BadOptionException.
|
|
*
|
|
* rargs : [string]
|
|
* the argument list currently being parsed. Only set when
|
|
* parseArgs() is active, and continually trimmed down as
|
|
* we consume arguments. Mainly there for the benefit of
|
|
* callback options.
|
|
* largs : [string]
|
|
* the list of leftover arguments that we have skipped while
|
|
* parsing options. If allowInterspersedArgs is false, this
|
|
* list is always empty.
|
|
* values : Values
|
|
* the set of option values currently being accumulated. Only
|
|
* set when parseArgs() is active. Also mainly for callbacks.
|
|
*
|
|
* @category Horde
|
|
* @package Argv
|
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
|
* @author Mike Naberezny <mike@maintainable.com>
|
|
* @copyright 2010-2017 Horde LLC
|
|
* @license http://www.horde.org/licenses/bsd BSD
|
|
*/
|
|
class Horde_Argv_Parser extends Horde_Argv_OptionContainer
|
|
{
|
|
public $standardOptionList = array();
|
|
|
|
protected $_usage;
|
|
public $optionGroups = array();
|
|
|
|
public function __construct($args = array())
|
|
{
|
|
$args = array_merge(array(
|
|
'usage' => null,
|
|
'optionList' => null,
|
|
'optionClass' => 'Horde_Argv_Option',
|
|
'version' => null,
|
|
'conflictHandler' => "error",
|
|
'description' => null,
|
|
'formatter' => null,
|
|
'addHelpOption' => true,
|
|
'prog' => null,
|
|
'epilog' => null,
|
|
'allowInterspersedArgs' => true,
|
|
'allowUnknownArgs' => false,
|
|
'ignoreUnknownArgs' => false,
|
|
), $args);
|
|
|
|
parent::__construct($args['optionClass'], $args['conflictHandler'], $args['description']);
|
|
$this->setUsage($args['usage']);
|
|
$this->prog = $args['prog'];
|
|
$this->version = $args['version'];
|
|
$this->allowInterspersedArgs = $args['allowInterspersedArgs'];
|
|
$this->allowUnknownArgs = $args['allowUnknownArgs'];
|
|
$this->ignoreUnknownArgs = $args['ignoreUnknownArgs'];
|
|
if (is_null($args['formatter'])) {
|
|
$args['formatter'] = new Horde_Argv_IndentedHelpFormatter();
|
|
}
|
|
$this->formatter = $args['formatter'];
|
|
$this->formatter->setParser($this);
|
|
$this->epilog = $args['epilog'];
|
|
|
|
// Populate the option list; initial sources are the
|
|
// standardOptionList class attribute, the 'optionList'
|
|
// argument, and (if applicable) the _addVersionOption() and
|
|
// _addHelpOption() methods.
|
|
$this->_populateOptionList($args['optionList'],
|
|
$args['addHelpOption']);
|
|
|
|
$this->_initParsingState();
|
|
}
|
|
|
|
// -- Private methods -----------------------------------------------
|
|
// (used by our OptionContainer's constructor)
|
|
|
|
protected function _createOptionList()
|
|
{
|
|
$this->optionList = array();
|
|
$this->optionGroups = array();
|
|
$this->_createOptionMappings();
|
|
}
|
|
|
|
protected function _addHelpOption()
|
|
{
|
|
$this->addOption('-h', '--help', array('action' => 'help',
|
|
'help' => Horde_Argv_Translation::t("show this help message and exit")));
|
|
}
|
|
|
|
protected function _addVersionOption()
|
|
{
|
|
$this->addOption('--version', array('action' => 'version',
|
|
'help' => Horde_Argv_Translation::t("show program's version number and exit")));
|
|
}
|
|
|
|
protected function _populateOptionList($optionList, $add_help = true)
|
|
{
|
|
if ($this->standardOptionList)
|
|
$this->addOptions($this->standardOptionList);
|
|
if ($optionList)
|
|
$this->addOptions($optionList);
|
|
if ($this->version)
|
|
$this->_addVersionOption();
|
|
if ($add_help)
|
|
$this->_addHelpOption();
|
|
}
|
|
|
|
protected function _initParsingState()
|
|
{
|
|
// These are set in parseArgs() for the convenience of callbacks.
|
|
$this->rargs = null;
|
|
$this->largs = null;
|
|
$this->values = null;
|
|
}
|
|
|
|
// -- Simple modifier methods ---------------------------------------
|
|
|
|
public function setUsage($usage)
|
|
{
|
|
if (is_null($usage))
|
|
$this->_usage = '%prog ' . Horde_Argv_Translation::t("[options]");
|
|
elseif ($usage == Horde_Argv_Option::SUPPRESS_USAGE)
|
|
$this->_usage = null;
|
|
else
|
|
$this->_usage = $usage;
|
|
}
|
|
|
|
public function enableInterspersedArgs()
|
|
{
|
|
$this->allowInterspersedArgs = true;
|
|
}
|
|
|
|
public function disableInterspersedArgs()
|
|
{
|
|
$this->allowInterspersedArgs = false;
|
|
}
|
|
|
|
public function setDefault($dest, $value)
|
|
{
|
|
$this->defaults[$dest] = $value;
|
|
}
|
|
|
|
public function setDefaults($defaults)
|
|
{
|
|
$this->defaults = array_merge($this->defaults, $defaults);
|
|
}
|
|
|
|
protected function _getAllOptions()
|
|
{
|
|
$options = $this->optionList;
|
|
foreach ($this->optionGroups as $group) {
|
|
$options = array_merge($options, $group->optionList);
|
|
}
|
|
return $options;
|
|
}
|
|
|
|
public function getDefaultValues()
|
|
{
|
|
$defaults = $this->defaults;
|
|
foreach ($this->_getAllOptions() as $option) {
|
|
$default = isset($defaults[$option->dest]) ? $defaults[$option->dest] : null;
|
|
if (is_string($default)) {
|
|
$opt_str = $option->getOptString();
|
|
$defaults[$option->dest] = $option->checkValue($opt_str, $default);
|
|
}
|
|
}
|
|
|
|
return new Horde_Argv_Values($defaults);
|
|
}
|
|
|
|
|
|
// -- OptionGroup methods -------------------------------------------
|
|
|
|
public function addOptionGroup()
|
|
{
|
|
// XXX lots of overlap with OptionContainer::addOption()
|
|
$args = func_get_args();
|
|
|
|
if (count($args) && is_string($args[0])) {
|
|
$groupFactory = new ReflectionClass('Horde_Argv_OptionGroup');
|
|
array_unshift($args, $this);
|
|
$group = $groupFactory->newInstanceArgs($args);
|
|
} elseif (count($args) == 1) {
|
|
$group = $args[0];
|
|
if (!$group instanceof Horde_Argv_OptionGroup)
|
|
throw new InvalidArgumentException("not an OptionGroup instance: " . var_export($group, true));
|
|
if ($group->parser !== $this)
|
|
throw new InvalidArgumentException("invalid OptionGroup (wrong parser)");
|
|
} else {
|
|
throw new InvalidArgumentException('invalid arguments');
|
|
}
|
|
|
|
$this->optionGroups[] = $group;
|
|
$this->defaults = array_merge($this->defaults, $group->defaults);
|
|
return $group;
|
|
}
|
|
|
|
public function getOptionGroup($opt_str)
|
|
{
|
|
if (isset($this->shortOpt[$opt_str])) {
|
|
$option = $this->shortOpt[$opt_str];
|
|
} elseif (isset($this->longOpt[$opt_str])) {
|
|
$option = $this->longOpt[$opt_str];
|
|
} else {
|
|
return null;
|
|
}
|
|
|
|
if ($option->container !== $this) {
|
|
return $option->container;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// -- Option-parsing methods ----------------------------------------
|
|
|
|
protected function _getArgs($args = null)
|
|
{
|
|
if (is_null($args)) {
|
|
$args = $_SERVER['argv'];
|
|
array_shift($args);
|
|
return $args;
|
|
} else {
|
|
return $args;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse the command-line options found in 'args' (default:
|
|
* sys.argv[1:]). Any errors result in a call to 'parserError()', which
|
|
* by default prints the usage message to stderr and calls
|
|
* exit() with an error message. On success returns a pair
|
|
* (values, args) where 'values' is an Values instance (with all
|
|
* your option values) and 'args' is the list of arguments left
|
|
* over after parsing options.
|
|
*/
|
|
public function parseArgs($args = null, $values = null)
|
|
{
|
|
$rargs = $this->_getArgs($args);
|
|
$largs = array();
|
|
if (is_null($values))
|
|
$values = $this->getDefaultValues();
|
|
|
|
// Store the halves of the argument list as attributes for the
|
|
// convenience of callbacks:
|
|
// rargs
|
|
// the rest of the command-line (the "r" stands for
|
|
// "remaining" or "right-hand")
|
|
// largs
|
|
// the leftover arguments -- ie. what's left after removing
|
|
// options and their arguments (the "l" stands for "leftover"
|
|
// or "left-hand")
|
|
$this->rargs =& $rargs;
|
|
$this->largs =& $largs;
|
|
$this->values = $values;
|
|
|
|
try {
|
|
$this->_processArgs($largs, $rargs, $values);
|
|
} catch (Horde_Argv_BadOptionException $e) {
|
|
$this->parserError($e->getMessage());
|
|
} catch (Horde_Argv_OptionValueException $e) {
|
|
$this->parserError($e->getMessage());
|
|
}
|
|
|
|
$args = array_merge($largs, $rargs);
|
|
return $this->checkValues($values, $args);
|
|
}
|
|
|
|
/**
|
|
* Check that the supplied option values and leftover arguments are
|
|
* valid. Returns the option values and leftover arguments
|
|
* (possibly adjusted, possibly completely new -- whatever you
|
|
* like). Default implementation just returns the passed-in
|
|
* values; subclasses may override as desired.
|
|
*/
|
|
public function checkValues($values, $args)
|
|
{
|
|
return array($values, $args);
|
|
}
|
|
|
|
/**
|
|
* _process_args(largs : [string],
|
|
* rargs : [string],
|
|
* values : Values)
|
|
*
|
|
* Process command-line arguments and populate 'values', consuming
|
|
* options and arguments from 'rargs'. If 'allowInterspersedArgs' is
|
|
* false, stop at the first non-option argument. If true, accumulate any
|
|
* interspersed non-option arguments in 'largs'.
|
|
*/
|
|
protected function _processArgs(&$largs, &$rargs, &$values)
|
|
{
|
|
while ($rargs) {
|
|
$arg = $rargs[0];
|
|
// We handle bare "--" explicitly, and bare "-" is handled by the
|
|
// standard arg handler since the short arg case ensures that the
|
|
// len of the opt string is greater than 1.
|
|
if ($arg == '--') {
|
|
array_shift($rargs);
|
|
return;
|
|
} elseif (substr($arg, 0, 2) == '--') {
|
|
// process a single long option (possibly with value(s))
|
|
$this->_processLongOpt($rargs, $values);
|
|
} elseif (substr($arg, 0, 1) == '-' && strlen($arg) > 1) {
|
|
// process a cluster of short options (possibly with
|
|
// value(s) for the last one only)
|
|
$this->_processShortOpts($rargs, $values);
|
|
} elseif ($this->allowInterspersedArgs) {
|
|
$largs[] = $arg;
|
|
array_shift($rargs);
|
|
} else {
|
|
// stop now, leave this arg in rargs
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Say this is the original argument list:
|
|
// [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]
|
|
// ^
|
|
// (we are about to process arg(i)).
|
|
//
|
|
// Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of
|
|
// [arg0, ..., arg(i-1)] (any options and their arguments will have
|
|
// been removed from largs).
|
|
//
|
|
// The while loop will usually consume 1 or more arguments per pass.
|
|
// If it consumes 1 (eg. arg is an option that takes no arguments),
|
|
// then after _process_arg() is done the situation is:
|
|
//
|
|
// largs = subset of [arg0, ..., arg(i)]
|
|
// rargs = [arg(i+1), ..., arg(N-1)]
|
|
//
|
|
// If allowInterspersedArgs is false, largs will always be
|
|
// *empty* -- still a subset of [arg0, ..., arg(i-1)], but
|
|
// not a very interesting subset!
|
|
}
|
|
|
|
/**
|
|
* opt : string) -> string
|
|
*
|
|
* Determine which long option string 'opt' matches, ie. which one
|
|
* it is an unambiguous abbrevation for. Raises BadOptionError if
|
|
* 'opt' doesn't unambiguously match any long option string.
|
|
*/
|
|
protected function _matchLongOpt($opt)
|
|
{
|
|
return self::matchAbbrev($opt, $this->longOpt);
|
|
}
|
|
|
|
/**
|
|
* (s : string, wordmap : {string : Option}) -> string
|
|
*
|
|
* Return the string key in 'wordmap' for which 's' is an unambiguous
|
|
* abbreviation. If 's' is found to be ambiguous or doesn't match any of
|
|
* 'words', raise BadOptionError.
|
|
*/
|
|
public static function matchAbbrev($s, $wordmap)
|
|
{
|
|
// Is there an exact match?
|
|
if (array_key_exists($s, $wordmap)) {
|
|
return $s;
|
|
}
|
|
|
|
// Isolate all words with s as a prefix.
|
|
$possibilities = array();
|
|
foreach (array_keys($wordmap) as $word) {
|
|
if (strncmp($word, $s, strlen($s)) === 0) {
|
|
$possibilities[] = $word;
|
|
}
|
|
}
|
|
|
|
// No exact match, so there had better be just one possibility.
|
|
if (count($possibilities) == 1) {
|
|
return $possibilities[0];
|
|
} elseif (!$possibilities) {
|
|
throw new Horde_Argv_BadOptionException($s);
|
|
} else {
|
|
// More than one possible completion: ambiguous prefix.
|
|
sort($possibilities);
|
|
throw new Horde_Argv_AmbiguousOptionException($s, $possibilities);
|
|
}
|
|
}
|
|
|
|
protected function _processLongOpt(&$rargs, &$values)
|
|
{
|
|
$arg = array_shift($rargs);
|
|
|
|
// Value explicitly attached to arg? Pretend it's the next
|
|
// argument.
|
|
if (strpos($arg, '=') !== false) {
|
|
list($opt, $next_arg) = explode('=', $arg, 2);
|
|
array_unshift($rargs, $next_arg);
|
|
$had_explicit_value = true;
|
|
} else {
|
|
$opt = $arg;
|
|
$had_explicit_value = false;
|
|
}
|
|
|
|
try {
|
|
$opt = $this->_matchLongOpt($opt);
|
|
$option = $this->longOpt[$opt];
|
|
} catch (Horde_Argv_BadOptionException $e) {
|
|
if ($this->ignoreUnknownArgs) {
|
|
return;
|
|
}
|
|
if ($this->allowUnknownArgs) {
|
|
$option = $this->addOption($opt, array('default' => true, 'action' => 'append'));
|
|
} else {
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
if ($option->takesValue()) {
|
|
$nargs = $option->nargs;
|
|
if (count($rargs) < $nargs) {
|
|
if (!$option->hasDefault()) {
|
|
if ($nargs == 1) {
|
|
$this->parserError(sprintf(Horde_Argv_Translation::t("%s option requires an argument"), $opt));
|
|
} else {
|
|
$this->parserError(sprintf(Horde_Argv_Translation::t("%s option requires %d arguments"), $opt, $nargs));
|
|
}
|
|
}
|
|
} elseif ($nargs == 1) {
|
|
$value = array_shift($rargs);
|
|
} else {
|
|
$value = array_splice($rargs, 0, $nargs);
|
|
}
|
|
|
|
} elseif ($had_explicit_value) {
|
|
$this->parserError(sprintf(Horde_Argv_Translation::t("%s option does not take a value"), $opt));
|
|
|
|
} else {
|
|
$value = null;
|
|
}
|
|
|
|
$option->process($opt, $value, $values, $this);
|
|
}
|
|
|
|
protected function _processShortOpts(&$rargs, &$values)
|
|
{
|
|
$arg = array_shift($rargs);
|
|
$stop = false;
|
|
$i = 1;
|
|
for ($c = 1, $c_max = strlen($arg); $c < $c_max; $c++) {
|
|
$ch = $arg[$c];
|
|
$opt = '-' . $ch;
|
|
$option = isset($this->shortOpt[$opt]) ? $this->shortOpt[$opt] : null;
|
|
$i++; // we have consumed a character
|
|
|
|
if (!$option) {
|
|
if ($this->allowUnknownArgs) {
|
|
$option = $this->addOption($opt, array('default' => true, 'action' => 'append'));
|
|
} else {
|
|
throw new Horde_Argv_BadOptionException($opt);
|
|
}
|
|
}
|
|
|
|
if ($option->takesValue()) {
|
|
// Any characters left in arg? Pretend they're the
|
|
// next arg, and stop consuming characters of arg.
|
|
if ($i < strlen($arg)) {
|
|
array_unshift($rargs, substr($arg, $i));
|
|
$stop = true;
|
|
}
|
|
|
|
$nargs = $option->nargs;
|
|
if (count($rargs) < $nargs) {
|
|
if (!$option->hasDefault()) {
|
|
if ($nargs == 1) {
|
|
$this->parserError(sprintf(Horde_Argv_Translation::t("%s option requires an argument"), $opt));
|
|
} else {
|
|
$this->parserError(sprintf(Horde_Argv_Translation::t("%s option requires %d arguments"), $opt, $nargs));
|
|
}
|
|
}
|
|
} elseif ($nargs == 1) {
|
|
$value = array_shift($rargs);
|
|
} else {
|
|
$value = array_splice($rargs, 0, $nargs);
|
|
}
|
|
|
|
} else {
|
|
// option doesn't take a value
|
|
$value = null;
|
|
}
|
|
|
|
$option->process($opt, $value, $values, $this);
|
|
|
|
if ($stop) { break; }
|
|
}
|
|
}
|
|
|
|
// -- Feedback methods ----------------------------------------------
|
|
|
|
public function getProgName()
|
|
{
|
|
if (is_null($this->prog))
|
|
return basename($_SERVER['argv'][0]);
|
|
else
|
|
return $this->prog;
|
|
}
|
|
|
|
public function expandProgName($s)
|
|
{
|
|
return str_replace("%prog", $this->getProgName(), $s);
|
|
}
|
|
|
|
public function getDescription()
|
|
{
|
|
return $this->expandProgName($this->description);
|
|
}
|
|
|
|
public function parserExit($status = 0, $msg = null)
|
|
{
|
|
if ($msg)
|
|
fwrite(STDERR, $msg);
|
|
exit($status);
|
|
}
|
|
|
|
/**
|
|
* Print a usage message incorporating $msg to stderr and exit.
|
|
* If you override this in a subclass, it should not return -- it
|
|
* should either exit or raise an exception.
|
|
*
|
|
* @param string $msg
|
|
*/
|
|
public function parserError($msg)
|
|
{
|
|
$this->printUsage(STDERR);
|
|
$this->parserExit(2, sprintf("%s: error: %s\n", $this->getProgName(), $msg));
|
|
}
|
|
|
|
public function getUsage($formatter = null)
|
|
{
|
|
if (is_null($formatter))
|
|
$formatter = $this->formatter;
|
|
if ($this->_usage)
|
|
return $formatter->formatUsage($this->expandProgName($this->_usage));
|
|
else
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* (file : file = stdout)
|
|
*
|
|
* Print the usage message for the current program ($this->_usage) to
|
|
* 'file' (default stdout). Any occurence of the string "%prog" in
|
|
* $this->_usage is replaced with the name of the current program
|
|
* (basename of sys.argv[0]). Does nothing if $this->_usage is empty
|
|
* or not defined.
|
|
*/
|
|
public function printUsage($file = null)
|
|
{
|
|
if (!$this->_usage)
|
|
return;
|
|
|
|
if (is_null($file))
|
|
echo $this->getUsage();
|
|
else
|
|
fwrite($file, $this->getUsage());
|
|
}
|
|
|
|
public function getVersion()
|
|
{
|
|
if ($this->version)
|
|
return $this->expandProgName($this->version);
|
|
else
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* file : file = stdout
|
|
*
|
|
* Print the version message for this program ($this->version) to
|
|
* 'file' (default stdout). As with printUsage(), any occurence
|
|
* of "%prog" in $this->version is replaced by the current program's
|
|
* name. Does nothing if $this->version is empty or undefined.
|
|
*/
|
|
public function printVersion($file = null)
|
|
{
|
|
if (!$this->version)
|
|
return;
|
|
|
|
if (is_null($file))
|
|
echo $this->getVersion() . "\n";
|
|
else
|
|
fwrite($file, $this->getVersion() . "\n");
|
|
}
|
|
|
|
public function formatOptionHelp($formatter = null)
|
|
{
|
|
if (is_null($formatter))
|
|
$formatter = $this->formatter;
|
|
$formatter->storeOptionStrings($this);
|
|
$result = array();
|
|
$result[] = $formatter->formatHeading(Horde_Argv_Translation::t("Options"));
|
|
$formatter->indent();
|
|
if ($this->optionList) {
|
|
$result[] = parent::formatOptionHelp($formatter);
|
|
$result[] = "\n";
|
|
}
|
|
foreach ($this->optionGroups as $group) {
|
|
$result[] = $group->formatHelp($formatter);
|
|
$result[] = "\n";
|
|
}
|
|
$formatter->dedent();
|
|
// Drop the last "\n", or the header if no options or option groups:
|
|
array_pop($result);
|
|
return implode('', $result);
|
|
}
|
|
|
|
public function formatEpilog($formatter)
|
|
{
|
|
return $formatter->formatEpilog($this->epilog);
|
|
}
|
|
|
|
public function formatHelp($formatter = null)
|
|
{
|
|
if (is_null($formatter))
|
|
$formatter = $this->formatter;
|
|
$result = array();
|
|
if ($this->_usage)
|
|
$result[] = $this->getUsage($formatter) . "\n";
|
|
if ($this->description)
|
|
$result[] = $this->formatDescription($formatter) . "\n";
|
|
$result[] = $this->formatOptionHelp($formatter);
|
|
$result[] = $this->formatEpilog($formatter);
|
|
return implode('', $result);
|
|
}
|
|
|
|
/**
|
|
* file : file = stdout
|
|
*
|
|
* Print an extended help message, listing all options and any
|
|
* help text provided with them, to 'file' (default stdout).
|
|
*/
|
|
public function printHelp($file = null)
|
|
{
|
|
if (is_null($file))
|
|
echo $this->formatHelp();
|
|
else
|
|
fwrite($file, $this->formatHelp());
|
|
}
|
|
|
|
}
|