modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2025-09-23 02:13:32 +04:00
parent 0fa1f5a182
commit 2e3b290d84
6 changed files with 151 additions and 88 deletions

View File

@ -7,7 +7,7 @@ use nulib\php\func;
use nulib\php\types\varray; use nulib\php\types\varray;
use nulib\php\types\vbool; use nulib\php\types\vbool;
class ArgDef { class ArgDef implements IArgo {
const TYPE_SHORT = 0, TYPE_LONG = 1, TYPE_COMMAND = 2; const TYPE_SHORT = 0, TYPE_LONG = 1, TYPE_COMMAND = 2;
const ARGS_NONE = 0, ARGS_MANDATORY = 1, ARGS_OPTIONAL = 2; const ARGS_NONE = 0, ARGS_MANDATORY = 1, ARGS_OPTIONAL = 2;
const ACTION_SET = 0, ACTION_INC = 1, ACTION_DEC = 2, ACTION_FUNC = 3; 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); else return array_keys($this->options);
} }
function isEmpty(): bool {
return $this->disabled || !boolval($this->options);
}
/** traiter le paramètre parent */ /** traiter le paramètre parent */
function processOptions(): void { function processOptions(): void {
$this->removeOptions($this->removes); $this->removeOptions($this->removes);
@ -433,17 +437,16 @@ class ArgDef {
return [ return [
...$this->getOptions(), ...$this->getOptions(),
"empty" => $this->isEmpty(), "empty" => $this->isEmpty(),
"help" => $this->help, //"help" => $this->help,
"have_short_options" => $this->haveShortOptions, //"have_short_options" => $this->haveShortOptions,
"have_long_options" => $this->haveLongOptions, //"have_long_options" => $this->haveLongOptions,
"is_command" => $this->isCommand, //"is_command" => $this->isCommand,
"is_help" => $this->isHelp, //"is_help" => $this->isHelp,
"is_remains" => $this->isRemains, //"is_remains" => $this->isRemains,
"ĥave_args" => $this->haveArgs, //"ĥave_args" => $this->haveArgs,
"min_args" => $this->minArgs, //"min_args" => $this->minArgs,
"max_args" => $this->maxArgs, //"max_args" => $this->maxArgs,
"args" => $this->args, //"argsdesc" => $this->argsdesc,
"argsdesc" => $this->argsdesc,
]; ];
} }
} }

View File

