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