diff --git a/src/app/cli/ArgDef.php b/src/app/cli/ArgDef.php index 614414d..9664d36 100644 --- a/src/app/cli/ArgDef.php +++ b/src/app/cli/ArgDef.php @@ -35,6 +35,19 @@ class ArgDef { } } + protected ?string $extends = null; + + function isExtends(): bool { + return $this->extends !== null; + } + + protected ?bool $disabled = null; + protected ?array $removes = null; + protected ?array $adds = null; + + protected ?array $args = null; + public ?string $argsdesc = null; + protected ?bool $ensureArray = null; protected ?int $action = null; protected ?func $func = null; @@ -44,10 +57,19 @@ class ArgDef { protected ?string $property = null; protected ?string $key = null; + public ?string $help = null; + protected function parse(array $def): void { [$options, $params] = cl::split_assoc($def); - $this->extends = $params["extends"] ?? null; + $this->extends ??= $params["extends"] ?? null; + + $this->disabled = vbool::withn($params["disabled"] ?? null); + $removes = varray::withn($params["remove"] ?? null); + A::merge($this->removes, $removes); + $adds = varray::withn($params["add"] ?? null); + A::merge($this->adds, $adds); + A::merge($this->adds, $options); $args = $params["args"] ?? null; $args ??= $params["arg"] ?? null; @@ -59,13 +81,6 @@ class ArgDef { $this->argsdesc ??= $params["argsdesc"] ?? null; - $this->disabled = vbool::withn($params["disabled"] ?? null); - $adds = varray::withn($params["add"] ?? null); - A::merge($this->adds, $adds); - A::merge($this->adds, $options); - $removes = varray::withn($params["remove"] ?? null); - A::merge($this->removes, $removes); - $this->ensureArray ??= $params["ensure_array"] ?? null; $action = $params["action"] ?? null; if ($action !== null) { @@ -97,18 +112,6 @@ class ArgDef { $this->help ??= $params["help"] ?? null; } - public bool $isHelp = false; - public bool $isRemains = false; - public bool $haveShortOptions = false; - public bool $haveLongOptions = false; - public bool $isCommand = false; - - public bool $haveArgs = false; - public ?int $minArgs = null; - public ?int $maxArgs = null; - public ?string $argsdesc = null; - - protected ?bool $disabled = null; protected ?array $options = []; function getOptions(): array { @@ -116,13 +119,12 @@ class ArgDef { else return array_keys($this->options); } - protected ?array $removes = null; - protected ?array $adds = null; - /** traiter le paramètre parent */ function processOptions(): void { $this->removeOptions($this->removes); + $this->removes = null; $this->addOptions($this->adds); + $this->adds = null; } function addOptions(?array $options): void { @@ -207,6 +209,16 @@ class ArgDef { unset($this->options[$option]); } + public bool $haveShortOptions = false; + public bool $haveLongOptions = false; + public bool $isCommand = false; + public bool $isHelp = false; + public bool $isRemains = false; + + public bool $haveArgs = false; + public ?int $minArgs = null; + public ?int $maxArgs = null; + /** mettre à jour le type d'option */ protected function updateType(): void { $haveShortOptions = false; @@ -236,14 +248,8 @@ class ArgDef { $this->isRemains = $isRemains; } - public ?array $extends = null; - - function isExtends(): bool { - return $this->extends !== null; - } - function processExtends(ArgDefs $argDefs): void { - $option = $this->extends[0] ?? null; + $option = $this->extends; if ($option === null) { throw new ArgException("extends: missing destination arg"); } @@ -266,8 +272,6 @@ class ArgDef { $dest->processOptions(); } - protected ?array $args = null; - /** * traiter les informations concernant les arguments puis calculer les nombres * minimum et maximum d'arguments que prend l'option @@ -424,4 +428,22 @@ class ArgDef { } $this->name = $name; } + + function debugInfos(): array { + return [ + ...$this->getOptions(), + "empty" => $this->isEmpty(), + "help" => $this->help, + "have_short_options" => $this->haveShortOptions, + "have_long_options" => $this->haveLongOptions, + "is_command" => $this->isCommand, + "is_help" => $this->isHelp, + "is_remains" => $this->isRemains, + "ĥave_args" => $this->haveArgs, + "min_args" => $this->minArgs, + "max_args" => $this->maxArgs, + "args" => $this->args, + "argsdesc" => $this->argsdesc, + ]; + } } diff --git a/src/app/cli/ArgDefs.php b/src/app/cli/ArgDefs.php index 1a35879..7d4d648 100644 --- a/src/app/cli/ArgDefs.php +++ b/src/app/cli/ArgDefs.php @@ -12,16 +12,24 @@ abstract class ArgDefs { protected array $defs; - protected function mergeParse(array $defs, ?array &$argDefs): void { + protected function mergeParse(array $defs, ?array &$argDefs, bool $parse=true): void { $defaults = $defs["defaults"] ?? null; - if ($defaults !== null) $this->mergeParse($defaults, $argDefs); + if ($defaults !== null) { + $this->mergeParse($defaults, $argDefs, false); + $this->parse($defaults, $argDefs); + } - $this->parse($defs, $argDefs); + if ($parse) $this->parse($defs, $argDefs); $merges = $defs["merges"] ?? null; $merge = $defs["merge"] ?? null; if ($merge !== null) $merges[] = $merge; - if ($merges !== null) $this->mergeParse($merges, $argDefs); + if ($merges !== null) { + foreach ($merges as $merge) { + $this->mergeParse($merge, $argDefs, false); + $this->parse($merge, $argDefs); + } + } } protected function parseParams(?array $params): void { diff --git a/src/app/cli/SimpleArgDefs.php b/src/app/cli/SimpleArgDefs.php index 4bf3d50..df19842 100644 --- a/src/app/cli/SimpleArgDefs.php +++ b/src/app/cli/SimpleArgDefs.php @@ -57,41 +57,55 @@ class SimpleArgDefs extends ArgDefs { protected function addAll(?array $argDefs): void { parent::addAll($argDefs); - $index = []; + $this->index = []; if ($argDefs !== null) { - # calculer les fusions + # calculer les options pour les objets déjà fusionnés puis indexer une + # première fois foreach ($argDefs as $argDef) { /** @var ArgDef $argDef */ if (!$argDef->isExtends()) { $argDef->processOptions(); } } + $this->index = []; + foreach ($argDefs as $argDef) { + if ($argDef->isExtends()) continue; + $options = $argDef->getOptions(); + foreach ($options as $option) { + /** @var ArgDef $prevArgDef */ + $prevArgDef = $this->index[$option] ?? null; + if ($prevArgDef !== null) $prevArgDef->removeOption($option); + $this->index[$option] = $argDef; + } + } + + # puis traiter les extensions d'objets, calculer les options pour ces + # objets et indexer pour la deuxième fois foreach ($argDefs as $argDef) { /** @var ArgDef $argDef */ if ($argDef->isExtends()) { $argDef->processExtends($this); } } - - # indexer les arguments + $this->index = []; foreach ($argDefs as $argDef) { if ($argDef->isExtends()) continue; $options = $argDef->getOptions(); foreach ($options as $option) { /** @var ArgDef $prevArgDef */ - $prevArgDef = $index[$option] ?? null; + $prevArgDef = $this->index[$option] ?? null; if ($prevArgDef !== null) $prevArgDef->removeOption($option); - $index[$option] = $argDef; + $this->index[$option] = $argDef; } } + # puis calculer nombre d'arguments et actions foreach ($argDefs as $argDef) { if ($argDef->isExtends()) continue; $argDef->processArgs(); $argDef->processAction(); } } - $this->index = $index; } function get(string $option): ?ArgDef { diff --git a/tests/app/cli/ArgDefTest.php b/tests/app/cli/ArgDefTest.php index aaea1a0..074b7d9 100644 --- a/tests/app/cli/ArgDefTest.php +++ b/tests/app/cli/ArgDefTest.php @@ -13,6 +13,7 @@ class ArgDefTest extends TestCase { $argDef->processOptions(); $argDef->processArgs(); $argDef->processAction(); + var_export($argDef->debugInfos()); #XXX self::assertSame($options, $argDef->getOptions()); self::assertSame($haveShortOptions, $argDef->haveShortOptions, "haveShortOptions"); self::assertSame($haveLongOptions, $argDef->haveLongOptions, "haveLongOptions"); @@ -155,4 +156,28 @@ class ArgDefTest extends TestCase { true, true, false, false, 0, 0, ""); } + + function testExtends() { + $ARGS1 = [ + ["-o:", "--longo", + "name" => "desto", + "help" => "help longo" + ], + ["-a:", "--longa", + "name" => "desta", + "help" => "help longa" + ], + ]; + $ARGS2 = [ + "merge" => $ARGS1, + ["extends" => "-a", + "remove" => ["--longa"], + "add" => ["--desta"], + "help" => "help desta" + ], + ]; + $argDefs1 = new SimpleArgDefs($ARGS1); + $argDefs2 = new SimpleArgDefs($ARGS2); + self::assertTrue(true); + } }