Skip to content

Instantly share code, notes, and snippets.

@moechofe
Last active February 15, 2019 16:27
Show Gist options
  • Save moechofe/4225616 to your computer and use it in GitHub Desktop.
Save moechofe/4225616 to your computer and use it in GitHub Desktop.
Quick and effective command line parser for PHP using getopt().
<?php
/**
* Parse the command line and fill variables.
* Params:
* array $opts = An associated array. Keys are the option names.
* Values are the references to variables that receive the values from the command lines.
* Nothing is returned but when values of the array $opts are passed by reference, they will contain the
* values extracted from the command line.
* Keys must be string.
* - "verbose" Allow long option.
* - "v" Allow short option.
* - "verbose|v" Allow long and short option.
* - Add the suffix "?" to indiquate that the value is optional.
* Values must be passed by reference, otherwise no value can be extracted from the command line.
* Values can be Closure. They will be call if the option is present in the command line.
* ----
* $verbose = null; // No value need for this argument.
* $output = ''; // Wait for a string value.
* $inputs = array(); // Can receive more than one value.
* qad\arg\parse(array(
* 'v' => &$verbose,
* 'output|o' => &$output,
* 'input|i' => &$input,
* 'whatever' => function($val){var_dump($val);} ));
* var_dump($verbose, $output, $input);
* ----
* array $args = When provided, will be filled by the arguments. Compared to an option, an argument as no name.
* Source: https://gist.github.com/4225616
*/
function parse(array $opts,array &$args=null)
{
global $argv,$argc;
if(is_array($args))
{
for($i=1;$i<count($argv);)
{
if(!preg_match('/^--?\w/',$argv[$i]))
{
array_push($args,array_splice($argv,$i,1));
$argc--;
}
else $i++;
}
}
$mapping = array();
// Build the "short" and "long" parameters for the getopt function.
list($short, $long) = array_values(array_reduce(array_keys($opts), function($r, $opt) use($opts, &$mapping)
{
assert('is_string($opt)');
if (preg_match('/(^[-\w]{2,})?(?:(?:^|\|)(\w))?(\?)?$/', $opt, $match))
{
$require_or_optional = !is_null($opts[$opt]) ? ':'.(!empty($match[3])?':':'') : '';
if (!empty($match[2]))
{
$r['short'] .= $match[2] . $require_or_optional;
$mapping[$match[2]] = $opt;
}
if (!empty($match[1]))
{
array_push($r['long'], $match[1] . $require_or_optional);
$mapping[$match[1]] = $opt;
}
}
return $r;
}, array('short'=>'', 'long'=>array()) ));
// Parse the arguments and fill the variables.
foreach( getopt($short, $long) as $opt => $val )
{
if (array_key_exists($opt, $mapping))
{
$dest = &$opts[$mapping[$opt]];
if (is_array($dest) and is_array($val)) $dest = array_merge($dest, $val);
elseif (is_array($dest)) array_push($dest, $val);
elseif (is_string($dest) ) $dest = is_array($val) ? current($val) : ($val===false?true:$val);
elseif (is_null($dest) or is_bool($dest)) $dest = true;
elseif ($dest instanceof Closure) $dest($val);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment