37    public static string $FORMAT_BOLD = 
"";
 
   38    public static string $FORMAT_OBFUSCATED = 
"";
 
   39    public static string $FORMAT_ITALIC = 
"";
 
   40    public static string $FORMAT_UNDERLINE = 
"";
 
   41    public static string $FORMAT_STRIKETHROUGH = 
"";
 
   43    public static string $FORMAT_RESET = 
"";
 
   45    public static string $COLOR_BLACK = 
"";
 
   46    public static string $COLOR_DARK_BLUE = 
"";
 
   47    public static string $COLOR_DARK_GREEN = 
"";
 
   48    public static string $COLOR_DARK_AQUA = 
"";
 
   49    public static string $COLOR_DARK_RED = 
"";
 
   50    public static string $COLOR_PURPLE = 
"";
 
   51    public static string $COLOR_GOLD = 
"";
 
   52    public static string $COLOR_GRAY = 
"";
 
   53    public static string $COLOR_DARK_GRAY = 
"";
 
   54    public static string $COLOR_BLUE = 
"";
 
   55    public static string $COLOR_GREEN = 
"";
 
   56    public static string $COLOR_AQUA = 
"";
 
   57    public static string $COLOR_RED = 
"";
 
   58    public static string $COLOR_LIGHT_PURPLE = 
"";
 
   59    public static string $COLOR_YELLOW = 
"";
 
   60    public static string $COLOR_WHITE = 
"";
 
   61    public static string $COLOR_MINECOIN_GOLD = 
"";
 
   62    public static string $COLOR_MATERIAL_QUARTZ = 
"";
 
   63    public static string $COLOR_MATERIAL_IRON = 
"";
 
   64    public static string $COLOR_MATERIAL_NETHERITE = 
"";
 
   65    public static string $COLOR_MATERIAL_REDSTONE = 
"";
 
   66    public static string $COLOR_MATERIAL_COPPER = 
"";
 
   67    public static string $COLOR_MATERIAL_GOLD = 
"";
 
   68    public static string $COLOR_MATERIAL_EMERALD = 
"";
 
   69    public static string $COLOR_MATERIAL_DIAMOND = 
"";
 
   70    public static string $COLOR_MATERIAL_LAPIS = 
"";
 
   71    public static string $COLOR_MATERIAL_AMETHYST = 
"";
 
   72    public static string $COLOR_MATERIAL_RESIN = 
"";
 
   74    private static ?
bool $formattingCodes = 
null;
 
   76    public static function hasFormattingCodes() : 
