in src/parser/argument/PhutilArgumentParser.php [124:283]
private function parseInternal(
array $specs,
$correct_spelling,
$initial_only) {
$specs = PhutilArgumentSpecification::newSpecsFromList($specs);
$this->mergeSpecs($specs);
$specs_by_name = mpull($specs, null, 'getName');
$specs_by_short = mpull($specs, null, 'getShortAlias');
unset($specs_by_short[null]);
$argv = $this->argv;
$len = count($argv);
$is_initial = true;
for ($ii = 0; $ii < $len; $ii++) {
$arg = $argv[$ii];
$map = null;
$options = null;
if (!is_string($arg)) {
// Non-string argument; pass it through as-is.
} else if ($arg == '--') {
// This indicates "end of flags".
break;
} else if ($arg == '-') {
// This is a normal argument (e.g., stdin).
continue;
} else if (!strncmp('--', $arg, 2)) {
$pre = '--';
$arg = substr($arg, 2);
$map = $specs_by_name;
$options = array_keys($specs_by_name);
} else if (!strncmp('-', $arg, 1) && strlen($arg) > 1) {
$pre = '-';
$arg = substr($arg, 1);
$map = $specs_by_short;
} else {
$is_initial = false;
}
if ($map) {
$val = null;
$parts = explode('=', $arg, 2);
if (count($parts) == 2) {
list($arg, $val) = $parts;
}
// Try to correct flag spelling for full flags, to allow users to make
// minor mistakes.
if ($correct_spelling && $options && !isset($map[$arg])) {
$corrections = PhutilArgumentSpellingCorrector::newFlagCorrector()
->correctSpelling($arg, $options);
if (count($corrections) == 1) {
$corrected = head($corrections);
$this->logMessage(
tsprintf(
"%s\n",
pht(
'(Assuming "%s" is the British spelling of "%s".)',
$pre.$arg,
$pre.$corrected)));
$arg = $corrected;
}
}
if (isset($map[$arg])) {
if ($initial_only && !$is_initial) {
throw new PhutilArgumentUsageException(
pht(
'Argument "%s" appears after the first non-flag argument. '.
'This special argument must appear before other arguments.',
"{$pre}{$arg}"));
}
$spec = $map[$arg];
unset($argv[$ii]);
$param_name = $spec->getParamName();
if ($val !== null) {
if ($param_name === null) {
throw new PhutilArgumentUsageException(
pht(
"Argument '%s' does not take a parameter.",
"{$pre}{$arg}"));
}
} else {
if ($param_name !== null) {
if ($ii + 1 < $len) {
$val = $argv[$ii + 1];
unset($argv[$ii + 1]);
$ii++;
} else {
throw new PhutilArgumentUsageException(
pht(
"Argument '%s' requires a parameter.",
"{$pre}{$arg}"));
}
} else {
$val = true;
}
}
if (!$spec->getRepeatable()) {
if (array_key_exists($spec->getName(), $this->results)) {
throw new PhutilArgumentUsageException(
pht(
"Argument '%s' was provided twice.",
"{$pre}{$arg}"));
}
}
$conflicts = $spec->getConflicts();
foreach ($conflicts as $conflict => $reason) {
if (array_key_exists($conflict, $this->results)) {
if (!is_string($reason) || !strlen($reason)) {
$reason = '.';
} else {
$reason = ': '.$reason.'.';
}
throw new PhutilArgumentUsageException(
pht(
"Argument '%s' conflicts with argument '%s'%s",
"{$pre}{$arg}",
"--{$conflict}",
$reason));
}
}
if ($spec->getRepeatable()) {
if ($spec->getParamName() === null) {
if (empty($this->results[$spec->getName()])) {
$this->results[$spec->getName()] = 0;
}
$this->results[$spec->getName()]++;
} else {
$this->results[$spec->getName()][] = $val;
}
} else {
$this->results[$spec->getName()] = $val;
}
}
}
}
foreach ($specs as $spec) {
if ($spec->getWildcard()) {
$this->results[$spec->getName()] = $this->filterWildcardArgv($argv);
$argv = array();
break;
}
}
$this->argv = array_values($argv);
return $this;
}