@ -3,60 +3,61 @@ namespace nulib\app\cli;
use nulib\cl; use nulib\cl;
abstract class ArgDefs { abstract class ArgDefs implements IArgo {
function __construct(array $defs) { function __construct(array $defs) {
$this->defs = $defs; $this->defs = $defs;
$this->mergeParse($defs, $argDefs); $this->mergeParse($defs, $argos);
$this->addAll($argDefs); $this->setArgos($argos);
} }
protected array $defs; 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; $defaults = $defs["defaults"] ?? null;
if ($defaults !== null) { if ($defaults !== null) {
$this->mergeParse($defaults, $argDefs, false); $this->mergeParse($defaults, $argos, false);
$this->parse($defaults, $argDefs); $this->parse($defaults, $argos);
} }
if ($parse) $this->parse($defs, $argDefs); if ($parse) $this->parse($defs, $argos);
$merges = $defs["merges"] ?? null; $merges = $defs["merges"] ?? null;
$merge = $defs["merge"] ?? null; $merge = $defs["merge"] ?? null;
if ($merge !== null) $merges[] = $merge; if ($merge !== null) $merges[] = $merge;
if ($merges !== null) { if ($merges !== null) {
foreach ($merges as $merge) { foreach ($merges as $merge) {
$this->mergeParse($merge, $argDefs, false); $this->mergeParse($merge, $argos, false);
$this->parse($merge, $argDefs); $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 parseParams(?array $params): void {
} }
protected function parse(array $defs, ?array &$argDefs): void { protected array $argos;
[$defs, $params] = cl::split_assoc($defs);
foreach ($defs as $def) { function getArgos(): array {
$argDefs[] = new ArgDef($def); return $this->argos;
}
$this->parseParams($params);
} }
protected array $all; protected function setArgos(?array $argos): void {
$argos ??= [];
protected function addAll(?array $argDefs): void { $this->argos = array_filter($argos, function (IArgo $argo): bool {
$this->all = $argDefs ?? []; return !$argo->isEmpty();
}
function all(): array {
return array_filter($this->all, function (ArgDef $argDef) {
return !$argDef->isEmpty();
}); });
} }
function isEmpty(): bool { function isEmpty(): bool {
return !$this->all(); return !$this->getArgos();
} }
function get(string $option): ?ArgDef { function get(string $option): ?ArgDef {
@ -117,4 +118,10 @@ abstract class ArgDefs {
function normalize(array $args): array { function normalize(array $args): array {
return $args; return $args;
} }
function debugInfos(): array {
return array_map(function (IArgo $argo) {
return $argo->debugInfos();
}, $this->argos);
}
} }

11
src/app/cli/IArgo.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace nulib\app\cli;
/**
* Interface IArgo: une instance de ArgDef, ArgGroup ou ArgSection
*/
interface IArgo {
function isEmpty(): bool;
function debugInfos(): array;
}

View File

@ -55,57 +55,62 @@ class SimpleArgDefs extends ArgDefs {
protected array $index; protected array $index;
protected function addAll(?array $argDefs): void { protected function setArgos(?array $argos): void {
parent::addAll($argDefs); $argos ??= [];
$this->index = [];
if ($argDefs !== null) {
# calculer les options pour les objets déjà fusionnés puis indexer une # calculer les options pour les objets déjà fusionnés puis indexer une
# première fois # première fois
foreach ($argDefs as $argDef) { foreach ($argos as $argo) {
/** @var ArgDef $argDef */ /** @var ArgDef $argo */
if (!$argDef->isExtends()) { if (!$argo->isExtends()) {
$argDef->processOptions(); $argo->processOptions();
} }
} }
$this->index = []; $this->index = [];
foreach ($argDefs as $argDef) { foreach ($argos as $argo) {
if ($argDef->isExtends()) continue; if ($argo->isExtends()) continue;
$options = $argDef->getOptions(); $options = $argo->getOptions();
foreach ($options as $option) { foreach ($options as $option) {
/** @var ArgDef $prevArgDef */ /** @var ArgDef $prevArgo */
$prevArgDef = $this->index[$option] ?? null; $prevArgo = $this->index[$option] ?? null;
if ($prevArgDef !== null) $prevArgDef->removeOption($option); if ($prevArgo !== null) $prevArgo->removeOption($option);
$this->index[$option] = $argDef; $this->index[$option] = $argo;
} }
} }
# puis traiter les extensions d'objets, calculer les options pour ces # puis traiter les extensions d'objets, calculer les options pour ces
# objets et indexer pour la deuxième fois # objets et indexer pour la deuxième fois
foreach ($argDefs as $argDef) { foreach ($argos as $argo) {
/** @var ArgDef $argDef */ /** @var ArgDef $argo */
if ($argDef->isExtends()) { if ($argo->isExtends()) {
$argDef->processExtends($this); $argo->processExtends($this);
} }
} }
$this->index = []; $this->index = [];
foreach ($argDefs as $argDef) { foreach ($argos as $argo) {
if ($argDef->isExtends()) continue; if ($argo->isExtends()) continue;
$options = $argDef->getOptions(); $options = $argo->getOptions();
foreach ($options as $option) { foreach ($options as $option) {
/** @var ArgDef $prevArgDef */ /** @var ArgDef $prevArgo */
$prevArgDef = $this->index[$option] ?? null; $prevArgo = $this->index[$option] ?? null;
if ($prevArgDef !== null) $prevArgDef->removeOption($option); if ($prevArgo !== null) $prevArgo->removeOption($option);
$this->index[$option] = $argDef; $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 # puis calculer nombre d'arguments et actions
foreach ($argDefs as $argDef) { foreach ($argos as $argo) {
if ($argDef->isExtends()) continue; if ($argo->isExtends()) continue;
$argDef->processArgs(); $argo->processArgs();
$argDef->processAction(); $argo->processAction();
}
} }
$this->argos = $argos;
} }
function get(string $option): ?ArgDef { function get(string $option): ?ArgDef {
@ -260,4 +265,15 @@ class SimpleArgDefs extends ArgDefs {
} }
return array_merge($options, ["--"], $remains); 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),
];
}
} }

View File

@ -4,8 +4,6 @@
* [x] pour le nombre d'arguments, supporter l'alias `*` pour `0..N` et `+` pour `1..N` * [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 * [ ] 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 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 puis faire une implémentation ArgsParser qui supporte les commandes, et les options dynamiques

View File

@ -157,6 +157,31 @@ class ArgDefTest extends TestCase {
false, 0, 0, ""); 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() { function testExtends() {
$ARGS1 = [ $ARGS1 = [
["-o:", "--longo", ["-o:", "--longo",
@ -176,8 +201,11 @@ class ArgDefTest extends TestCase {
"help" => "help desta" "help" => "help desta"
], ],
]; ];
$argDefs1 = new SimpleArgDefs($ARGS1); //$argDefs1 = new SimpleArgDefs($ARGS1);
//var_export($argDefs1->debugInfos()); #XXX
$argDefs2 = new SimpleArgDefs($ARGS2); $argDefs2 = new SimpleArgDefs($ARGS2);
var_export($argDefs2->debugInfos()); #XXX
self::assertTrue(true); self::assertTrue(true);
} }
} }