bool{
 
   77        if(self::$formattingCodes === 
null){
 
   78            throw new \LogicException(
"Formatting codes have not been initialized");
 
   80        return self::$formattingCodes;
 
   83    private static function detectFormattingCodesSupport() : 
bool{
 
   84        $stdout = fopen(
"php://stdout", 
"w");
 
   87            stream_isatty($stdout) && 
 
   89                getenv(
'TERM') !== 
false || 
 
   90                (function_exists(
'sapi_windows_vt100_support') && sapi_windows_vt100_support($stdout)) 
 
   97    protected static function getFallbackEscapeCodes() : 
void{
 
   98        self::$FORMAT_BOLD = 
"\x1b[1m";
 
   99        self::$FORMAT_OBFUSCATED = 
"";
 
  100        self::$FORMAT_ITALIC = 
"\x1b[3m";
 
  101        self::$FORMAT_UNDERLINE = 
"\x1b[4m";
 
  102        self::$FORMAT_STRIKETHROUGH = 
"\x1b[9m";
 
  104        self::$FORMAT_RESET = 
"\x1b[m";
 
  106        $color = fn(
int $code) => 
"\x1b[38;5;{$code}m";
 
  108        self::$COLOR_BLACK = $color(16);
 
  109        self::$COLOR_DARK_BLUE = $color(19);
 
  110        self::$COLOR_DARK_GREEN = $color(34);
 
  111        self::$COLOR_DARK_AQUA = $color(37);
 
  112        self::$COLOR_DARK_RED = $color(124);
 
  113        self::$COLOR_PURPLE = $color(127);
 
  114        self::$COLOR_GOLD = $color(214);
 
  115        self::$COLOR_GRAY = $color(145);
 
  116        self::$COLOR_DARK_GRAY = $color(59);
 
  117        self::$COLOR_BLUE = $color(63);
 
  118        self::$COLOR_GREEN = $color(83);
 
  119        self::$COLOR_AQUA = $color(87);
 
  120        self::$COLOR_RED = $color(203);
 
  121        self::$COLOR_LIGHT_PURPLE = $color(207);
 
  122        self::$COLOR_YELLOW = $color(227);
 
  123        self::$COLOR_WHITE = $color(231);
 
  124        self::$COLOR_MINECOIN_GOLD = $color(184);
 
  125        self::$COLOR_MATERIAL_QUARTZ = $color(188);
 
  126        self::$COLOR_MATERIAL_IRON = $color(251);
 
  127        self::$COLOR_MATERIAL_NETHERITE = $color(237);
 
  128        self::$COLOR_MATERIAL_REDSTONE = $color(88);
 
  129        self::$COLOR_MATERIAL_COPPER = $color(131);
 
  130        self::$COLOR_MATERIAL_GOLD = $color(178);
 
  131        self::$COLOR_MATERIAL_EMERALD = $color(35);
 
  132        self::$COLOR_MATERIAL_DIAMOND = $color(37);
 
  133        self::$COLOR_MATERIAL_LAPIS = $color(24);
 
  134        self::$COLOR_MATERIAL_AMETHYST = $color(98);
 
  135        self::$COLOR_MATERIAL_RESIN = $color(208);
 
  138    protected static function getEscapeCodes() : 
void{
 
  139        $tput = fn(
string $args) => is_string($result = shell_exec(
"tput $args")) ? $result : 
"";
 
  140        $setaf = fn(
int $code) => $tput(
"setaf $code");
 
  142        self::$FORMAT_BOLD = $tput(
"bold");
 
  143        self::$FORMAT_OBFUSCATED = $tput(
"smacs");
 
  144        self::$FORMAT_ITALIC = $tput(
"sitm");
 
  145        self::$FORMAT_UNDERLINE = $tput(
"smul");
 
  146        self::$FORMAT_STRIKETHROUGH = 
"\x1b[9m"; 
 
  148        self::$FORMAT_RESET = $tput(
"sgr0");
 
  150        $colors = (int) $tput(
"colors");
 
  152            self::$COLOR_BLACK = $colors >= 256 ? $setaf(16) : $setaf(0);
 
  153            self::$COLOR_DARK_BLUE = $colors >= 256 ? $setaf(19) : $setaf(4);
 
  154            self::$COLOR_DARK_GREEN = $colors >= 256 ? $setaf(34) : $setaf(2);
 
  155            self::$COLOR_DARK_AQUA = $colors >= 256 ? $setaf(37) : $setaf(6);
 
  156            self::$COLOR_DARK_RED = $colors >= 256 ? $setaf(124) : $setaf(1);
 
  157            self::$COLOR_PURPLE = $colors >= 256 ? $setaf(127) : $setaf(5);
 
  158            self::$COLOR_GOLD = $colors >= 256 ? $setaf(214) : $setaf(3);
 
  159            self::$COLOR_GRAY = $colors >= 256 ? $setaf(145) : $setaf(7);
 
  160            self::$COLOR_DARK_GRAY = $colors >= 256 ? $setaf(59) : $setaf(8);
 
  161            self::$COLOR_BLUE = $colors >= 256 ? $setaf(63) : $setaf(12);
 
  162            self::$COLOR_GREEN = $colors >= 256 ? $setaf(83) : $setaf(10);
 
  163            self::$COLOR_AQUA = $colors >= 256 ? $setaf(87) : $setaf(14);
 
  164            self::$COLOR_RED = $colors >= 256 ? $setaf(203) : $setaf(9);
 
  165            self::$COLOR_LIGHT_PURPLE = $colors >= 256 ? $setaf(207) : $setaf(13);
 
  166            self::$COLOR_YELLOW = $colors >= 256 ? $setaf(227) : $setaf(11);
 
  167            self::$COLOR_WHITE = $colors >= 256 ? $setaf(231) : $setaf(15);
 
  168            self::$COLOR_MINECOIN_GOLD = $colors >= 256 ? $setaf(184) : $setaf(11);
 
  169            self::$COLOR_MATERIAL_QUARTZ = $colors >= 256 ? $setaf(188) : $setaf(7);
 
  170            self::$COLOR_MATERIAL_IRON = $colors >= 256 ? $setaf(251) : $setaf(7);
 
  171            self::$COLOR_MATERIAL_NETHERITE = $colors >= 256 ? $setaf(237) : $setaf(1);
 
  172            self::$COLOR_MATERIAL_REDSTONE = $colors >= 256 ? $setaf(88) : $setaf(9);
 
  173            self::$COLOR_MATERIAL_COPPER = $colors >= 256 ? $setaf(131) : $setaf(3);
 
  174            self::$COLOR_MATERIAL_GOLD = $colors >= 256 ? $setaf(178) : $setaf(11);
 
  175            self::$COLOR_MATERIAL_EMERALD = $colors >= 256 ? $setaf(35) : $setaf(2);
 
  176            self::$COLOR_MATERIAL_DIAMOND = $colors >= 256 ? $setaf(37) : $setaf(14);
 
  177            self::$COLOR_MATERIAL_LAPIS = $colors >= 256 ? $setaf(24) : $setaf(12);
 
  178            self::$COLOR_MATERIAL_AMETHYST = $colors >= 256 ? $setaf(98) : $setaf(13);
 
  179            self::$COLOR_MATERIAL_RESIN = $colors >= 256 ? $setaf(208) : $setaf(11);
 
  181            self::$COLOR_BLACK = self::$COLOR_DARK_GRAY = self::$COLOR_MATERIAL_NETHERITE = $setaf(0);
 
  182            self::$COLOR_RED = self::$COLOR_DARK_RED = self::$COLOR_MATERIAL_REDSTONE = self::$COLOR_MATERIAL_COPPER = $setaf(1);
 
  183            self::$COLOR_GREEN = self::$COLOR_DARK_GREEN = self::$COLOR_MATERIAL_EMERALD = $setaf(2);
 
  184            self::$COLOR_YELLOW = self::$COLOR_GOLD = self::$COLOR_MINECOIN_GOLD = self::$COLOR_MATERIAL_GOLD = self::$COLOR_MATERIAL_RESIN = $setaf(3);
 
  185            self::$COLOR_BLUE = self::$COLOR_DARK_BLUE = self::$COLOR_MATERIAL_LAPIS = $setaf(4);
 
  186            self::$COLOR_LIGHT_PURPLE = self::$COLOR_PURPLE = self::$COLOR_MATERIAL_AMETHYST = $setaf(5);
 
  187            self::$COLOR_AQUA = self::$COLOR_DARK_AQUA = self::$COLOR_MATERIAL_DIAMOND = $setaf(6);
 
  188            self::$COLOR_GRAY = self::$COLOR_WHITE = self::$COLOR_MATERIAL_QUARTZ = self::$COLOR_MATERIAL_IRON = $setaf(7);
 
  192    public static function init(?
bool $enableFormatting = 
null) : 
void{
 
  193        self::$formattingCodes = $enableFormatting ?? self::detectFormattingCodesSupport();
 
  194        if(!self::$formattingCodes){
 
  199            case Utils::OS_LINUX:
 
  200            case Utils::OS_MACOS:
 
  202                if(getenv(
'TERM') !== 
false){
 
  203                    self::getEscapeCodes();
 
  207            case Utils::OS_WINDOWS:
 
  208            case Utils::OS_ANDROID:
 
  209                self::getFallbackEscapeCodes();
 
  216    public static function isInit() : 
bool{
 
  217        return self::$formattingCodes !== 
null;
 
  224    public static function toANSI(
string $string) : string{
 
  227            $newString .= match ($token) {
 
  228                TextFormat::BOLD => Terminal::$FORMAT_BOLD,
 
  229                TextFormat::OBFUSCATED => Terminal::$FORMAT_OBFUSCATED,
 
  230                TextFormat::ITALIC => Terminal::$FORMAT_ITALIC,
 
  231                TextFormat::RESET => Terminal::$FORMAT_RESET,
 
  232                TextFormat::BLACK => Terminal::$COLOR_BLACK,
 
  233                TextFormat::DARK_BLUE => Terminal::$COLOR_DARK_BLUE,
 
  234                TextFormat::DARK_GREEN => Terminal::$COLOR_DARK_GREEN,
 
  235                TextFormat::DARK_AQUA => Terminal::$COLOR_DARK_AQUA,
 
  236                TextFormat::DARK_RED => Terminal::$COLOR_DARK_RED,
 
  237                TextFormat::DARK_PURPLE => Terminal::$COLOR_PURPLE,
 
  238                TextFormat::GOLD => Terminal::$COLOR_GOLD,
 
  239                TextFormat::GRAY => Terminal::$COLOR_GRAY,
 
  240                TextFormat::DARK_GRAY => Terminal::$COLOR_DARK_GRAY,
 
  241                TextFormat::BLUE => Terminal::$COLOR_BLUE,
 
  242                TextFormat::GREEN => Terminal::$COLOR_GREEN,
 
  243                TextFormat::AQUA => Terminal::$COLOR_AQUA,
 
  244                TextFormat::RED => Terminal::$COLOR_RED,
 
  245                TextFormat::LIGHT_PURPLE => Terminal::$COLOR_LIGHT_PURPLE,
 
  246                TextFormat::YELLOW => Terminal::$COLOR_YELLOW,
 
  247                TextFormat::WHITE => Terminal::$COLOR_WHITE,
 
  248                TextFormat::MINECOIN_GOLD => Terminal::$COLOR_MINECOIN_GOLD,
 
  249                TextFormat::MATERIAL_QUARTZ => Terminal::$COLOR_MATERIAL_QUARTZ,
 
  250                TextFormat::MATERIAL_IRON => Terminal::$COLOR_MATERIAL_IRON,
 
  251                TextFormat::MATERIAL_NETHERITE => Terminal::$COLOR_MATERIAL_NETHERITE,
 
  252                TextFormat::MATERIAL_REDSTONE => Terminal::$COLOR_MATERIAL_REDSTONE,
 
  253                TextFormat::MATERIAL_COPPER => Terminal::$COLOR_MATERIAL_COPPER,
 
  254                TextFormat::MATERIAL_GOLD => Terminal::$COLOR_MATERIAL_GOLD,
 
  255                TextFormat::MATERIAL_EMERALD => Terminal::$COLOR_MATERIAL_EMERALD,
 
  256                TextFormat::MATERIAL_DIAMOND => Terminal::$COLOR_MATERIAL_DIAMOND,
 
  257                TextFormat::MATERIAL_LAPIS => Terminal::$COLOR_MATERIAL_LAPIS,
 
  258                TextFormat::MATERIAL_AMETHYST => Terminal::$COLOR_MATERIAL_AMETHYST,
 
  259                TextFormat::MATERIAL_RESIN => Terminal::$COLOR_MATERIAL_RESIN,
 
 
  270    public static function write(
string $line) : void{
 
  271        echo self::toANSI($line);
 
 
  279        echo self::toANSI($line) . self::$FORMAT_RESET . PHP_EOL;