origDefs = $defs; $this->initDefs($defs, $setup); } protected array $origDefs; protected ?array $aomain; protected ?array $aosections; protected ?array $aospecials; public ?Aodef $remainsArgdef = null; function initDefs(array $defs, bool $setup=true): void { $this->mergeParse($defs, $aobjects); $this->aomain = $aobjects["main"] ?? null; $this->aosections = $aobjects["sections"] ?? null; $this->aospecials = $aobjects["specials"] ?? null; if ($setup) $this->setup(); } protected function mergeParse(array $defs, ?array &$aobjects, bool $parse=true): void { $aobjects ??= []; $merges = $defs["merges"] ?? null; $merge = $defs["merge"] ?? null; if ($merge !== null) $merges[] = $merge; if ($merges !== null) { foreach ($merges as $merge) { $this->mergeParse($merge, $aobjects, false); $this->parse($merge, $aobjects); } } if ($parse) $this->parse($defs, $aobjects); $merge = $defs["merge_after"] ?? null; if ($merge !== null) { $this->mergeParse($merge, $aobjects, false); $this->parse($merge, $aobjects); } } protected function parse(array $defs, array &$aobjects): void { [$defs, $params] = cl::split_assoc($defs); if ($defs !== null) { $aomain =& $aobjects["main"]; foreach ($defs as $def) { $first = $def[0] ?? null; if ($first === "group") { $aobject = new Aogroup($def); } else { $aobject = new Aodef($def); } $aomain[] = $aobject; } } $sections = $params["sections"] ?? null; if ($sections !== null) { $aosections =& $aobjects["sections"]; $index = 0; foreach ($sections as $key => $section) { if ($key === $index) { $index++; $aosections[] = new Aosection($section); } else { /** @var Aosection $aosection */ $aosection = $aosections[$key] ?? null; if ($aosection === null) { $aosections[$key] = new Aosection($section); } else { #XXX il faut implémenter la fusion en cas de section existante # pour le moment, la liste existante est écrasée $aosection->initDefs($section); } } } } $this->parseParams($params); } protected function parseParams(?array $params): void { } function all(?array $what=null): iterable { $returnsAodef = $what["aodef"] ?? true; $returnsAolist = $what["aolist"] ?? false; $returnExtends = $what["extends"] ?? false; $withSpecials = $what["aospecials"] ?? true; # lister les sections avant, pour que les options de la section principale # soient prioritaires $aosections = $this->aosections; if ($aosections !== null) { /** @var Aosection $aobject */ foreach ($aosections as $aosection) { if ($returnsAolist) { yield $aosection; } elseif ($returnsAodef) { yield from $aosection->all($what); } } } $aomain = $this->aomain; if ($aomain !== null) { /** @var Aodef $aobject */ foreach ($aomain as $aobject) { if ($aobject instanceof Aodef) { if ($returnsAodef) { if ($returnExtends) { if ($aobject->isExtends()) yield $aobject; } else { if (!$aobject->isExtends()) yield $aobject; } } } elseif ($aobject instanceof Aolist) { if ($returnsAolist) { yield $aobject; } elseif ($returnsAodef) { yield from $aobject->all($what); } } } } $aospecials = $this->aospecials; if ($withSpecials && $aospecials !== null) { /** @var Aodef $aobject */ foreach ($aospecials as $aobject) { yield $aobject; } } } protected function filter(callable $callback): void { $aomain = $this->aomain; if ($aomain !== null) { $filtered = []; /** @var Aodef $aobject */ foreach ($aomain as $aobject) { if ($aobject instanceof Aolist) { $aobject->filter($callback); } if (call_user_func($callback, $aobject)) { $filtered[] = $aobject; } } $this->aomain = $filtered; } $aosections = $this->aosections; if ($aosections !== null) { $filtered = []; /** @var Aosection $aosection */ foreach ($aosections as $aosection) { $aosection->filter($callback); if (call_user_func($callback, $aosection)) { $filtered[] = $aosection; } } $this->aosections = $filtered; } } protected function setup(): void { # calculer les options foreach ($this->all() as $aodef) { $aodef->setup1(); } /** @var Aodef $aodef */ foreach ($this->all(["extends" => true]) as $aodef) { $aodef->setup1(true, $this); } # ne garder que les objets non vides $this->filter(function($aobject): bool { if ($aobject instanceof Aodef) { return !$aobject->isEmpty(); } elseif ($aobject instanceof Aolist) { return !$aobject->isEmpty(); } else { return false; } }); # puis calculer nombre d'arguments et actions foreach ($this->all() as $aodef) { $aodef->setup2(); } } function isEmpty(): bool { foreach ($this->all() as $aobject) { return false; } return true; } function get(string $option): ?Aodef { return null; } function actionPrintHelp(string $arg): void { $this->printHelp([ "show_all" => $arg === "--help++", ]); } function printHelp(?array $what=null): void { $show = $what["show_all"] ?? false; if (!$show) $show = null; $aosections = $this->aosections; if ($aosections !== null) { /** @var Aosection $aosection */ foreach ($aosections as $aosection) { $aosection->printHelp(cl::merge($what, [ "show" => $show, "prefix" => "\n", ])); } } $aomain = $this->aomain; if ($aomain !== null) { echo "\nOPTIONS\n"; foreach ($aomain as $aobject) { $aobject->printHelp(cl::merge($what, [ "show" => $show, ])); } } } function __toString(): string { $items = []; $what = [ "aodef" => true, "aolist" => true, ]; foreach ($this->all($what) as $aobject) { if ($aobject instanceof Aodef) { $items[] = strval($aobject); } elseif ($aobject instanceof Aogroup) { $items[] = implode("\n", [ "group", str::indent(strval($aobject)), ]); } elseif ($aobject instanceof Aosection) { $items[] = implode("\n", [ "section", str::indent(strval($aobject)), ]); } else { $items[] = false; } } return implode("\n", $items); } }