Class it:
/**
* Parse command line options with Usage given as template and return assoc array.
* @param $usage Usage parsed to determine options, example see below.
* @param $p['optbeforearg'] Stop parsing options when first argument is encountered
* @param $p['noexit'] Just return false in case of help or bad usage
* @return Associative array of options, key 'args' for optional non-option args
*
* Usage: myprogram.php [OPTIONS] PATTERN [MOREARGS]
* -s, --short Use short ouput
* -f, --file=FILE Use FILE for input [foo.txt]
* -x EXTENSION Ignore EXTENSION
* Mandatory arguments from the Usage: line are returned under their (lowercased!) name.
* Option text must be indented; if long and short option present, value is stored in long one.
* For long opts with arguments, = is mandatory in usage. Defaults in [ ] at end of line
* Two or more blanks must be in front of option explanation
* Options without arguments store true or false under their key
* Option --help or -h prints de-indented usage and exits (needs not be in usage)
* Option --debug foo-bar will store bar in EDC('foo'). (needs not be in usage)
* Option --verbose sets debug variable verbose for EDC('verbose', $bar). (must be in usage)
*/
static function getopt($usage, $p = array())
{
$GLOBALS['it_stdin'] = array(
'fd' => null,
'args' => array(),
'filename' => "",
'line' => 0,
);
$result = array('args' => array());
if ($indentation = it::match('^\s+', $usage))
$usage = it::replace(array($indentation => "\n"), $usage);
foreach(explode("\n", trim($usage)) as $usageline)
{
$shortoptname = $shortoptarg = $longoptname = $longoptarg = "";
foreach (explode(',', $usageline, 2) as $optdesc)
{
$optdesc = trim($optdesc);
if ($matches = (array)it::match('^--(\w[\w-]*)(=[A-Z])?', $optdesc))
list($longoptname, $longoptarg) = $matches;
else if ($matches = (array)it::match('^-(\w)( [A-Z])?', $optdesc))
list($shortoptname, $shortoptarg) = $matches;
}
if (($default = it::match('\[(.*)\]\s*$', $usageline)) !== null)
{
if ($longoptarg || $shortoptarg)
$defaults[$longoptname ? $longoptname : $shortoptname] = it::replace(array('^default:\s*' => ""), trim($default));
else if (($longoptname || $shortoptname) && it::match('^\w+$', $default))
it::error('defaults for boolean arguments not supported!');
}
if ($longoptname || $shortoptname)
{
if ($longoptname && ($shortoptname || $shortoptname === "0"))
{
if ($alias[$shortoptname])
it::error("getopt: short option -$shortoptname is used twice: --{$alias[$shortoptname]} and --$longoptname!");
$alias[$shortoptname] = $longoptname;
}
$witharg[$longoptname ? $longoptname : $shortoptname] = $longoptarg || $shortoptarg;
}
}
$witharg['debug'] = true;
$argsdesc = trim(it::replace(array("\n.*" => "", "^\S+\s+\S+\s*" => ""), trim($usage)));
$mandatoryargs = it::match('\S+', it::replace(['\[.*?\]' => ''], $argsdesc), ['all' => true]);
$optionalargs = it::match('\[((?!OPTIONS\]).*?)\]', $argsdesc, ['all' => true]);
if ($mandatoryargs && !it::match("Usage:", $usage))
it::error("Usage string must contain 'Usage:'");
foreach (array_slice($_SERVER['argv'], 1) as $arg)
{
if ($eat)
$result[array_shift($eat)] = $arg;
else if (!$noopts && $arg == "--")
$noopts = true;
else if (!$noopts && ($matches = (array)it::match('^--(\w[\w-]*)(=.*)?', $arg)))
{
list($optname, $val) = $matches;
if (!isset($witharg[$optname]) || isset($val) && !$witharg[$optname])
$err = true;
else if($witharg[$optname] && !$val)
$eat[] = $optname;
else
$result[$optname] = $val ? substr($val, 1) : true;
}
else if (!$noopts && (($letters = it::match('^-(\w+)', $arg)) || $letters === "0"))
{
foreach (explode("\n", trim(chunk_split($letters, 1, "\n"))) as $letter)
{
$optname = $alias[$letter] ? $alias[$letter] : $letter;
if ($witharg[$optname] && it::match('=', $arg))
$result[$optname] = it::match('=(.*)', $arg);
else if ($witharg[$optname])
$eat[] = $optname;
else if (!isset($witharg[$optname]))
$err = true;
else
$result[$optname] = true;
}
}
else if($mandatoryargs)
$result[strtolower(array_shift($mandatoryargs))] = $seenarg = $arg;
else
$result['args'][] = $seenarg = $arg;
if ($p['optbeforearg'] && $seenarg)
$noopts = true;
}
if ($err || $eat || $result['h'] || $result['help'] || $mandatoryargs || (!$optionalargs && $result['args']))
{
if (is_resource($out = $result['h'] || $result['help'] ? STDOUT : STDERR))
fputs($out, trim($usage) . "\n");
return $p['noexit'] ? false : exit(1);
}
if ($result['debug'])
it_debug::set($result['debug']);
$GLOBALS['it_stdin']['args'] = $result['args'] ? $result['args'] : array("-");
if ($result['verbose'])
$GLOBALS['debug_verbose']++;
return $result + (array)$defaults;
}