nur-ture/src/app/cli/Aolist.php

269 lines
7.0 KiB
PHP

<?php
namespace nulib\app\cli;
use nulib\cl;
use nulib\str;
use const true;
/**
* Class Aodefs: une liste d'objets Aodef
*/
abstract class Aolist {
function __construct(array $defs, bool $setup=true) {
$this->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);
}
}