diff --git a/src/app/cli/ArgDef.php b/src/app/cli/ArgDef.php index 9664d36..fa508bc 100644 --- a/src/app/cli/ArgDef.php +++ b/src/app/cli/ArgDef.php @@ -7,7 +7,7 @@ use nulib\php\func; use nulib\php\types\varray; use nulib\php\types\vbool; -class ArgDef { +class ArgDef implements IArgo { const TYPE_SHORT = 0, TYPE_LONG = 1, TYPE_COMMAND = 2; const ARGS_NONE = 0, ARGS_MANDATORY = 1, ARGS_OPTIONAL = 2; const ACTION_SET = 0, ACTION_INC = 1, ACTION_DEC = 2, ACTION_FUNC = 3; @@ -119,6 +119,10 @@ class ArgDef { else return array_keys($this->options); } + function isEmpty(): bool { + return $this->disabled || !boolval($this->options); + } + /** traiter le paramètre parent */ function processOptions(): void { $this->removeOptions($this->removes); @@ -433,17 +437,16 @@ class ArgDef { 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, + //"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, + //"argsdesc" => $this->argsdesc, ]; } } diff --git a/src/app/cli/ArgDefs.php b/src/app/cli/ArgDefs.php index 7d4d648..9944349 100644 --- a/src/app/cli/ArgDefs.php +++ b/src/app/cli/ArgDefs.php @@ -3,60 +3,61 @@ namespace nulib\app\cli; use nulib\cl; -abstract class ArgDefs { +abstract class ArgDefs implements IArgo { function __construct(array $defs) { $this->defs = $defs; - $this->mergeParse($defs, $argDefs); - $this->addAll($argDefs); + $this->mergeParse($defs, $argos); + $this->setArgos($argos); } protected array $defs; - protected function mergeParse(array $defs, ?array &$argDefs, bool $parse=true): void { + protected function mergeParse(array $defs, ?array &$argos, bool $parse=true): void { $defaults = $defs["defaults"] ?? null; if ($defaults !== null) { - $this->mergeParse($defaults, $argDefs, false); - $this->parse($defaults, $argDefs); + $this->mergeParse($defaults, $argos, false); + $this->parse($defaults, $argos); } - if ($parse) $this->parse($defs, $argDefs); + if ($parse) $this->parse($defs, $argos); $merges = $defs["merges"] ?? null; $merge = $defs["merge"] ?? null; if ($merge !== null) $merges[] = $merge; if ($merges !== null) { foreach ($merges as $merge) { - $this->mergeParse($merge, $argDefs, false); - $this->parse($merge, $argDefs); + $this->mergeParse($merge, $argos, false); + $this->parse($merge, $argos); } } } + protected function parse(array $defs, ?array &$argos): void { + [$defs, $params] = cl::split_assoc($defs); + foreach ($defs as $def) { + $argos[] = new ArgDef($def); + } + $this->parseParams($params); + } + protected function parseParams(?array $params): void { } - protected function parse(array $defs, ?array &$argDefs): void { - [$defs, $params] = cl::split_assoc($defs); - foreach ($defs as $def) { - $argDefs[] = new ArgDef($def); - } - $this->parseParams($params); + protected array $argos; + + function getArgos(): array { + return $this->argos; } - protected array $all; - - protected function addAll(?array $argDefs): void { - $this->all = $argDefs ?? []; - } - - function all(): array { - return array_filter($this->all, function (ArgDef $argDef) { - return !$argDef->isEmpty(); + protected function setArgos(?array $argos): void { + $argos ??= []; + $this->argos = array_filter($argos, function (IArgo $argo): bool { + return !$argo->isEmpty(); }); } function isEmpty(): bool { - return !$this->all(); + return !$this->getArgos(); } function get(string $option): ?ArgDef { @@ -117,4 +118,10 @@ abstract class ArgDefs { function normalize(array $args): array { return $args; } + + function debugInfos(): array { + return array_map(function (IArgo $argo) { + return $argo->debugInfos(); + }, $this->argos); + } } diff --git a/src/app/cli/IArgo.php b/src/app/cli/IArgo.php new file mode 100644 index 0000000..d8a2158 --- /dev/null +++ b/src/app/cli/IArgo.php @@ -0,0 +1,11 @@ +index = []; - if ($argDefs !== null) { - # 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; - } - } + protected function setArgos(?array $argos): void { + $argos ??= []; - # 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); - } - } - $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 calculer nombre d'arguments et actions - foreach ($argDefs as $argDef) { - if ($argDef->isExtends()) continue; - $argDef->processArgs(); - $argDef->processAction(); + # calculer les options pour les objets déjà fusionnés puis indexer une + # première fois + foreach ($argos as $argo) { + /** @var ArgDef $argo */ + if (!$argo->isExtends()) { + $argo->processOptions(); } } + $this->index = []; + foreach ($argos as $argo) { + if ($argo->isExtends()) continue; + $options = $argo->getOptions(); + foreach ($options as $option) { + /** @var ArgDef $prevArgo */ + $prevArgo = $this->index[$option] ?? null; + if ($prevArgo !== null) $prevArgo->removeOption($option); + $this->index[$option] = $argo; + } + } + + # puis traiter les extensions d'objets, calculer les options pour ces + # objets et indexer pour la deuxième fois + foreach ($argos as $argo) { + /** @var ArgDef $argo */ + if ($argo->isExtends()) { + $argo->processExtends($this); + } + } + $this->index = []; + foreach ($argos as $argo) { + if ($argo->isExtends()) continue; + $options = $argo->getOptions(); + foreach ($options as $option) { + /** @var ArgDef $prevArgo */ + $prevArgo = $this->index[$option] ?? null; + if ($prevArgo !== null) $prevArgo->removeOption($option); + $this->index[$option] = $argo; + } + } + + # ne garder que les objets non vides + $argos = array_filter($argos, function(IArgo $argo): bool { + return !$argo->isEmpty(); + }); + + # puis calculer nombre d'arguments et actions + foreach ($argos as $argo) { + if ($argo->isExtends()) continue; + $argo->processArgs(); + $argo->processAction(); + } + + $this->argos = $argos; } function get(string $option): ?ArgDef { @@ -260,4 +265,15 @@ class SimpleArgDefs extends ArgDefs { } return array_merge($options, ["--"], $remains); } + + function debugInfos(): array { + return [ + "argos" => array_map(function (IArgo $argo) { + return $argo->debugInfos(); + }, $this->argos), + "index" => array_map(function (IArgo $argo) { + return $argo->debugInfos(); + }, $this->index), + ]; + } } diff --git a/src/app/cli/TODO.md b/src/app/cli/TODO.md index 44c1be5..7f3a2c1 100644 --- a/src/app/cli/TODO.md +++ b/src/app/cli/TODO.md @@ -4,8 +4,6 @@ * [x] pour le nombre d'arguments, supporter l'alias `*` pour `0..N` et `+` pour `1..N` * [ ] transformer un schéma en définition d'arguments, un tableau en liste d'arguments, et vice-versa -lors de la surcharge d'une définition d'option, certaines options sont supprimées. quand toutes les options sont supprimées, la définition disparait. - faire une implémentation SimpleArgsParser qui ne supporte pas les commandes, uniquement les options puis faire une implémentation ArgsParser qui supporte les commandes, et les options dynamiques diff --git a/tests/app/cli/ArgDefTest.php b/tests/app/cli/ArgDefTest.php index 074b7d9..d84a787 100644 --- a/tests/app/cli/ArgDefTest.php +++ b/tests/app/cli/ArgDefTest.php @@ -157,6 +157,31 @@ class ArgDefTest extends TestCase { false, 0, 0, ""); } + function testOverride() { + $argDefs = new SimpleArgDefs([ + ["-o", "--longx"], + "merge" => [ + ["-o", "--longo"], + ], + ]); + var_export($argDefs->debugInfos()); #XXX + + $argDefs = new SimpleArgDefs([ + ["-o", "--longo"], + ["-o", "--longx"], + ]); + var_export($argDefs->debugInfos()); #XXX + + $argDefs = new SimpleArgDefs([ + ["-o", "--longo"], + ["-o"], + ["--longo"], + ]); + var_export($argDefs->debugInfos()); #XXX + + self::assertTrue(true); + } + function testExtends() { $ARGS1 = [ ["-o:", "--longo", @@ -176,8 +201,11 @@ class ArgDefTest extends TestCase { "help" => "help desta" ], ]; - $argDefs1 = new SimpleArgDefs($ARGS1); + //$argDefs1 = new SimpleArgDefs($ARGS1); + //var_export($argDefs1->debugInfos()); #XXX $argDefs2 = new SimpleArgDefs($ARGS2); + var_export($argDefs2->debugInfos()); #XXX + self::assertTrue(true); } }