diff --git a/src/output/IMessenger.php b/src/output/IMessenger.php index aeceae9..3110317 100644 --- a/src/output/IMessenger.php +++ b/src/output/IMessenger.php @@ -5,8 +5,8 @@ namespace nur\sery\output; * Interface IMessenger: un objet pouvant afficher des messages de l'application */ interface IMessenger { - const LEVEL_DEBUG = -1, LEVEL_NORMAL = 0, LEVEL_MAJOR = 1, LEVEL_NONE = 2; - const MIN_LEVEL = self::LEVEL_DEBUG, MAX_LEVEL = self::LEVEL_MAJOR; + const DEBUG = -1, NORMAL = 0, MAJOR = 1, NONE = 2; + const MIN_LEVEL = self::DEBUG, MAX_LEVEL = self::MAJOR; /** réinitialiser les paramètres de l'objet */ function resetParams(?array $params=null): void; @@ -22,7 +22,7 @@ interface IMessenger { * flush tous les messages en cours. ne peut être imbriqué. on peut considérer * que c'est une sorte de "reset" de l'objet */ - function section($content, ?int $level=null): void; + function section($content, ?callable $func=null, ?int $level=null): void; /** * commencer un chapitre. @@ -30,7 +30,7 @@ interface IMessenger { * peut être imbriqué dans un autre chapitre. terminer automatiquement * l'action en cours avec un résultat neutre */ - function title($content, ?int $level=null): void; + function title($content, ?callable $func=null, ?int $level=null): void; /** ajouter une description au chapitre courant. */ function desc($content, ?int $level=null): void; @@ -40,7 +40,7 @@ interface IMessenger { * * peut être imbriqué dans une autre action. */ - function action($content, ?int $level=null): void; + function action($content, ?callable $func=null, ?int $level=null): void; /** * ajouter une étape à l'action courante. diff --git a/src/output/TODO.md b/src/output/TODO.md index 059a71d..59913e2 100644 --- a/src/output/TODO.md +++ b/src/output/TODO.md @@ -1,127 +1,8 @@ -# IMessenger +# TOOD -## TOOD - -* [ ] section(), title() et action() acceptent une fonction qui fait le travail - avec en premier argument l'instance de messenger, et qui termine l'objet - l'objet ensuite * [ ] possibilité de paramétrer le nom du fichier destination pour faire une rotation des logs -* [ ] support quiet (uniquement major), very-quiet (aucun message n'est affiché) * [ ] support verbose? cela suppose rajouter un niveau supplémentaire `LEVEL_MINOR` entre `LEVEL_DEBUG` et `LEVEL_NORMAL` -## Principe - -* 3 niveaux: DEBUG, NORMAL, MAJOR -* plusieurs types de messages: - * section: flush tous les messages en cours, ne peut pas être imbriqué - * title: début d'une action de haut niveau, peut être imbriqué - * desc: description longue de l'action de haut niveau qui vient de démarrer - * print: donnée non structurée - * action: début d'une action, peut être imbriqué - * step: étape d'une action - * success: résultat: action réussie - * failure: résultat: action ratée - * info: événement: pour information - * note: événement: information importante - * warn: événement: avertissement - * error: événement: erreur - * end: fin de action ou title -* section, title et desc ne sont affichés que si une action ou un événement est affiché en-dessous -* quand on "rajoute" une desc, décider s'il faut remplacer la description en cours pas encore affichée, ou s'il faut simplement le rajouter à la suite - - -visuellement: -* debug - ~~~ - >> section << - t title - > desc - print - . action: - . step - v action success - . action: - . step - x action failure - v action success - x action failure - . action0: - . action1: - ? action2 result - ? action1 result - ? action0 result - i info - w warn - e error - t title0 - t title1 - print under title1 - print under title0 - ~~~ - result est soit success, soit failure.. -* normal - ~~~ - - >>> section <<< - >>> ------- <<< - T title - > desc - print - . action: - . step - V action success - . action: - . step - X action failure - V action success - X action failure - . action0: - . action1: - ? action2 result - ? action1 result - ? action0 result - I info - W warn - E error - T title0 - T title1 - print under title1 - print under title0 - ~~~ -* major - ~~~ - - =========== - = section = - =========== - title - ------- - > desc - print - . action: - . step - V action success - . action: - . step - X action failure - V action success - X action failure - . action0: - . action1: - ? action2 result - ? action1 result - ? action0 result - NOTE: info - ATTENTION: warn - CRITICAL: error - title0 - -------- - title1 - -------- - print under title1 - print under title0 - ~~~ - -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file diff --git a/src/output/_messenger.php b/src/output/_messenger.php index 44520b1..4cd24ab 100644 --- a/src/output/_messenger.php +++ b/src/output/_messenger.php @@ -65,16 +65,16 @@ abstract class _messenger { ############################################################################# - const DEBUG = IMessenger::LEVEL_DEBUG; - const NORMAL = IMessenger::LEVEL_NORMAL; - const MAJOR = IMessenger::LEVEL_MAJOR; - const NONE = IMessenger::LEVEL_NONE; + const DEBUG = IMessenger::DEBUG; + const NORMAL = IMessenger::NORMAL; + const MAJOR = IMessenger::MAJOR; + const NONE = IMessenger::NONE; static function reset_params(?array $params=null): void { static::get()->resetParams($params); } - static function section($content, ?int $level=null): void { static::get()->section($content, $level); } - static function title($content, ?int $level=null): void { static::get()->title($content, $level); } + static function section($content, ?callable $func=null, ?int $level=null): void { static::get()->section($content, $func, $level); } + static function title($content, ?callable $func=null, ?int $level=null): void { static::get()->title($content, $func, $level); } static function desc($content, ?int $level=null): void { static::get()->desc($content, $level); } - static function action($content, ?int $level=null): void { static::get()->action($content, $level); } + static function action($content, ?callable $func=null, ?int $level=null): void { static::get()->action($content, $func, $level); } static function step($content, ?int $level=null): void { static::get()->step($content, $level); } static function asuccess($content=null): void { static::get()->asuccess($content); } static function afailure($content=null): void { static::get()->afailure($content); } diff --git a/src/output/std/ProxyMessenger.php b/src/output/std/ProxyMessenger.php index cddf2c6..2950a06 100644 --- a/src/output/std/ProxyMessenger.php +++ b/src/output/std/ProxyMessenger.php @@ -25,10 +25,10 @@ class ProxyMessenger implements IMessenger { }; unset($msg); return $clone; } - function section($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->section($content, $level); } } - function title($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->title($content, $level); } } + function section($content, ?callable $func=null, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->section($content, $func, $level); } } + function title($content, ?callable $func=null, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->title($content, $func, $level); } } function desc($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->desc($content, $level); } } - function action($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->action($content, $level); } } + function action($content, ?callable $func=null, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->action($content, $func, $level); } } function step($content, ?int $level=null): void { foreach ($this->msgs as $msg) { $msg->step($content, $level); } } function asuccess($content=null): void { foreach ($this->msgs as $msg) { $msg->asuccess($content); } } function afailure($content=null): void { foreach ($this->msgs as $msg) { $msg->afailure($content); } } diff --git a/src/output/std/StdMessenger.php b/src/output/std/StdMessenger.php index 3bf925b..cd577c9 100644 --- a/src/output/std/StdMessenger.php +++ b/src/output/std/StdMessenger.php @@ -13,16 +13,16 @@ class StdMessenger implements IMessenger { const DATE_FORMAT = 'Y-m-d\TH:i:s.u'; const VALID_LEVELS = [ - self::LEVEL_DEBUG, - self::LEVEL_NORMAL, - self::LEVEL_MAJOR, - self::LEVEL_NONE, + self::DEBUG, + self::NORMAL, + self::MAJOR, + self::NONE, ]; const LEVEL_MAP = [ - "debug" => self::LEVEL_DEBUG, "verbose" => self::LEVEL_DEBUG, - "normal" => self::LEVEL_NORMAL, - "major" => self::LEVEL_MAJOR, "quiet" => self::LEVEL_MAJOR, - "none" => self::LEVEL_NONE, "silent" => self::LEVEL_NONE, + "debug" => self::DEBUG, "verbose" => self::DEBUG, + "normal" => self::NORMAL, + "major" => self::MAJOR, "quiet" => self::MAJOR, + "none" => self::NONE, "silent" => self::NONE, ]; protected static function decr_level(int $level): int { @@ -44,7 +44,7 @@ class StdMessenger implements IMessenger { } const GENERIC_PREFIXES = [ - self::LEVEL_MAJOR => [ + self::MAJOR => [ "section" => [true, "SECTION!", "===", "=", "=", "==="], "title" => [false, "TITLE!", null, "T", "", "==="], "desc" => ["DESC!", ">", ""], @@ -55,7 +55,7 @@ class StdMessenger implements IMessenger { "step" => ["*", ".", ""], "print" => [null, null, null], ], - self::LEVEL_NORMAL => [ + self::NORMAL => [ "section" => [true, "SECTION:", "---", "-", "-", "---"], "title" => [false, "TITLE:", null, "T", "", "---"], "desc" => ["DESC:", ">", ""], @@ -66,7 +66,7 @@ class StdMessenger implements IMessenger { "step" => ["*", ".", ""], "print" => [null, null, null], ], - self::LEVEL_DEBUG => [ + self::DEBUG => [ "section" => [true, "section", null, ">>", "<<", null], "title" => [false, "title", null, "t", "", null], "desc" => ["desc", ">", ""], @@ -91,15 +91,15 @@ class StdMessenger implements IMessenger { $indent = cl::get($params, "indent", static::INDENT); $defaultLevel = cl::get($params, "default_level"); - if ($defaultLevel === null) $defaultLevel = self::LEVEL_NORMAL; + if ($defaultLevel === null) $defaultLevel = self::NORMAL; $defaultLevel = self::verifix_level($defaultLevel); $debug = boolval(cl::get($params, "debug")); $minLevel = cl::get($params, "min_level"); - if ($minLevel === null && $debug) $minLevel = self::LEVEL_DEBUG; + if ($minLevel === null && $debug) $minLevel = self::DEBUG; if ($minLevel === null) $minLevel = cl::get($params, "verbosity"); # alias - if ($minLevel === null) $minLevel = self::LEVEL_NORMAL; - $minLevel = self::verifix_level($minLevel, self::LEVEL_NONE); + if ($minLevel === null) $minLevel = self::NORMAL; + $minLevel = self::verifix_level($minLevel, self::NONE); $addDate = boolval(cl::get($params, "add_date")); $dateFormat = cl::get($params, "date_format", static::DATE_FORMAT); @@ -135,9 +135,9 @@ class StdMessenger implements IMessenger { $debug = cl::get($params, "debug"); $minLevel = cl::get($params, "min_level"); - if ($minLevel === null && $debug !== null) $minLevel = $debug? self::LEVEL_DEBUG: self::LEVEL_NORMAL; + if ($minLevel === null && $debug !== null) $minLevel = $debug? self::DEBUG: self::NORMAL; if ($minLevel === null) $minLevel = cl::get($params, "verbosity"); # alias - if ($minLevel !== null) $minLevel = self::verifix_level($minLevel, self::LEVEL_NONE); + if ($minLevel !== null) $minLevel = self::verifix_level($minLevel, self::NONE); $addDate = cl::get($params, "add_date"); $dateFormat = cl::get($params, "date_format"); @@ -424,7 +424,7 @@ class StdMessenger implements IMessenger { /** @var array section qui est en attente d'affichage */ protected $section; - function section($content, ?int $level=null): void { + function section($content, ?callable $func=null, ?int $level=null): void { $this->endSection(); $this->inSection = true; if (!$this->checkLevel($level)) return; @@ -434,6 +434,13 @@ class StdMessenger implements IMessenger { "content" => $content, "print_content" => true, ]; + if ($func !== null) { + try { + $func($this); + } finally { + $this->endSection(); + } + } } protected function printSection() { @@ -458,8 +465,9 @@ class StdMessenger implements IMessenger { /** @var array */ protected $title; - function title($content, ?int $level=null): void { + function title($content, ?callable $func=null, ?int $level=null): void { if (!$this->checkLevel($level)) return; + $until = count($this->titles); $this->titles[] = [ "line_prefix" => $this->getLinePrefix(), "level" => $level, @@ -469,6 +477,13 @@ class StdMessenger implements IMessenger { "print_descs" => false, ]; $this->title =& $this->titles[count($this->titles) - 1]; + if ($func !== null) { + try { + $func($this); + } finally { + $this->endTitle($until); + } + } } function desc($content, ?int $level=null): void { @@ -508,8 +523,11 @@ class StdMessenger implements IMessenger { }; unset($title); } - protected function endTitle(): void { - array_pop($this->titles); + protected function endTitle(?int $until=null): void { + if ($until === null) $until = count($this->titles) - 1; + while (count($this->titles) > $until) { + array_pop($this->titles); + } if ($this->titles) { $this->title =& $this->titles[count($this->titles) - 1]; } else { @@ -524,8 +542,9 @@ class StdMessenger implements IMessenger { /** @var array */ protected $action; - function action($content, ?int $level=null): void { + function action($content, ?callable $func=null, ?int $level=null): void { $this->checkLevel($level); + $until = count($this->actions); $this->actions[] = [ "line_prefix" => $this->getLinePrefix(), "level" => $level, @@ -535,6 +554,18 @@ class StdMessenger implements IMessenger { "result_content" => null, ]; $this->action =& $this->actions[count($this->actions) - 1]; + if ($func !== null) { + try { + $result = $func($this); + if ($result !== null) { + if ($result === true) $this->asuccess(); + elseif ($result === false) $this->afailure(); + else $this->adone($result); + } + } finally { + $this->endAction($until); + } + } } function printActions(bool $willEnd=false): void { @@ -597,8 +628,11 @@ class StdMessenger implements IMessenger { $this->endAction(); } - protected function endAction(): void { - array_pop($this->actions); + protected function endAction(?int $until=null): void { + if ($until === null) $until = count($this->actions) - 1; + while (count($this->actions) > $until) { + array_pop($this->actions); + } if ($this->actions) { $this->action =& $this->actions[count($this->actions) - 1]; } else { diff --git a/tbin/test-console.php b/tbin/test-console.php index 248f4b2..8a522d6 100755 --- a/tbin/test-console.php +++ b/tbin/test-console.php @@ -44,116 +44,246 @@ for ($i = 1; $i <= $count; $i++) { break; } } -$c = new StdMessenger($params); +$msg = new StdMessenger($params); -$c->section("section"); +$msg->title("title0"); +$msg->title("title1"); +$msg->print("print under title1"); +$msg->end(); +$msg->print("print under title0"); +$msg->end(); -$c->title("title"); -$c->desc("desc"); -$c->print("print"); +$msg->desc("action avec step"); +$msg->action("action avec step"); +$msg->step("step"); +$msg->asuccess("action success"); -$c->action("action"); -$c->step("step"); -$c->asuccess("action success"); +$msg->action("action avec step"); +$msg->step("step"); +$msg->afailure("action failure"); -$c->action("action"); -$c->step("step"); -$c->afailure("action failure"); +$msg->action("action avec step"); +$msg->step("step"); +$msg->adone("action neutral"); -$c->action("action"); -$c->step("step"); -$c->adone("action neutral"); +$msg->desc("actions sans step"); +$msg->action("action sans step"); +$msg->asuccess("action success"); -$c->action("action"); -$c->asuccess("action success"); +$msg->action("action sans step"); +$msg->afailure("action failure"); -$c->action("action"); -$c->afailure("action failure"); +$msg->action("action sans step"); +$msg->adone("action neutral"); -$c->action("action"); -$c->adone("action neutral"); +$msg->desc("actions imbriquées"); +$msg->action("action0"); +$msg->action("action1"); +$msg->action("action2"); +$msg->asuccess("action2 success"); +$msg->asuccess("action1 success"); +$msg->asuccess("action0 success"); -$c->action("action0"); -$c->action("action1"); -$c->action("action2"); -$c->asuccess("action2 success"); -$c->asuccess("action1 success"); -$c->asuccess("action0 success"); +$msg->desc("action avec step, sans messages"); +$msg->action("action avec step, sans messages, success"); +$msg->step("step"); +$msg->asuccess(); -$c->action("action"); -$c->step("step"); -$c->asuccess(); +$msg->action("action avec step, sans messages, failure"); +$msg->step("step"); +$msg->afailure(); -$c->action("action"); -$c->step("step"); -$c->afailure(); +$msg->action("action avec step, sans messages, done"); +$msg->step("step"); +$msg->adone(); -$c->action("action"); -$c->step("step"); -$c->adone(); +$msg->desc("action sans step, sans messages"); +$msg->action("action sans step, sans messages, success"); +$msg->asuccess(); -$c->action("action"); -$c->asuccess(); +$msg->action("action sans step, sans messages, failure"); +$msg->afailure(); -$c->action("action"); -$c->afailure(); +$msg->action("action sans step, sans messages, done"); +$msg->adone(); -$c->action("action"); -$c->adone(); +$msg->desc("actions imbriquées, sans messages"); +$msg->action("action0"); +$msg->action("action1"); +$msg->action("action2"); +$msg->asuccess(); +$msg->asuccess(); +$msg->asuccess(); -$c->action("action0"); -$c->action("action1"); -$c->action("action2"); -$c->asuccess(); -$c->asuccess(); -$c->asuccess(); +$msg->info("info"); +$msg->note("note"); +$msg->warn("warn"); +$msg->error("error"); -$c->info("info"); -$c->note("note"); -$c->warn("warn"); -$c->error("error"); +$msg->section("section", function ($msg) { + $msg->title("title", function ($msg) { + $msg->desc("desc"); + $msg->print("print"); -$c->end(); + $msg->desc("action avec step"); + $msg->action("action avec step", function ($msg) { + $msg->step("step"); + $msg->asuccess("action success"); + }); -$c->title("title0"); -$c->title("title1"); -$c->print("print under title1"); -$c->end(); -$c->print("print under title0"); -$c->end(); + $msg->action("action avec step", function ($msg) { + $msg->step("step"); + $msg->afailure("action failure"); + }); -$c->end(true); + $msg->action("action avec step", function ($msg) { + $msg->step("step"); + $msg->adone("action done"); + }); -$c->section("multi-line\nsection"); -$c->title("multi-line\ntitle"); -$c->title("another\ntitle"); -$c->print("multi-line\nprint"); -$c->info("multi-line\ninfo"); -$c->action("multi-line\naction"); -$c->asuccess(); -$c->action("multi-line\naction"); -$c->step("multi-line\nstep"); -$c->afailure(); -$c->action("multi-line\naction"); -$c->step("multi-line\nstep"); -$c->asuccess("multi-line\nsuccess"); -$c->action("multi-line\naction"); -$c->step("multi-line\nstep"); -$c->adone("multi-line\ndone"); -$c->end(true); + $msg->desc("actions sans step"); + $msg->action("action sans step", function ($msg) { + $msg->asuccess("action success"); + }); -$exception = new Exception("message"); -$userException1 = new UserException("userMessage"); -$userException2 = new UserException("userMessage", "techMessage"); -$c->section("Exceptions"); -$c->title("avec message"); -$c->info(["exception", $exception]); -$c->info(["userException1", $userException1]); -$c->info(["userException2", $userException2]); -$c->end(); + $msg->action("action sans step", function ($msg) { + $msg->afailure("action failure"); + }); + + $msg->action("action sans step", function ($msg) { + $msg->adone("action done"); + }); + + $msg->desc("actions imbriquées"); + $msg->action("action0", function ($msg) { + $msg->action("action1", function ($msg) { + $msg->action("action2", function ($msg) { + $msg->asuccess("action2 success"); + }); + $msg->asuccess("action1 success"); + }); + $msg->asuccess("action0 success"); + }); + + $msg->desc("action avec step, sans messages"); + $msg->action("action avec step, sans messages, success", function ($msg) { + $msg->step("step"); + $msg->asuccess(); + }); + + $msg->action("action avec step, sans messages, failure", function ($msg) { + $msg->step("step"); + $msg->afailure(); + }); + + $msg->action("action avec step, sans messages, done", function ($msg) { + $msg->step("step"); + $msg->adone(); + }); + + $msg->desc("action sans step, sans messages"); + $msg->action("action sans step, sans messages, success", function ($msg) { + $msg->asuccess(); + }); + + $msg->action("action sans step, sans messages, failure", function ($msg) { + $msg->afailure(); + }); + + $msg->action("action sans step, sans messages, done", function ($msg) { + $msg->adone(); + }); + + $msg->desc("actions imbriquées, sans messages"); + $msg->action("action0", function ($msg) { + $msg->action("action1", function ($msg) { + $msg->action("action2", function ($msg) { + $msg->asuccess(); + }); + $msg->asuccess(); + }); + $msg->asuccess(); + }); + + $msg->desc("action avec step, avec code de retour"); + $msg->action("action avec step, avec code de retour true", function ($msg) { + $msg->step("step"); + return true; + }); + + $msg->action("action avec step, avec code de retour false", function ($msg) { + $msg->step("step"); + return false; + }); + + $msg->action("action avec step, avec code de retour autre", function ($msg) { + $msg->step("step"); + return "autre"; + }); + + $msg->action("action avec step, avec code de retour null", function ($msg) { + $msg->step("step"); + }); + + $msg->desc("action sans step, avec code de retour"); + $msg->action("action sans step, avec code de retour true", function ($msg) { + return true; + }); + + $msg->action("action sans step, avec code de retour false", function ($msg) { + return false; + }); + + $msg->action("action sans step, avec code de retour autre", function ($msg) { + return "autre"; + }); + + # ici, il n'y aura pas de message du tout + $msg->action("action sans step, avec code de retour null", function ($msg) { + }); + + $msg->info("info"); + $msg->note("note"); + $msg->warn("warn"); + $msg->error("error"); + }); +}); + +$msg->section("multi-line\nsection", function ($msg) { + $msg->title("multi-line\ntitle"); + $msg->title("another\ntitle"); + + $msg->print("multi-line\nprint"); + $msg->info("multi-line\ninfo"); + $msg->action("multi-line\naction"); + $msg->asuccess(); + $msg->action("multi-line\naction"); + $msg->step("multi-line\nstep"); + $msg->afailure(); + $msg->action("multi-line\naction"); + $msg->step("multi-line\nstep"); + $msg->asuccess("multi-line\nsuccess"); + $msg->action("multi-line\naction"); + $msg->step("multi-line\nstep"); + $msg->adone("multi-line\ndone"); + + $msg->end(); + $msg->end(); +}); + +$msg->section("Exceptions", function ($msg) { + $e = new Exception("message"); + $u1 = new UserException("userMessage"); + $u2 = new UserException("userMessage", "techMessage"); + $msg->title("avec message", function ($msg) use ($e, $u1, $u2) { + $msg->info(["exception", $e]); + $msg->info(["userException1", $u1]); + $msg->info(["userException2", $u2]); + }); + $msg->title("sans message", function ($msg) use ($e, $u1, $u2) { + $msg->info($e); + $msg->info($u1); + $msg->info($u2); + }); +}); -$c->title("sans message"); -$c->info($exception); -$c->info($userException1); -$c->info($userException2); -$c->end();