diff --git a/libs/cli-utils/src/App.php b/libs/cli-utils/src/App.php index 5bf08bf..f44ca26 100644 --- a/libs/cli-utils/src/App.php +++ b/libs/cli-utils/src/App.php @@ -43,7 +43,9 @@ class App */ private $messages = []; - /** @var int */ + /** + * @var int + */ private $keyWidth = 12; /** @@ -61,7 +63,6 @@ public function __construct(array $argv = null) $this->script = \array_shift($argv); // parse flags [$this->args, $this->opts] = Flags::simpleParseArgv($argv); - } /** @@ -178,6 +179,10 @@ public function addCommand(string $command, callable $handler, string $descripti throw new \InvalidArgumentException('Invalid arguments'); } + if (($len = \strlen($command)) > $this->keyWidth) { + $this->keyWidth = $len; + } + $this->commands[$command] = $handler; $this->messages[$command] = \trim($description); } @@ -219,7 +224,7 @@ public function displayHelp(string $err = ''): void $help = "Welcome to the Lite Console Application.\n\nAvailable Commands:\n"; foreach ($this->messages as $command => $desc) { - $command = str_pad($command, $commandWidth, ' '); + $command = \str_pad($command, $commandWidth, ' '); $desc = $desc ?: 'No description for the command'; $help .= " $command $desc\n"; } diff --git a/libs/cli-utils/src/Cli.php b/libs/cli-utils/src/Cli.php index 54a47fd..586a82a 100644 --- a/libs/cli-utils/src/Cli.php +++ b/libs/cli-utils/src/Cli.php @@ -8,22 +8,33 @@ namespace Toolkit\Cli; +use function getenv; + /** * Class Cli * @package Toolkit\Cli */ class Cli { + public const LOG_LEVEL2TAG = [ + 'info' => 'info', + 'warn' => 'warning', + 'warning' => 'warning', + 'debug' => 'cyan', + 'notice' => 'notice', + 'error' => 'error', + ]; + /******************************************************************************* * read/write message ******************************************************************************/ /** - * @param mixed $message + * @param string $message * @param bool $nl * @return string */ - public static function read($message = null, $nl = false): string + public static function read(string $message = '', bool $nl = false): string { if ($message) { self::write($message, $nl); @@ -33,15 +44,24 @@ public static function read($message = null, $nl = false): string } /** - * write message to console - * @param $messages - * @param bool $nl - * @param bool $quit + * @param string $format + * @param mixed ...$args */ - public static function write($messages, $nl = true, $quit = false): void + public static function writef(string $format, ...$args): void + { + self::write(\sprintf($format, ...$args)); + } + + /** + * Write message to console + * @param string|array $messages + * @param bool $nl + * @param bool|int $quit + */ + public static function write($messages, bool $nl = true, $quit = false): void { if (\is_array($messages)) { - $messages = implode($nl ? \PHP_EOL : '', $messages); + $messages = \implode($nl ? \PHP_EOL : '', $messages); } self::stdout(Color::parseTag($messages), $nl, $quit); @@ -53,10 +73,10 @@ public static function write($messages, $nl = true, $quit = false): void * @param bool $nl * @param bool|int $quit */ - public static function stdout(string $message, $nl = true, $quit = false): void + public static function stdout(string $message, bool $nl = true, $quit = false): void { - fwrite(\STDOUT, $message . ($nl ? \PHP_EOL : '')); - fflush(\STDOUT); + \fwrite(\STDOUT, $message . ($nl ? \PHP_EOL : '')); + \fflush(\STDOUT); if (($isTrue = true === $quit) || \is_int($quit)) { $code = $isTrue ? 0 : $quit; @@ -72,8 +92,8 @@ public static function stdout(string $message, $nl = true, $quit = false): void */ public static function stderr(string $message, $nl = true, $quit = -1): void { - fwrite(\STDERR, self::color('[ERROR] ', 'red') . $message . ($nl ? PHP_EOL : '')); - fflush(\STDOUT); + \fwrite(\STDERR, self::color('[ERROR] ', 'red') . $message . ($nl ? PHP_EOL : '')); + \fflush(\STDOUT); if (($isTrue = true === $quit) || \is_int($quit)) { $code = $isTrue ? 0 : $quit; @@ -95,6 +115,47 @@ public static function color(string $text, $style = null): string return Color::render($text, $style); } + /** + * print log to console + * @param string $msg + * @param array $data + * @param string $type + * @param array $opts + * [ + * '_category' => 'application', + * 'process' => 'work', + * 'pid' => 234, + * 'coId' => 12, + * ] + */ + public static function log(string $msg, array $data = [], string $type = 'info', array $opts = []): void + { + if (isset(self::LOG_LEVEL2TAG[$type])) { + $type = ColorTag::add(\strtoupper($type), self::LOG_LEVEL2TAG[$type]); + } + + $userOpts = []; + + foreach ($opts as $n => $v) { + if (\is_numeric($n) || \strpos($n, '_') === 0) { + $userOpts[] = "[$v]"; + } else { + $userOpts[] = "[$n:$v]"; + } + } + + $optString = $userOpts ? ' ' . \implode(' ', $userOpts) : ''; + + self::write(\sprintf( + '%s [%s]%s %s %s', + \date('Y/m/d H:i:s'), + $type, + $optString, + \trim($msg), + $data ? \PHP_EOL . \json_encode($data, \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT) : '' + )); + } + /******************************************************************************* * some helpers ******************************************************************************/ diff --git a/libs/cli-utils/src/Color.php b/libs/cli-utils/src/Color.php index b798ba0..18246f5 100644 --- a/libs/cli-utils/src/Color.php +++ b/libs/cli-utils/src/Color.php @@ -34,6 +34,7 @@ */ class Color { + public const RESET = 0; public const NORMAL = 0; // Foreground color @@ -164,7 +165,7 @@ class Color * @param array $args * @return string */ - public static function __callStatic($method, array $args) + public static function __callStatic(string $method, array $args) { if (isset(self::STYLES[$method])) { return self::render($args[0], $method); @@ -173,12 +174,8 @@ public static function __callStatic($method, array $args) return ''; } - /******************************************************************************* - * color render - ******************************************************************************/ - /** - * apply style for text + * Apply style for text * @param string $style * @param string $text * @return string @@ -189,7 +186,21 @@ public static function apply(string $style, string $text): string } /** - * render text + * Format and print to STDOUT + * @param string $format + * @param mixed ...$args + */ + public static function printf(string $format, ...$args): void + { + echo self::render(\sprintf($format, ...$args)); + } + + /******************************************************************************* + * color render + ******************************************************************************/ + + /** + * Render text, apply color code * @param string $text * @param string|array $style * - string: 'green', 'blue' @@ -214,7 +225,7 @@ public static function render(string $text, $style = null): string $color = \implode(';', $style); // user color tag: message - } elseif (\strpos($text, '<') !== false) { + } elseif (\strpos($text, ' 0) { return self::parseTag($text); } else { return $text; @@ -240,7 +251,7 @@ public static function parseTag(string $text) return static::clearColor($text); } - if (!\preg_match_all(self::COLOR_TAG, $text, $matches)) { + if (!\preg_match_all(ColorTag::MATCH_TAG, $text, $matches)) { return $text; } diff --git a/libs/cli-utils/src/ColorTag.php b/libs/cli-utils/src/ColorTag.php index 73b389e..ed10cc5 100644 --- a/libs/cli-utils/src/ColorTag.php +++ b/libs/cli-utils/src/ColorTag.php @@ -15,14 +15,15 @@ class ColorTag { // regex used for removing color tags - private const STRIP_TAG = '/<[\/]?[a-zA-Z=;]+>/'; + public const STRIP_TAG = '/<[\/]?[a-zA-Z=;]+>/'; // Regex to match tags/ - private const COLOR_TAG = '/<([a-zA-Z=;]+)>(.*?)<\/\\1>/s'; + public const MATCH_TAG = '/<([a-zA-Z=;_]+)>(.*?)<\/\\1>/s'; /** - * alias of the wrap() + * Alias of the wrap() * @param string $text + * @param string $tag * @return string */ public static function add(string $text, string $tag): string @@ -51,7 +52,7 @@ public static function wrap(string $text, string $tag): string */ public static function matchAll(string $text): array { - if (!\preg_match_all(self::COLOR_TAG, $text, $matches)) { + if (!\preg_match_all(self::MATCH_TAG, $text, $matches)) { return []; } @@ -64,17 +65,17 @@ public static function parse(string $text): string } /** - * exists color tags + * Exists color tags * @param string $text * @return bool */ public static function exists(string $text): bool { - return false !== \strpos($text, ' 0; } /** - * alias of the strip() + * Alias of the strip() * @param string $text * @return string */ diff --git a/libs/cli-utils/src/Console.php b/libs/cli-utils/src/Console.php deleted file mode 100644 index e7d2ccf..0000000 --- a/libs/cli-utils/src/Console.php +++ /dev/null @@ -1,66 +0,0 @@ - 'info', - 'warn' => 'warning', - 'warning' => 'warning', - 'debug' => 'cyan', - 'notice' => 'notice', - 'error' => 'error', - ]; - - /** - * print log to console - * @param string $msg - * @param array $data - * @param string $type - * @param array $opts - * [ - * '_category' => 'application', - * 'process' => 'work', - * 'pid' => 234, - * 'coId' => 12, - * ] - */ - public static function log(string $msg, array $data = [], string $type = 'info', array $opts = []): void - { - if (isset(self::LOG_LEVEL2TAG[$type])) { - $type = ColorTag::add(\strtoupper($type), self::LOG_LEVEL2TAG[$type]); - } - - $userOpts = []; - - foreach ($opts as $n => $v) { - if (\is_numeric($n) || \strpos($n, '_') === 0) { - $userOpts[] = "[$v]"; - } else { - $userOpts[] = "[$n:$v]"; - } - } - - $optString = $userOpts ? ' ' . \implode(' ', $userOpts) : ''; - - Cli::write(\sprintf( - '%s [%s]%s %s %s', - \date('Y/m/d H:i:s'), - $type, - $optString, - \trim($msg), - $data ? \PHP_EOL . \json_encode($data, \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT) : '' - )); - } -} diff --git a/libs/cli-utils/test/ColorTagTest.php b/libs/cli-utils/test/ColorTagTest.php index 1eaec14..51fd608 100644 --- a/libs/cli-utils/test/ColorTagTest.php +++ b/libs/cli-utils/test/ColorTagTest.php @@ -20,13 +20,26 @@ class ColorTagTest extends TestCase public function testMatchAll(): void { $ret = ColorTag::matchAll('text0 or text1'); - $this->assertCount(3, $ret); // tag $this->assertSame('tag', $ret[1][0]); $this->assertSame('info', $ret[1][1]); // content $this->assertSame('text0', $ret[2][0]); + + $ret = ColorTag::matchAll('text'); + $this->assertCount(3, $ret); + // tag + $this->assertSame('some_tag', $ret[1][0]); + // content + $this->assertSame('text', $ret[2][0]); + + $ret = ColorTag::matchAll('text'); + $this->assertCount(3, $ret); + // tag + $this->assertSame('someTag', $ret[1][0]); + // content + $this->assertSame('text', $ret[2][0]); } public function testStrip(): void diff --git a/libs/cli-utils/test/ColorTest.php b/libs/cli-utils/test/ColorTest.php new file mode 100644 index 0000000..d9fa986 --- /dev/null +++ b/libs/cli-utils/test/ColorTest.php @@ -0,0 +1,42 @@ +assertStringContainsString(Color::STYLES['info'], $text); + + $text = Color::render('text', [Color::RESET, Color::FG_CYAN]); + $this->assertStringContainsString(Color::STYLES['cyan'], $text); + + $text = Color::render('text'); + $this->assertStringContainsString(Color::STYLES['info'], $text); + + $text = Color::render('text'); + $this->assertStringContainsString(Color::STYLES['light_blue'], $text); + + $text = Color::render('text'); + $this->assertStringContainsString(Color::STYLES['lightBlue'], $text); + } + + public function testApply(): void + { + $text = Color::apply('info', 'text'); + $this->assertStringContainsString(Color::STYLES['info'], $text); + + foreach (Color::STYLES as $name => $code) { + $text = Color::apply($name, 'text'); + $this->assertStringContainsString($code, $text); + } + } +}