* Original option spec
* @var array
*/
- private $orig;
+ private $orig = [];
/**
* Compiled spec
* @return pharext\CliArgs self
*/
public function compile(array $spec = null) {
- $this->orig = $spec;
- $this->spec = [];
+ $this->orig = array_merge($this->orig, $spec);
foreach ((array) $spec as $arg) {
- $this->spec["-".$arg[0]] = $arg;
+ if (isset($arg[0])) {
+ $this->spec["-".$arg[0]] = $arg;
+ }
$this->spec["--".$arg[1]] = $arg;
}
return $this;
}
+ /**
+ * Get original spec
+ * @return array
+ */
+ public function getSpec() {
+ return $this->orig;
+ }
+
+ /**
+ * Get compiled spec
+ * @return array
+ */
+ public function getCompiledSpec() {
+ return $this->spec;
+ }
+
/**
* Parse command line arguments according to the compiled spec.
*
for ($i = 0; $i < $argc; ++$i) {
$o = $argv[$i];
- if ($o{0} === '-' && strlen($o) > 1 && $o{1} !== '-') {
+ if ($o{0} === '-' && strlen($o) > 2 && $o{1} !== '-') {
// multiple short opts, .e.g -vps
$argc += strlen($o) - 2;
array_splice($argv, $i, 1, array_map(function($s) {
return "-$s";
}, str_split(substr($o, 1))));
$o = $argv[$i];
+ } elseif ($o{0} === '-' && strlen($o) > 2 && $o{1} === '-' && 0 < ($eq = strpos($o, "="))) {
+ $argc++;
+ array_splice($argv, $i, 1, [
+ substr($o, 0, $eq++),
+ substr($o, $eq)
+ ]);
+ $o = $argv[$i];
}
if (!isset($this->spec[$o])) {
- yield sprintf("Unknown option %s", $argv[$i]);
+ yield sprintf("Unknown option %s", $o);
} elseif (!$this->optAcceptsArg($o)) {
$this[$o] = true;
} elseif ($i+1 < $argc && !isset($this->spec[$argv[$i+1]])) {
$this[$o] = $argv[++$i];
- } elseif ($this->optNeedsArg($o)) {
- yield sprintf("Option --%s needs an argument", $this->optLongName($o));
+ } elseif ($this->optRequiresArg($o)) {
+ yield sprintf("Option --%s requires an argument", $this->optLongName($o));
} else {
// OPTARG
$this[$o] = $this->optDefaultArg($o);
}
}
- /**
- * Output command line help message
- * @param string $prog
- */
- public function help($prog) {
- printf("\nUsage:\n\n $ %s", $prog);
- $flags = [];
- $required = [];
- $optional = [];
- foreach ($this->orig as $spec) {
- if ($spec[3] & self::REQARG) {
- if ($spec[3] & self::REQUIRED) {
- $required[] = $spec;
- } else {
- $optional[] = $spec;
- }
- } else {
- $flags[] = $spec;
- }
- }
-
- if ($flags) {
- printf(" [-%s]", implode("|-", array_column($flags, 0)));
- }
- foreach ($required as $req) {
- printf(" -%s <arg>", $req[0]);
- }
- if ($optional) {
- printf(" [-%s <arg>]", implode("|-", array_column($optional, 0)));
- }
- printf("\n\n");
- foreach ($this->orig as $spec) {
- printf(" -%s|--%s %s", $spec[0], $spec[1], ($spec[3] & self::REQARG) ? "<arg> " : (($spec[3] & self::OPTARG) ? "[<arg>]" : " "));
- printf("%s%s %s", str_repeat(" ", 16-strlen($spec[1])), $spec[2], ($spec[3] & self::REQUIRED) ? "(REQUIRED)" : "");
- if (isset($spec[4])) {
- printf(" [%s]", $spec[4]);
- }
- printf("\n");
- }
- printf("\n");
- }
-
/**
* Retreive the default argument of an option
* @param string $o
return "";
}
+ /**
+ * Retrieve option's flags
+ * @param string $o
+ * @return int
+ */
+ private function optFlags($o) {
+ $o = $this->opt($o);
+ if (isset($this->spec[$o])) {
+ return $this->spec[$o][3];
+ }
+ return null;
+ }
+
/**
* Check whether an option is flagged for halting argument processing
* @param string $o
* @return boolean
*/
private function optHalts($o) {
- $o = $this->opt($o);
- return $this->spec[$o][3] & self::HALT;
+ return $this->optFlags($o) & self::HALT;
}
/**
* @param string $o
* @return boolean
*/
- private function optNeedsArg($o) {
- $o = $this->opt($o);
- return $this->spec[$o][3] & self::REQARG;
+ private function optRequiresArg($o) {
+ return $this->optFlags($o) & self::REQARG;
}
/**
* @return boolean
*/
private function optAcceptsArg($o) {
- $o = $this->opt($o);
- return $this->spec[$o][3] & 0xf00;
+ return $this->optFlags($o) & 0xf00;
}
/**
* @return boolean
*/
private function optIsMulti($o) {
- $o = $this->opt($o);
- return $this->spec[$o][3] & self::MULTI;
+ return $this->optFlags($o) & self::MULTI;
}
/**
return $this->offsetGet($o);
}
function offsetSet($o, $v) {
+ $osn = $this->optShortName($o);
+ $oln = $this->optLongName($o);
if ($this->optIsMulti($o)) {
- $this->args["-".$this->optShortName($o)][] = $v;
- $this->args["--".$this->optLongName($o)][] = $v;
+ if (isset($osn)) {
+ $this->args["-$osn"][] = $v;
+ }
+ $this->args["--$oln"][] = $v;
} else {
- $this->args["-".$this->optShortName($o)] = $v;
- $this->args["--".$this->optLongName($o)] = $v;
+ if (isset($osn)) {
+ $this->args["-$osn"] = $v;
+ }
+ $this->args["--$oln"] = $v;
}
}
function __set($o, $v) {