241 lines
6.7 KiB
PHP
241 lines
6.7 KiB
PHP
|
<?php
|
||
|
namespace nur\sery\output;
|
||
|
|
||
|
use Exception;
|
||
|
use nulib\cl;
|
||
|
|
||
|
class Console implements IMessenger {
|
||
|
const VALID_LEVELS = [
|
||
|
self::LEVEL_DEBUG,
|
||
|
self::LEVEL_NORMAL,
|
||
|
self::LEVEL_MAJOR,
|
||
|
];
|
||
|
const LEVEL_MAP = [
|
||
|
"debug" => self::LEVEL_DEBUG,
|
||
|
"d" => self::LEVEL_DEBUG,
|
||
|
"normal" => self::LEVEL_NORMAL,
|
||
|
"n" => self::LEVEL_NORMAL,
|
||
|
"major" => self::LEVEL_MAJOR,
|
||
|
"m" => self::LEVEL_MAJOR,
|
||
|
];
|
||
|
|
||
|
const TYPE_PREFIXES = [
|
||
|
self::LEVEL_MAJOR => [
|
||
|
"section" => [true, "SECTION!", "===", "<color @b>= ", " =</color>", "==="],
|
||
|
"title" => ["TITLE!", null, "<color @b>T</color><color b> ", "</color>", "---"],
|
||
|
"desc" => ["DESC!", "<color @b>></color> ", ""],
|
||
|
"error" => ["CRITICAL!", "<color @r>E! ", "</color>"],
|
||
|
"warn" => ["ATTENTION!", "<color @y>W! ", "</color>"],
|
||
|
"note" => ["IMPORTANT!", "<color @g>N! ", "</color>"],
|
||
|
"info" => ["IMPORTANT!", "<color @b>I! ", "</color>"],
|
||
|
],
|
||
|
self::LEVEL_NORMAL => [
|
||
|
"section" => [true, "SECTION:", null, "<color @b>>> ", " <<</color>", "---"],
|
||
|
"title" => ["TITLE:", null, "<color @b>T</color><color b> ", "</color>", null],
|
||
|
"desc" => ["DESC:", "<color @b>></color> ", ""],
|
||
|
"error" => ["ERROR:", "<color @r>E</color><color r> ", "</color>"],
|
||
|
"warn" => ["WARN:", "<color @y>W</color><color y> ", "</color>"],
|
||
|
"note" => ["NOTE:", "<color @g>N</color> ", ""],
|
||
|
"info" => ["INFO:", "<color @b>I</color> ", ""],
|
||
|
],
|
||
|
self::LEVEL_DEBUG => [
|
||
|
"section" => [false, "s", null, "<color @w>>> ", " <<</color>", null],
|
||
|
"title" => ["t", "<color b>t ", "</color>"],
|
||
|
"desc" => [">", "<color b>></color> ", ""],
|
||
|
"error" => ["e", "<color r>e</color><color -r> ", "</color>"],
|
||
|
"warn" => ["w", "<color y>w</color><color -y> ", "</color>"],
|
||
|
"note" => ["i", "<color b>i</color> ", ""],
|
||
|
"info" => ["D", "<color @w>D</color><color w> ", "</color>"],
|
||
|
],
|
||
|
];
|
||
|
|
||
|
const RESULT_PREFIXES = [
|
||
|
"step" => ["*", "<color @w>.</color>"],
|
||
|
"failure" => ["(FAILURE)", "<color r>✘</color>"],
|
||
|
"success" => ["(SUCCESS)", "<color @g>✔</color>"],
|
||
|
"neutral" => [null, null],
|
||
|
];
|
||
|
|
||
|
function __construct(?array $params=null) {
|
||
|
$debug = boolval(cl::get($params, "debug"));
|
||
|
$minLevel = cl::get($params, "min_level");
|
||
|
if ($minLevel === null) $minLevel = $debug? self::LEVEL_DEBUG: self::LEVEL_NORMAL;
|
||
|
if (!in_array($minLevel, self::VALID_LEVELS)) {
|
||
|
$minLevel = cl::get(self::LEVEL_MAP, $minLevel, $minLevel);
|
||
|
}
|
||
|
if (!in_array($minLevel, self::VALID_LEVELS)) {
|
||
|
throw new Exception("$minLevel: invalid level");
|
||
|
}
|
||
|
|
||
|
$this->out = new StdOutput(STDOUT);
|
||
|
$this->err = new StdOutput(STDERR);
|
||
|
$this->minLevel = intval($minLevel);
|
||
|
$this->pending = [];
|
||
|
$this->inSection = false;
|
||
|
$this->titles = null;
|
||
|
$this->actions = null;
|
||
|
}
|
||
|
|
||
|
/** @var StdOutput la sortie standard */
|
||
|
protected $out;
|
||
|
|
||
|
/** @var StdOutput la sortie d'erreur */
|
||
|
protected $err;
|
||
|
|
||
|
/** @var int level minimum que doivent avoir les messages pour être affichés */
|
||
|
protected $minLevel;
|
||
|
|
||
|
/** @var bool est-on dans une section? */
|
||
|
protected $inSection;
|
||
|
|
||
|
/** @var array|string section qui est en attente d'affichage */
|
||
|
protected $section;
|
||
|
|
||
|
function section($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
$this->endSection();
|
||
|
$this->inSection = true;
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->section = $content;
|
||
|
}
|
||
|
|
||
|
protected function printSection() {
|
||
|
if ($this->section !== null) {
|
||
|
$this->section = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected function endSection(): void {
|
||
|
$this->inSection = false;
|
||
|
$this->section = null;
|
||
|
}
|
||
|
|
||
|
/** @var array */
|
||
|
protected $titles;
|
||
|
|
||
|
/** @var array */
|
||
|
protected $currentTitle;
|
||
|
|
||
|
function title($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->titles[] = [
|
||
|
"title" => $content,
|
||
|
"descs" => [],
|
||
|
"print" => true,
|
||
|
];
|
||
|
$this->currentTitle =& $this->titles[count($this->titles) - 1];
|
||
|
}
|
||
|
|
||
|
function desc($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->currentTitle["descs"][] = $content;
|
||
|
}
|
||
|
|
||
|
protected function printTitles(): void {
|
||
|
$this->printSection();
|
||
|
}
|
||
|
|
||
|
protected function endTitle(): void {
|
||
|
array_pop($this->titles);
|
||
|
if ($this->titles) {
|
||
|
$this->currentTitle =& $this->titles[count($this->titles) - 1];
|
||
|
} else {
|
||
|
unset($this->currentTitle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function print($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->printTitles();
|
||
|
$this->out->print($content);
|
||
|
}
|
||
|
|
||
|
/** @var array */
|
||
|
protected $actions;
|
||
|
|
||
|
/** @var array */
|
||
|
protected $currentAction;
|
||
|
|
||
|
function action($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
$this->actions[] = [
|
||
|
"level" => $level,
|
||
|
"contents" => [$content],
|
||
|
"result" => null,
|
||
|
"print" => true,
|
||
|
];
|
||
|
$this->currentAction =& $this->actions[count($this->actions) - 1];
|
||
|
}
|
||
|
|
||
|
function printActions(): void {
|
||
|
$this->printTitles();
|
||
|
|
||
|
}
|
||
|
|
||
|
function step($content): void {
|
||
|
$this->printActions();
|
||
|
}
|
||
|
|
||
|
function success($content=null): void {
|
||
|
$this->currentAction["contents"][] = $content;
|
||
|
$this->currentAction["result"] = true;
|
||
|
$this->printActions();
|
||
|
$this->endAction();
|
||
|
}
|
||
|
|
||
|
function failure($content=null): void {
|
||
|
$this->currentAction["contents"][] = $content;
|
||
|
$this->currentAction["result"] = false;
|
||
|
$this->printActions();
|
||
|
$this->endAction();
|
||
|
}
|
||
|
|
||
|
function neutral($content=null): void {
|
||
|
$this->currentAction["contents"][] = $content;
|
||
|
$this->currentAction["result"] = null;
|
||
|
$this->printActions();
|
||
|
$this->endAction();
|
||
|
}
|
||
|
|
||
|
protected function endAction(): void {
|
||
|
array_pop($this->actions);
|
||
|
if ($this->actions) {
|
||
|
$this->currentAction =& $this->actions[count($this->actions) - 1];
|
||
|
} else {
|
||
|
unset($this->currentAction);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function info($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->printActions();
|
||
|
}
|
||
|
|
||
|
function note($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->printActions();
|
||
|
}
|
||
|
|
||
|
function warn($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->printActions();
|
||
|
}
|
||
|
|
||
|
function error($content, int $level=self::LEVEL_NORMAL): void {
|
||
|
if ($level < $this->minLevel) return;
|
||
|
$this->printActions();
|
||
|
}
|
||
|
|
||
|
function end(bool $all=false) {
|
||
|
if ($all) {
|
||
|
while ($this->actions) $this->neutral();
|
||
|
while ($this->titles) $this->endTitle();
|
||
|
$this->endSection();
|
||
|
} elseif ($this->actions) {
|
||
|
$this->endAction();
|
||
|
} elseif ($this->titles) {
|
||
|
$this->endTitle();
|
||
|
} else {
|
||
|
$this->endSection();
|
||
|
}
|
||
|
}
|
||
|
}
|