modifs.mineures sans commentaires
This commit is contained in:
parent
e4d5860d8e
commit
737f0b411b
@ -12,27 +12,61 @@ class ArgDef {
|
||||
const ARGS_NONE = 0, ARGS_MANDATORY = 1, ARGS_OPTIONAL = 2;
|
||||
const ACTION_SET = 0, ACTION_INC = 1, ACTION_DEC = 2, ACTION_FUNC = 3;
|
||||
|
||||
protected static function parse_def(ArgDef $dest, array $def): void {
|
||||
function __construct(array $def) {
|
||||
$this->def = $def;
|
||||
$this->mergeParse($def);
|
||||
}
|
||||
|
||||
protected array $def;
|
||||
|
||||
protected function mergeParse(array $def): void {
|
||||
$defaults = $defs["defaults"] ?? null;
|
||||
if ($defaults !== null) $this->mergeParse($defaults);
|
||||
|
||||
$this->parse($def);
|
||||
|
||||
$merges = $defs["merges"] ?? null;
|
||||
$merge = $defs["merge"] ?? null;
|
||||
if ($merge !== null) $merges[] = $merge;
|
||||
if ($merges !== null) {
|
||||
foreach ($merges as $merge) {
|
||||
if ($merge !== null) $this->mergeParse($merge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ?bool $ensureArray = null;
|
||||
protected ?int $action = null;
|
||||
protected ?func $func = null;
|
||||
protected ?bool $inverse = null;
|
||||
protected $value = null;
|
||||
protected ?string $name = null;
|
||||
protected ?string $property = null;
|
||||
protected ?string $key = null;
|
||||
|
||||
protected function parse(array $def): void {
|
||||
[$options, $params] = cl::split_assoc($def);
|
||||
|
||||
$this->extends = $params["extends"] ?? null;
|
||||
|
||||
$args = $params["args"] ?? null;
|
||||
$args ??= $params["arg"] ?? null;
|
||||
if ($args === true) $args = 1;
|
||||
elseif ($args === "*") $args = [null];
|
||||
elseif ($args === "+") $args = ["value", null];
|
||||
if (is_int($args)) $args = array_fill(0, $args, "value");
|
||||
$dest->args ??= cl::withn($args);
|
||||
$this->args ??= cl::withn($args);
|
||||
|
||||
$dest->argsdesc ??= $params["argsdesc"] ?? null;
|
||||
$this->argsdesc ??= $params["argsdesc"] ?? null;
|
||||
|
||||
$this->disabled = vbool::withn($params["disabled"] ?? null);
|
||||
$adds = varray::withn($params["add"] ?? null);
|
||||
A::merge($dest->adds, $adds);
|
||||
A::merge($dest->adds, $options);
|
||||
A::merge($this->adds, $adds);
|
||||
A::merge($this->adds, $options);
|
||||
$removes = varray::withn($params["remove"] ?? null);
|
||||
A::merge($dest->removes, $removes);
|
||||
$dest->disabled = vbool::withn($params["disabled"] ?? null);
|
||||
A::merge($this->removes, $removes);
|
||||
|
||||
$dest->ensureArray ??= $params["ensure_array"] ?? null;
|
||||
$this->ensureArray ??= $params["ensure_array"] ?? null;
|
||||
$action = $params["action"] ?? null;
|
||||
if ($action !== null) {
|
||||
$func = null;
|
||||
@ -51,72 +85,44 @@ class ArgDef {
|
||||
$action = self::ACTION_FUNC;
|
||||
break;
|
||||
}
|
||||
$dest->action ??= $action;
|
||||
$dest->func ??= $func;
|
||||
$this->action ??= $action;
|
||||
$this->func ??= $func;
|
||||
}
|
||||
$dest->inverse ??= $params["inverse"] ?? false;
|
||||
$dest->value ??= $params["value"] ?? null;
|
||||
$dest->name ??= $params["name"] ?? null;
|
||||
$dest->property ??= $params["property"] ?? null;
|
||||
$dest->key ??= $params["key"] ?? null;
|
||||
$this->inverse ??= $params["inverse"] ?? null;
|
||||
$this->value ??= $params["value"] ?? null;
|
||||
$this->name ??= $params["name"] ?? null;
|
||||
$this->property ??= $params["property"] ?? null;
|
||||
$this->key ??= $params["key"] ?? null;
|
||||
|
||||
$dest->help ??= $params["help"] ?? null;
|
||||
$this->help ??= $params["help"] ?? null;
|
||||
}
|
||||
|
||||
protected static function merge_parse_def(ArgDef $dest, array $def, ?ArgDefs $argDefs=null): void {
|
||||
$defaults = $defs["defaults"] ?? null;
|
||||
if (is_string($defaults)) $defaults = $argDefs->getArgDef($defaults)->origDef;
|
||||
if ($defaults !== null) self::merge_parse_def($dest, $defaults);
|
||||
|
||||
self::parse_def($dest, $def);
|
||||
|
||||
$merges = $defs["merges"] ?? null;
|
||||
$merge = $defs["merge"] ?? null;
|
||||
if ($merge !== null) $merges[] = $merge;
|
||||
if ($merges !== null) {
|
||||
foreach ($merges as $merge) {
|
||||
if (is_string($merge)) $merge = $argDefs->getArgDef($merge)->origDef;
|
||||
if ($merge !== null) self::merge_parse_def($dest, $merge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function __construct(array $def, ?ArgDefs $argDefs=null) {
|
||||
$this->origDef = $def;
|
||||
self::merge_parse_def($this, $def, $argDefs);
|
||||
}
|
||||
|
||||
protected array $origDef;
|
||||
|
||||
public bool $isHelp = false;
|
||||
public bool $isRemains = false;
|
||||
public bool $haveShortOptions = false;
|
||||
public bool $haveLongOptions = false;
|
||||
public bool $haveCommands = 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 {
|
||||
return array_keys($this->options);
|
||||
if ($this->disabled) return [];
|
||||
else return array_keys($this->options);
|
||||
}
|
||||
|
||||
protected ?array $removes = null;
|
||||
protected ?array $adds = null;
|
||||
protected ?bool $disabled = null;
|
||||
|
||||
/** traiter le paramètre parent */
|
||||
function processOptions(): void {
|
||||
if ($this->disabled) {
|
||||
$this->options = [];
|
||||
} else {
|
||||
$this->removeOptions($this->removes);
|
||||
$this->addOptions($this->adds);
|
||||
}
|
||||
$this->removeOptions($this->removes);
|
||||
$this->addOptions($this->adds);
|
||||
}
|
||||
|
||||
function addOptions(?array $options): void {
|
||||
@ -205,7 +211,7 @@ class ArgDef {
|
||||
protected function updateType(): void {
|
||||
$haveShortOptions = false;
|
||||
$haveLongOptions = false;
|
||||
$haveCommands = false;
|
||||
$isCommand = false;
|
||||
$isHelp = false;
|
||||
$isRemains = true;
|
||||
foreach ($this->options as $option) {
|
||||
@ -218,18 +224,48 @@ class ArgDef {
|
||||
$haveLongOptions = true;
|
||||
break;
|
||||
case self::TYPE_COMMAND:
|
||||
$haveCommands = true;
|
||||
$isCommand = true;
|
||||
break;
|
||||
}
|
||||
if ($option["option"] === "--help") $isHelp = true;
|
||||
}
|
||||
$this->haveShortOptions = $haveShortOptions;
|
||||
$this->haveLongOptions = $haveLongOptions;
|
||||
$this->haveCommands = $haveCommands;
|
||||
$this->isCommand = $isCommand;
|
||||
$this->isHelp = $isHelp;
|
||||
$this->isRemains = $isRemains;
|
||||
}
|
||||
|
||||
public ?array $extends = null;
|
||||
|
||||
function isExtends(): bool {
|
||||
return $this->extends !== null;
|
||||
}
|
||||
|
||||
function processExtends(ArgDefs $argDefs): void {
|
||||
$option = $this->extends[0] ?? null;
|
||||
if ($option === null) {
|
||||
throw new ArgException("extends: missing destination arg");
|
||||
}
|
||||
$dest = $argDefs->get($option);
|
||||
if ($dest === null) {
|
||||
throw new ArgException("$option: invalid destination arg");
|
||||
}
|
||||
|
||||
if ($this->ensureArray !== null) $dest->ensureArray = $this->ensureArray;
|
||||
if ($this->action !== null) $dest->action = $this->action;
|
||||
if ($this->func !== null) $dest->func = $this->func;
|
||||
if ($this->inverse !== null) $dest->inverse = $this->inverse;
|
||||
if ($this->value !== null) $dest->value = $this->value;
|
||||
if ($this->name !== null) $dest->name = $this->name;
|
||||
if ($this->property !== null) $dest->property = $this->property;
|
||||
if ($this->key !== null) $dest->key = $this->key;
|
||||
|
||||
A::merge($dest->removes, $this->removes);
|
||||
A::merge($dest->adds, $this->adds);
|
||||
$dest->processOptions();
|
||||
}
|
||||
|
||||
protected ?array $args = null;
|
||||
|
||||
/**
|
||||
@ -330,15 +366,6 @@ class ArgDef {
|
||||
$this->argsdesc = implode(" ", $argsdesc);
|
||||
}
|
||||
|
||||
protected ?bool $ensureArray = null;
|
||||
protected ?int $action = null;
|
||||
protected ?func $func = null;
|
||||
protected bool $inverse = false;
|
||||
protected $value = null;
|
||||
protected ?string $name = null;
|
||||
protected ?string $property = null;
|
||||
protected ?string $key = null;
|
||||
|
||||
private static function get_longest(array $options, int $type): ?string {
|
||||
$longest = null;
|
||||
$maxlen = 0;
|
||||
|
@ -2,68 +2,58 @@
|
||||
namespace nulib\app\cli;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\php\types\vbool;
|
||||
|
||||
abstract class ArgDefs {
|
||||
protected static function parse_defs(SimpleArgDefs $dest, array $defs, ?array &$argDefs): void {
|
||||
[$defs, $params] = cl::split_assoc($defs);
|
||||
|
||||
# méta-informations
|
||||
$dest->prefix ??= $params["prefix"] ?? null;
|
||||
$dest->name ??= $params["name"] ?? null;
|
||||
$dest->purpose ??= $params["purpose"] ?? null;
|
||||
$dest->usage ??= $params["usage"] ?? null;
|
||||
$dest->description ??= $params["description"] ?? null;
|
||||
$dest->suffix ??= $params["suffix"] ?? null;
|
||||
|
||||
$dest->commandname ??= $params["commandname"] ?? null;
|
||||
$dest->commandproperty ??= $params["commandproperty"] ?? null;
|
||||
$dest->commandkey ??= $params["commandkey"] ?? null;
|
||||
|
||||
$dest->argsname ??= $params["argsname"] ?? null;
|
||||
$dest->argsproperty ??= $params["argsproperty"] ?? null;
|
||||
$dest->argskey ??= $params["argskey"] ?? null;
|
||||
|
||||
$dest->autohelp ??= vbool::withn($params["autohelp"] ?? null);
|
||||
$dest->autoremains ??= vbool::withn($params["autoremains"] ?? null);
|
||||
|
||||
# définition des options
|
||||
foreach ($defs as $def) {
|
||||
$argDefs[] = new ArgDef($def, $dest);
|
||||
}
|
||||
function __construct(array $defs) {
|
||||
$this->defs = $defs;
|
||||
$this->mergeParse($defs, $argDefs);
|
||||
$this->addAll($argDefs);
|
||||
}
|
||||
|
||||
protected static function merge_parse_defs(SimpleArgDefs $dest, array $defs, ?array &$argDefs): void {
|
||||
$defaults = $defs["defaults"] ?? null;
|
||||
if ($defaults !== null) self::merge_parse_defs($dest, $defaults, $argDefs);
|
||||
protected array $defs;
|
||||
|
||||
self::parse_defs($dest, $defs, $argDefs);
|
||||
protected function mergeParse(array $defs, ?array &$argDefs): void {
|
||||
$defaults = $defs["defaults"] ?? null;
|
||||
if ($defaults !== null) $this->mergeParse($defaults, $argDefs);
|
||||
|
||||
$this->parse($defs, $argDefs);
|
||||
|
||||
$merges = $defs["merges"] ?? null;
|
||||
$merge = $defs["merge"] ?? null;
|
||||
if ($merge !== null) $merges[] = $merge;
|
||||
if ($merges !== null) self::merge_parse_defs($dest, $merges, $argDefs);
|
||||
if ($merges !== null) $this->mergeParse($merges, $argDefs);
|
||||
}
|
||||
|
||||
public ?string $prefix = null;
|
||||
public ?string $name = null;
|
||||
public ?string $purpose = null;
|
||||
public ?string $usage = null;
|
||||
public ?string $description = null;
|
||||
public ?string $suffix = null;
|
||||
protected function parseParams(?array $params): void {
|
||||
}
|
||||
|
||||
public ?string $commandname = null;
|
||||
public ?string $commandproperty = null;
|
||||
public ?string $commandkey = null;
|
||||
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);
|
||||
}
|
||||
|
||||
public ?string $argsname = null;
|
||||
public ?string $argsproperty = null;
|
||||
public ?string $argskey = null;
|
||||
protected array $all;
|
||||
|
||||
public ?bool $autohelp = null;
|
||||
public ?bool $autoremains = null;
|
||||
protected function addAll(?array $argDefs): void {
|
||||
$this->all = $argDefs ?? [];
|
||||
}
|
||||
|
||||
abstract function getArgDef(string $option): ?ArgDef;
|
||||
function all(): array {
|
||||
return array_filter($this->all, function (ArgDef $argDef) {
|
||||
return !$argDef->isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
function isEmpty(): bool {
|
||||
return !$this->all();
|
||||
}
|
||||
|
||||
function get(string $option): ?ArgDef {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* consommer les arguments de $src en avançant l'index $srci et provisionner
|
||||
@ -116,5 +106,7 @@ abstract class ArgDefs {
|
||||
}
|
||||
}
|
||||
|
||||
abstract function normalize(array $args): array;
|
||||
function normalize(array $args): array {
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
5
src/app/cli/ArgGroup.php
Normal file
5
src/app/cli/ArgGroup.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
class ArgGroup extends ArgDefs {
|
||||
}
|
20
src/app/cli/ArgSection.php
Normal file
20
src/app/cli/ArgSection.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
use nulib\php\types\vbool;
|
||||
|
||||
class ArgSection extends ArgDefs {
|
||||
public bool $show = true;
|
||||
public ?string $prefix = null;
|
||||
public ?string $title = null;
|
||||
public ?string $description = null;
|
||||
public ?string $suffix = null;
|
||||
|
||||
protected function parseParams(?array $params): void {
|
||||
$this->show = vbool::with($section["show"] ?? true);
|
||||
$this->prefix ??= $params["prefix"] ?? null;
|
||||
$this->title ??= $params["name"] ?? null;
|
||||
$this->description ??= $params["description"] ?? null;
|
||||
$this->suffix ??= $params["suffix"] ?? null;
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
use nulib\php\types\vbool;
|
||||
|
||||
/**
|
||||
* Class SimpleArgDefs: une définition simple des arguments et des options
|
||||
* valides d'un programme: les commandes ne sont pas supportées, ni les suites
|
||||
@ -12,38 +14,87 @@ namespace nulib\app\cli;
|
||||
* cmd1 -x // cmd2 -y n'est PAS supporté
|
||||
*/
|
||||
class SimpleArgDefs extends ArgDefs {
|
||||
function __construct(array $defs) {
|
||||
self::merge_parse_defs($this, $defs, $argDefs);
|
||||
public ?string $prefix = null;
|
||||
public ?string $name = null;
|
||||
public ?string $purpose = null;
|
||||
public ?string $usage = null;
|
||||
public ?string $description = null;
|
||||
public ?string $suffix = null;
|
||||
|
||||
# calculer les fusions
|
||||
foreach ($argDefs as $argDef) {
|
||||
/** @var ArgDef $argDef */
|
||||
$argDef->processOptions();
|
||||
}
|
||||
public ?string $commandname = null;
|
||||
public ?string $commandproperty = null;
|
||||
public ?string $commandkey = null;
|
||||
|
||||
# indexer les arguments
|
||||
$index = [];
|
||||
foreach ($argDefs as $argDef) {
|
||||
$options = $argDef->getOptions();
|
||||
foreach ($options as $option) {
|
||||
if (array_key_exists($option, $index)) {
|
||||
$index[$option]->removeOption($option);
|
||||
}
|
||||
$index[$option] = $argDef;
|
||||
}
|
||||
}
|
||||
public ?string $argsname = null;
|
||||
public ?string $argsproperty = null;
|
||||
public ?string $argskey = null;
|
||||
|
||||
foreach ($argDefs as $argDef) {
|
||||
$argDef->processArgs();
|
||||
$argDef->processAction();
|
||||
}
|
||||
public ?bool $autohelp = null;
|
||||
public ?bool $autoremains = null;
|
||||
|
||||
$this->index = $index;
|
||||
protected function parseParams(?array $params): void {
|
||||
# méta-informations
|
||||
$this->prefix ??= $params["prefix"] ?? null;
|
||||
$this->name ??= $params["name"] ?? null;
|
||||
$this->purpose ??= $params["purpose"] ?? null;
|
||||
$this->usage ??= $params["usage"] ?? null;
|
||||
$this->description ??= $params["description"] ?? null;
|
||||
$this->suffix ??= $params["suffix"] ?? null;
|
||||
|
||||
$this->commandname ??= $params["commandname"] ?? null;
|
||||
$this->commandproperty ??= $params["commandproperty"] ?? null;
|
||||
$this->commandkey ??= $params["commandkey"] ?? null;
|
||||
|
||||
$this->argsname ??= $params["argsname"] ?? null;
|
||||
$this->argsproperty ??= $params["argsproperty"] ?? null;
|
||||
$this->argskey ??= $params["argskey"] ?? null;
|
||||
|
||||
$this->autohelp ??= vbool::withn($params["autohelp"] ?? null);
|
||||
$this->autoremains ??= vbool::withn($params["autoremains"] ?? null);
|
||||
}
|
||||
|
||||
protected array $index;
|
||||
|
||||
function getArgDef(string $option): ?ArgDef {
|
||||
protected function addAll(?array $argDefs): void {
|
||||
parent::addAll($argDefs);
|
||||
$index = [];
|
||||
if ($argDefs !== null) {
|
||||
# calculer les fusions
|
||||
foreach ($argDefs as $argDef) {
|
||||
/** @var ArgDef $argDef */
|
||||
if (!$argDef->isExtends()) {
|
||||
$argDef->processOptions();
|
||||
}
|
||||
}
|
||||
foreach ($argDefs as $argDef) {
|
||||
/** @var ArgDef $argDef */
|
||||
if ($argDef->isExtends()) {
|
||||
$argDef->processExtends($this);
|
||||
}
|
||||
}
|
||||
|
||||
# indexer les arguments
|
||||
foreach ($argDefs as $argDef) {
|
||||
if ($argDef->isExtends()) continue;
|
||||
$options = $argDef->getOptions();
|
||||
foreach ($options as $option) {
|
||||
/** @var ArgDef $prevArgDef */
|
||||
$prevArgDef = $index[$option] ?? null;
|
||||
if ($prevArgDef !== null) $prevArgDef->removeOption($option);
|
||||
$index[$option] = $argDef;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($argDefs as $argDef) {
|
||||
if ($argDef->isExtends()) continue;
|
||||
$argDef->processArgs();
|
||||
$argDef->processAction();
|
||||
}
|
||||
}
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
function get(string $option): ?ArgDef {
|
||||
return $this->index[$option] ?? null;
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@ faire une implémentation SimpleArgsParser qui ne supporte pas les commandes, un
|
||||
|
||||
puis faire une implémentation ArgsParser qui supporte les commandes, et les options dynamiques
|
||||
|
||||
## WIP
|
||||
|
||||
documenter que dans les cas simples, on peut tout simplement refaire la définition, e.g
|
||||
~~~php
|
||||
[
|
||||
@ -20,4 +18,9 @@ documenter que dans les cas simples, on peut tout simplement refaire la définit
|
||||
]
|
||||
~~~
|
||||
|
||||
ajouter le support des sections, la section par défaut ayant la clé `0` (c'est
|
||||
la première section définie implicitement)
|
||||
|
||||
ajouter le support des groupes
|
||||
|
||||
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
|
@ -100,5 +100,18 @@
|
||||
valeurs séquentielles sont des clés du schéma", soit un mode automatique
|
||||
activé par un paramètre où une valeur `"val"` devient `"val"=>true` si la clé
|
||||
"val" existe dans le schéma
|
||||
* pour les schémas associatifs, support de la définition de valeurs de suite avec
|
||||
la clé "..." e.g
|
||||
~~~php
|
||||
const SCHEMA = [
|
||||
"a" => "string",
|
||||
"b" => "bool",
|
||||
"..." => "int",
|
||||
];
|
||||
# pourrait modéliser ["first", true, 1, 2, 3]
|
||||
~~~
|
||||
et on aurait alors `[[type]]` qui est équivalent à `["..." => type]`
|
||||
et donc ListSchema est un cas particulier de AssocSchema (qui pourrait être
|
||||
renommé ArraySchema)
|
||||
|
||||
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
|
@ -7,7 +7,7 @@ class ArgDefTest extends TestCase {
|
||||
protected static function assertArg(
|
||||
ArgDef $argDef,
|
||||
array $options,
|
||||
bool $haveShortOptions, bool $haveLongOptions, bool $haveCommands,
|
||||
bool $haveShortOptions, bool $haveLongOptions, bool $isCommand,
|
||||
bool $haveArgs, ?int $minArgs, ?int $maxArgs, ?string $argsdesc
|
||||
) {
|
||||
$argDef->processOptions();
|
||||
@ -16,7 +16,7 @@ class ArgDefTest extends TestCase {
|
||||
self::assertSame($options, $argDef->getOptions());
|
||||
self::assertSame($haveShortOptions, $argDef->haveShortOptions, "haveShortOptions");
|
||||
self::assertSame($haveLongOptions, $argDef->haveLongOptions, "haveLongOptions");
|
||||
self::assertSame($haveCommands, $argDef->haveCommands, "haveCommands");
|
||||
self::assertSame($isCommand, $argDef->isCommand, "isCommand");
|
||||
self::assertSame($haveArgs, $argDef->haveArgs, "haveArgs");
|
||||
self::assertSame($minArgs, $argDef->minArgs, "minArgs");
|
||||
self::assertSame($maxArgs, $argDef->maxArgs, "maxArgs");
|
||||
|
Loading…
x
Reference in New Issue
Block a user