modifs.mineures sans commentaires
This commit is contained in:
parent
b0f5de5e9f
commit
ce86cfe354
194
src/app/cli/Arg.php
Normal file
194
src/app/cli/Arg.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
use nulib\A;
|
||||
use nulib\cl;
|
||||
use nulib\php\types\varray;
|
||||
|
||||
class Arg {
|
||||
const TYPE_SHORT = 0, TYPE_LONG = 1, TYPE_COMMAND = 2;
|
||||
const ARGS_NONE = 0, ARGS_MANDATORY = 1, ARGS_OPTIONAL = 2;
|
||||
|
||||
function __construct(array $def) {
|
||||
[$options, $params] = cl::split_assoc($def);
|
||||
|
||||
$args = $params["args"] ?? null;
|
||||
$args ??= $params["arg"] ?? null;
|
||||
if ($args === true) $args = 1;
|
||||
if (is_int($args)) $args = array_fill(0, $args, "value");
|
||||
$this->_args = cl::withn($args);
|
||||
|
||||
$this->argsdesc = $params["argsdesc"] ?? null;
|
||||
|
||||
$extends = $params["extends"] ?? null;
|
||||
if ($extends !== null) {
|
||||
A::merge($extends["add"], $options);
|
||||
$this->extends = $extends;
|
||||
$this->processExtends();
|
||||
#XXX à terme, processExtends() est appelé par ArgsParser après le
|
||||
# chargement de tous les arguments, parce que [arg] peut-être une
|
||||
# référence e.g ["extends" => ["arg" => "-o", "add" => ["--longo"]]]
|
||||
} else {
|
||||
$this->addOptions($options);
|
||||
}
|
||||
}
|
||||
|
||||
protected ?array $options = [];
|
||||
|
||||
function getOptions(): array {
|
||||
return array_keys($this->options);
|
||||
}
|
||||
|
||||
public bool $haveShortOptions = false;
|
||||
public bool $haveLongOptions = false;
|
||||
public bool $haveCommands = false;
|
||||
|
||||
public bool $haveArgs = false;
|
||||
public ?int $minArgs = null;
|
||||
public ?int $maxArgs = null;
|
||||
public ?string $argsdesc = null;
|
||||
|
||||
function addOptions(?array $options): void {
|
||||
if ($options === null) return;
|
||||
foreach ($options as $option) {
|
||||
if (substr($option, 0, 2) === "--") {
|
||||
$type = self::TYPE_LONG;
|
||||
if (preg_match('/^--([^:-]+)(::?)?$/', $option, $ms)) {
|
||||
$name = $ms[1];
|
||||
$args = $ms[2] ?? null;
|
||||
$option = "--$name";
|
||||
} else {
|
||||
throw new ArgException("$option: invalid long option");
|
||||
}
|
||||
} elseif (substr($option, 0, 1) === "-") {
|
||||
$type = self::TYPE_SHORT;
|
||||
if (preg_match('/^-([^:-])(::?)?$/', $option, $ms)) {
|
||||
$name = $ms[1];
|
||||
$args = $ms[2] ?? null;
|
||||
$option = "-$name";
|
||||
} else {
|
||||
throw new ArgException("$option: invalid short option");
|
||||
}
|
||||
} else {
|
||||
$type = self::TYPE_COMMAND;
|
||||
if (preg_match('/^([^:-]+)$/', $option, $ms)) {
|
||||
$name = $ms[1];
|
||||
$args = null;
|
||||
$option = "$name";
|
||||
} else {
|
||||
throw new ArgException("$option: invalid command");
|
||||
}
|
||||
}
|
||||
if ($args === ":") {
|
||||
$argsType = self::ARGS_MANDATORY;
|
||||
} elseif ($args === "::") {
|
||||
$argsType = self::ARGS_OPTIONAL;
|
||||
} else {
|
||||
$argsType = self::ARGS_NONE;
|
||||
}
|
||||
$this->options[$option] = [
|
||||
"name" => $name,
|
||||
"option" => $option,
|
||||
"type" => $type,
|
||||
"args_type" => $argsType,
|
||||
];
|
||||
}
|
||||
$this->updateType();
|
||||
}
|
||||
|
||||
function removeOptions(?array $options): void {
|
||||
if ($options === null) return;
|
||||
foreach ($options as $option) {
|
||||
if (substr($option, 0, 2) === "--") {
|
||||
if (preg_match('/^--([^:-]+)(::?)?$/', $option, $ms)) {
|
||||
$name = $ms[1];
|
||||
$option = "--$name";
|
||||
} else {
|
||||
throw new ArgException("$option: invalid long option");
|
||||
}
|
||||
} elseif (substr($option, 0, 1) === "-") {
|
||||
if (preg_match('/^-([^:-])(::?)?$/', $option, $ms)) {
|
||||
$name = $ms[1];
|
||||
$option = "-$name";
|
||||
} else {
|
||||
throw new ArgException("$option: invalid short option");
|
||||
}
|
||||
} else {
|
||||
if (preg_match('/^([^:-]+)$/', $option, $ms)) {
|
||||
$name = $ms[1];
|
||||
$option = "$name";
|
||||
} else {
|
||||
throw new ArgException("$option: invalid command");
|
||||
}
|
||||
}
|
||||
unset($this->options[$option]);
|
||||
}
|
||||
$this->updateType();
|
||||
}
|
||||
|
||||
protected ?array $extends;
|
||||
|
||||
function processExtends(): void {
|
||||
$extends = $this->extends;
|
||||
$base = $extends["arg"] ?? null;
|
||||
if ($base === null) return;
|
||||
$base = new self($base);
|
||||
$this->options = $base->options;
|
||||
$this->removeOptions(varray::withn($extends["remove"] ?? null));
|
||||
$this->addOptions(varray::withn($extends["add"] ?? null));
|
||||
}
|
||||
|
||||
protected function updateType(): void {
|
||||
$haveShortOptions = false;
|
||||
$haveLongOptions = false;
|
||||
$haveCommands = false;
|
||||
foreach ($this->options as $option) {
|
||||
switch ($option["type"]) {
|
||||
case self::TYPE_SHORT:
|
||||
$haveShortOptions = true;
|
||||
break;
|
||||
case self::TYPE_LONG:
|
||||
$haveLongOptions = true;
|
||||
break;
|
||||
case self::TYPE_COMMAND:
|
||||
$haveCommands = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->haveShortOptions = $haveShortOptions;
|
||||
$this->haveLongOptions = $haveLongOptions;
|
||||
$this->haveCommands = $haveCommands;
|
||||
}
|
||||
|
||||
protected ?array $_args = null;
|
||||
|
||||
protected function updateArgs(): void {
|
||||
if ($this->_args === null) {
|
||||
$haveArgs = false;
|
||||
$optionalArgs = null;
|
||||
foreach ($this->options as $option) {
|
||||
switch ($option["args_type"]) {
|
||||
case self::ARGS_NONE:
|
||||
break;
|
||||
case self::ARGS_MANDATORY:
|
||||
$haveArgs = true;
|
||||
$optionalArgs = false;
|
||||
break;
|
||||
case self::ARGS_OPTIONAL:
|
||||
$haveArgs = true;
|
||||
$optionalArgs ??= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$optionalArgs ??= false;
|
||||
if ($haveArgs) {
|
||||
$args = ["value"];
|
||||
if ($optionalArgs) $args = [$args];
|
||||
}
|
||||
}
|
||||
#XXX calculer minArgs, maxArgs, argsdesc
|
||||
$this->haveArgs = $haveArgs;
|
||||
$this->_args = $args;
|
||||
$this->argsdesc = $argsdesc;
|
||||
}
|
||||
}
|
7
src/app/cli/ArgException.php
Normal file
7
src/app/cli/ArgException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
use nulib\ValueException;
|
||||
|
||||
class ArgException extends ValueException {
|
||||
}
|
48
tests/app/cli/ArgTest.php
Normal file
48
tests/app/cli/ArgTest.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
use nur\t\TestCase;
|
||||
|
||||
class ArgTest extends TestCase {
|
||||
function testBase() {
|
||||
$arg = new Arg(["-o", "--longo"]);
|
||||
self::assertSame(["-o", "--longo"], $arg->getOptions());
|
||||
self::assertFalse($arg->haveArgs);
|
||||
self::assertFalse($arg->optionalArgs);
|
||||
|
||||
$arg = new Arg(["-o:", "--longo"]);
|
||||
self::assertSame(["-o", "--longo"], $arg->getOptions());
|
||||
self::assertTrue($arg->haveArgs);
|
||||
self::assertFalse($arg->optionalArgs);
|
||||
|
||||
$arg = new Arg(["-o::", "--longo"]);
|
||||
self::assertSame(["-o", "--longo"], $arg->getOptions());
|
||||
self::assertTrue($arg->haveArgs);
|
||||
self::assertTrue($arg->optionalArgs);
|
||||
|
||||
$arg = new Arg(["-o:", "--longo:"]);
|
||||
self::assertSame(["-o", "--longo"], $arg->getOptions());
|
||||
self::assertTrue($arg->haveArgs);
|
||||
self::assertFalse($arg->optionalArgs);
|
||||
|
||||
$arg = new Arg(["-o:", "--longo::"]);
|
||||
self::assertSame(["-o", "--longo"], $arg->getOptions());
|
||||
self::assertTrue($arg->haveArgs);
|
||||
self::assertFalse($arg->optionalArgs);
|
||||
}
|
||||
|
||||
function testExtends() {
|
||||
$basedef = ["-o:", "--longo"];
|
||||
$def = [
|
||||
"extends" => [
|
||||
"arg" => $basedef,
|
||||
"add" => ["-a", "--longa"],
|
||||
"remove" => ["-o", "--longo"],
|
||||
],
|
||||
];
|
||||
$arg = new Arg($def);
|
||||
self::assertSame(["-a", "--longa"], $arg->getOptions());
|
||||
self::assertFalse($arg->haveArgs);
|
||||
self::assertFalse($arg->optionalArgs);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user