- Added color / formats management

This commit is contained in:
mcndave committed 2024-10-31 10:33:00 -04:00
1 parent d503628356
commit 32d5079559
11 files changed
+297 -2

No files matched your search

+95
View File
@@ -0,0 +1,95 @@
<?php
namespace Mcnd\CLI\Lib;
class AsciiFormatter
{
public array $stack = [];
protected string $latest;
public function parse(array|string $content) : array|string
{
return is_array($content) ? array_map([ $this, 'parseContent' ], $content) : $this->parseContent($content);
}
protected function parseContent(string $text) : string
{
if (str_contains($text, '#[')) {
# Opening 'tag'
$text = preg_replace_callback("#(\#\[)(.*?)(\])#s", function ($matches) {
if ( empty($stack) ) {
$this->stack[] = $this->translateFormat("c:default, bg:default, f:normal");
}
else {
$this->stack[] = $this->latest;
}
$this->latest = $this->translateFormat($matches[2]);
return $this->latest;
}, $text);
# Closing 'tag'
$text = preg_replace_callback("#(\[\#\])#s", function ($matches) {
$close = $this->stack ? array_pop($this->stack) : "";
return $close;
}, $text);
}
return $text;
}
protected function translateFormat(string $source) : string
{
$valueType =
$color = $background = $format = null;
foreach(array_map(fn($e) => trim(strtolower($e)), explode(',', $source)) as $formatting) {
if ( ! strstr($formatting, ':' )) {
throw new \InvalidArgumentException(
sprintf("Arguments must be called with their variable's name (%s)", $formatting)
);
}
list($scope, $value) = explode(':', $formatting, 2);
switch($scope) {
case 'color':
case 'c':
$type = ValueTypeEnum::autodetect($value);
if ($type === ValueTypeEnum::Ascii16) {
$color = ColorEnum::mapFrom($value);
}
elseif ($type === ValueTypeEnum::Ascii256) {
$color = RgbColor::mapFrom($value);
}
break;
case 'background':
case 'bg':
case 'b':
$type = ValueTypeEnum::autodetect($value);
if ($type === ValueTypeEnum::Ascii16) {
$background = BackgroundColorEnum::mapFrom($value);
}
elseif ($type === ValueTypeEnum::Ascii256) {
$background = RgbBackground::mapFrom($value);
}
break;
case 'format':
case 'f':
$format = FormatEnum::mapFrom($value);
break;
}
}
return ($color ? $color->output() : "") . ($background ? $background->output() : "") . ($format ? $format->output() : "");
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace Mcnd\CLI\Lib;
enum BackgroundColorEnum : string
{
use ColorMappingTrait;
case Default = "49";
case Black = "40";
case Red = "41";
case Green = "42";
case Yellow = "43";
case Blue = "44";
case Magenta = "45";
case Cyan = "46";
case LightGray = "47";
case DarkGray = "100";
case LightRed = "101";
case LightGreen = "102";
case LightYellow = "103";
case LightBlue = "104";
case LightMagenta = "105";
case LightCyan = "106";
case White = "107";
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace Mcnd\CLI\Lib;
enum ColorEnum : string
{
use ColorMappingTrait;
case Default = "39";
case Black = "30";
case Red = "31";
case Green = "32";
case Yellow = "33";
case Blue = "34";
case Magenta = "35";
case Cyan = "36";
case LightGray = "37";
case DarkGray = "90";
case LightRed = "91";
case LightGreen = "92";
case LightYellow = "93";
case LightBlue = "94";
case LightMagenta = "95";
case LightCyan = "96";
case White = "97";
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Mcnd\CLI\Lib;
trait ColorMappingTrait
{
public static function mapFrom(string $name) : ? self
{
return [
'black' => self::Black,
'red' => self::Red,
'green' => self::Green,
'yellow' => self::Yellow,
'blue' => self::Blue,
'magenta' => self::Magenta,
'cyan' => self::Cyan,
'lightgray' => self::LightGray,
'darkgray' => self::DarkGray,
'lightred' => self::LightRed,
'lightgreen' => self::LightGreen,
'lightyellow' => self::LightYellow,
'lightblue' => self::LightBlue,
'lightmagenta' => self::LightMagenta,
'lightcyan' => self::LightCyan,
'white' => self::White,
][$name] ?? null;
}
public function output() : string
{
return "\e[{$this->value}m";
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace Mcnd\CLI\Lib;
enum FormatEnum : string
{
case Normal = "0";
case Bold = "1";
case Dim = "2";
case Italic = "3";
case Underlined = "4";
case Blinking = "5";
case Reverse = "7";
case Invisible = "8";
public static function mapFrom(string $name): ?self
{
return [
'n' => self::Normal,
'normal' => self::Normal,
'b' => self::Bold,
'bold' => self::Bold,
'd' => self::Dim,
'dim' => self::Dim,
'i' => self::Italic,
'italic' => self::Italic,
'u' => self::Underlined,
'underlined' => self::Underlined,
'blinking' => self::Blinking,
'reverse' => self::Reverse,
'invisible' => self::Invisible,
][$name] ?? null;
}
public function output() : string
{
return "\e[{$this->value}m";
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace Mcnd\CLI\Lib;
class RgbBackground extends RgbColor
{
public function output() : string
{
return "\033[48;2;{$this->rgb}m";
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace Mcnd\CLI\Lib;
class RgbColor
{
public readonly string $rgb;
public function __construct(int $red, int $green, int $blue)
{
$this->rgb = "$red;$green;$blue";
}
public static function mapFrom(string $value) : ? self
{
$begin = strpos($value, 'rgb(') + 4;
$end = strrpos($value, ')');
$rgb = substr($value, $begin, $end - $begin);
return new static(...explode(';', $rgb));
}
public function output() : string
{
return "\033[38;2;{$this->rgb}m";
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace Mcnd\CLI\Lib;
enum ValueTypeEnum
{
case NoColors;
case Ascii16;
case Ascii256;
public static function autodetect(string $value) : self
{
if ( substr($value, 0, 4) === 'rgb(' ) {
if (! strstr($value, ')')) {
throw new \InvalidArgumentException(
sprintf("An unclosed parenthesis was found for 'rgb' color %s", $value)
);
}
return self::Ascii256;
}
elseif ( ColorEnum::mapFrom($value) !== null || BackgroundColorEnum::mapFrom($value) ) {
return self::Ascii16;
}
return self::NoColors;
}
}