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 =
"";
73 private static ?
bool $formattingCodes =
null;
75 public static function hasFormattingCodes() :
bool{
76 if(self::$formattingCodes ===
null){
77 throw new \LogicException(
"Formatting codes have not been initialized");
79 return self::$formattingCodes;
82 private static function detectFormattingCodesSupport() :
bool{
83 $stdout = fopen(
"php://stdout",
"w");
86 stream_isatty($stdout) &&
88 getenv(
'TERM') !==
false ||
89 (function_exists(
'sapi_windows_vt100_support') && sapi_windows_vt100_support($stdout))
96 protected static function getFallbackEscapeCodes() :
void{
97 self::$FORMAT_BOLD =
"\x1b[1m";
98 self::$FORMAT_OBFUSCATED =
"";
99 self::$FORMAT_ITALIC =
"\x1b[3m";
100 self::$FORMAT_UNDERLINE =
"\x1b[4m";
101 self::$FORMAT_STRIKETHROUGH =
"\x1b[9m";
103 self::$FORMAT_RESET =
"\x1b[m";
105 $color = fn(
int $code) =>
"\x1b[38;5;{$code}m";
107 self::$COLOR_BLACK = $color(16);
108 self::$COLOR_DARK_BLUE = $color(19);
109 self::$COLOR_DARK_GREEN = $color(34);
110 self::$COLOR_DARK_AQUA = $color(37);
111 self::$COLOR_DARK_RED = $color(124);
112 self::$COLOR_PURPLE = $color(127);
113 self::$COLOR_GOLD = $color(214);
114 self::$COLOR_GRAY = $color(145);
115 self::$COLOR_DARK_GRAY = $color(59);
116 self::$COLOR_BLUE = $color(63);
117 self::$COLOR_GREEN = $color(83);
118 self::$COLOR_AQUA = $color(87);
119 self::$COLOR_RED = $color(203);
120 self::$COLOR_LIGHT_PURPLE = $color(207);
121 self::$COLOR_YELLOW = $color(227);
122 self::$COLOR_WHITE = $color(231);
123 self::$COLOR_MINECOIN_GOLD = $color(184);
124 self::$COLOR_MATERIAL_QUARTZ = $color(188);
125 self::$COLOR_MATERIAL_IRON = $color(251);
126 self::$COLOR_MATERIAL_NETHERITE = $color(237);
127 self::$COLOR_MATERIAL_REDSTONE = $color(88);
128 self::$COLOR_MATERIAL_COPPER = $color(131);
129 self::$COLOR_MATERIAL_GOLD = $color(178);
130 self::$COLOR_MATERIAL_EMERALD = $color(35);
131 self::$COLOR_MATERIAL_DIAMOND = $color(37);
132 self::$COLOR_MATERIAL_LAPIS = $color(24);
133 self::$COLOR_MATERIAL_AMETHYST = $color(98);
136 protected static function getEscapeCodes() :
void{
137 $tput = fn(
string $args) => is_string($result = shell_exec(
"tput $args")) ? $result :
"";
138 $setaf = fn(
int $code) => $tput(
"setaf $code");
140 self::$FORMAT_BOLD = $tput(
"bold");
141 self::$FORMAT_OBFUSCATED = $tput(
"smacs");
142 self::$FORMAT_ITALIC = $tput(
"sitm");
143 self::$FORMAT_UNDERLINE = $tput(
"smul");
144 self::$FORMAT_STRIKETHROUGH =
"\x1b[9m";
146 self::$FORMAT_RESET = $tput(
"sgr0");
148 $colors = (int) $tput(
"colors");
150 self::$COLOR_BLACK = $colors >= 256 ? $setaf(16) : $setaf(0);
151 self::$COLOR_DARK_BLUE = $colors >= 256 ? $setaf(19) : $setaf(4);
152 self::$COLOR_DARK_GREEN = $colors >= 256 ? $setaf(34) : $setaf(2);
153 self::$COLOR_DARK_AQUA = $colors >= 256 ? $setaf(37) : $setaf(6);
154 self::$COLOR_DARK_RED = $colors >= 256 ? $setaf(124) : $setaf(1);
155 self::$COLOR_PURPLE = $colors >= 256 ? $setaf(127) : $setaf(5);
156 self::$COLOR_GOLD = $colors >= 256 ? $setaf(214) : $setaf(3);
157 self::$COLOR_GRAY = $colors >= 256 ? $setaf(145) : $setaf(7);
158 self::$COLOR_DARK_GRAY = $colors >= 256 ? $setaf(59) : $setaf(8);
159 self::$COLOR_BLUE = $colors >= 256 ? $setaf(63) : $setaf(12);
160 self::$COLOR_GREEN = $colors >= 256 ? $setaf(83) : $setaf(10);
161 self::$COLOR_AQUA = $colors >= 256 ? $setaf(87) : $setaf(14);
162 self::$COLOR_RED = $colors >= 256 ? $setaf(203) : $setaf(9);
163 self::$COLOR_LIGHT_PURPLE = $colors >= 256 ? $setaf(207) : $setaf(13);
164 self::$COLOR_YELLOW = $colors >= 256 ? $setaf(227) : $setaf(11);
165 self::$COLOR_WHITE = $colors >= 256 ? $setaf(231) : $setaf(15);
166 self::$COLOR_MINECOIN_GOLD = $colors >= 256 ? $setaf(184) : $setaf(11);
167 self::$COLOR_MATERIAL_QUARTZ = $colors >= 256 ? $setaf(188) : $setaf(7);
168 self::$COLOR_MATERIAL_IRON = $colors >= 256 ? $setaf(251) : $setaf(7);
169 self::$COLOR_MATERIAL_NETHERITE = $colors >= 256 ? $setaf(237) : $setaf(1);
170 self::$COLOR_MATERIAL_REDSTONE = $colors >= 256 ? $setaf(88) : $setaf(9);
171 self::$COLOR_MATERIAL_COPPER = $colors >= 256 ? $setaf(131) : $setaf(3);
172 self::$COLOR_MATERIAL_GOLD = $colors >= 256 ? $setaf(178) : $setaf(11);
173 self::$COLOR_MATERIAL_EMERALD = $colors >= 256 ? $setaf(35) : $setaf(2);
174 self::$COLOR_MATERIAL_DIAMOND = $colors >= 256 ? $setaf(37) : $setaf(14);
175 self::$COLOR_MATERIAL_LAPIS = $colors >= 256 ? $setaf(24) : $setaf(12);
176 self::$COLOR_MATERIAL_AMETHYST = $colors >= 256 ? $setaf(98) : $setaf(13);
178 self::$COLOR_BLACK = self::$COLOR_DARK_GRAY = self::$COLOR_MATERIAL_NETHERITE = $setaf(0);
179 self::$COLOR_RED = self::$COLOR_DARK_RED = self::$COLOR_MATERIAL_REDSTONE = self::$COLOR_MATERIAL_COPPER = $setaf(1);
180 self::$COLOR_GREEN = self::$COLOR_DARK_GREEN = self::$COLOR_MATERIAL_EMERALD = $setaf(2);
181 self::$COLOR_YELLOW = self::$COLOR_GOLD = self::$COLOR_MINECOIN_GOLD = self::$COLOR_MATERIAL_GOLD = $setaf(3);
182 self::$COLOR_BLUE = self::$COLOR_DARK_BLUE = self::$COLOR_MATERIAL_LAPIS = $setaf(4);
183 self::$COLOR_LIGHT_PURPLE = self::$COLOR_PURPLE = self::$COLOR_MATERIAL_AMETHYST = $setaf(5);
184 self::$COLOR_AQUA = self::$COLOR_DARK_AQUA = self::$COLOR_MATERIAL_DIAMOND = $setaf(6);
185 self::$COLOR_GRAY = self::$COLOR_WHITE = self::$COLOR_MATERIAL_QUARTZ = self::$COLOR_MATERIAL_IRON = $setaf(7);
189 public static function init(?
bool $enableFormatting =
null) :
void{
190 self::$formattingCodes = $enableFormatting ?? self::detectFormattingCodesSupport();
191 if(!self::$formattingCodes){
196 case Utils::OS_LINUX:
197 case Utils::OS_MACOS:
199 if(getenv(
'TERM') !==
false){
200 self::getEscapeCodes();
204 case Utils::OS_WINDOWS:
205 case Utils::OS_ANDROID:
206 self::getFallbackEscapeCodes();
213 public static function isInit() :
bool{
214 return self::$formattingCodes !==
null;
221 public static function toANSI(
string $string) : string{
224 $newString .= match ($token) {
225 TextFormat::BOLD => Terminal::$FORMAT_BOLD,
226 TextFormat::OBFUSCATED => Terminal::$FORMAT_OBFUSCATED,
227 TextFormat::ITALIC => Terminal::$FORMAT_ITALIC,
228 TextFormat::RESET => Terminal::$FORMAT_RESET,
229 TextFormat::BLACK => Terminal::$COLOR_BLACK,
230 TextFormat::DARK_BLUE => Terminal::$COLOR_DARK_BLUE,
231 TextFormat::DARK_GREEN => Terminal::$COLOR_DARK_GREEN,
232 TextFormat::DARK_AQUA => Terminal::$COLOR_DARK_AQUA,
233 TextFormat::DARK_RED => Terminal::$COLOR_DARK_RED,
234 TextFormat::DARK_PURPLE => Terminal::$COLOR_PURPLE,
235 TextFormat::GOLD => Terminal::$COLOR_GOLD,
236 TextFormat::GRAY => Terminal::$COLOR_GRAY,
237 TextFormat::DARK_GRAY => Terminal::$COLOR_DARK_GRAY,
238 TextFormat::BLUE => Terminal::$COLOR_BLUE,
239 TextFormat::GREEN => Terminal::$COLOR_GREEN,
240 TextFormat::AQUA => Terminal::$COLOR_AQUA,
241 TextFormat::RED => Terminal::$COLOR_RED,
242 TextFormat::LIGHT_PURPLE => Terminal::$COLOR_LIGHT_PURPLE,
243 TextFormat::YELLOW => Terminal::$COLOR_YELLOW,
244 TextFormat::WHITE => Terminal::$COLOR_WHITE,
245 TextFormat::MINECOIN_GOLD => Terminal::$COLOR_MINECOIN_GOLD,
246 TextFormat::MATERIAL_QUARTZ => Terminal::$COLOR_MATERIAL_QUARTZ,
247 TextFormat::MATERIAL_IRON => Terminal::$COLOR_MATERIAL_IRON,
248 TextFormat::MATERIAL_NETHERITE => Terminal::$COLOR_MATERIAL_NETHERITE,
249 TextFormat::MATERIAL_REDSTONE => Terminal::$COLOR_MATERIAL_REDSTONE,
250 TextFormat::MATERIAL_COPPER => Terminal::$COLOR_MATERIAL_COPPER,
251 TextFormat::MATERIAL_GOLD => Terminal::$COLOR_MATERIAL_GOLD,
252 TextFormat::MATERIAL_EMERALD => Terminal::$COLOR_MATERIAL_EMERALD,
253 TextFormat::MATERIAL_DIAMOND => Terminal::$COLOR_MATERIAL_DIAMOND,
254 TextFormat::MATERIAL_LAPIS => Terminal::$COLOR_MATERIAL_LAPIS,
255 TextFormat::MATERIAL_AMETHYST => Terminal::$COLOR_MATERIAL_AMETHYST,
266 public static function write(
string $line) : void{
267 echo self::toANSI($line);
275 echo self::toANSI($line) . self::$FORMAT_RESET . PHP_EOL;