Skip to content

Commit efdc2e8

Browse files
committed
add new class
1 parent 3c76510 commit efdc2e8

File tree

3 files changed

+279
-3
lines changed

3 files changed

+279
-3
lines changed

Diff for: src/Color.php

+9-3
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,14 @@ class Color
208208
'white_ex' => '97',
209209

210210
// option
211-
'bold' => '1',
211+
'b' => '0;1',
212+
'bold' => '0;1',
213+
'fuzzy' => '2',
212214
'italic' => '3',
213215
'underscore' => '4',
216+
'blink' => '5',
214217
'reverse' => '7',
218+
'concealed' => '8',
215219
];
216220

217221
// Regex to match color tags
@@ -221,6 +225,8 @@ class Color
221225
public const COLOR_TPL = "\033[%sm%s\033[0m";
222226

223227
/**
228+
* Flag to remove color codes from the output
229+
*
224230
* @var bool
225231
*/
226232
private static $noColor = false;
@@ -387,7 +393,7 @@ public static function stringToCode(string $string): string
387393
// check color name is valid
388394
if (!isset(static::$knownColors[$fg])) {
389395
$errTpl = 'Invalid foreground color "%1$s" [%2$s]';
390-
$names = implode(', ', self::getKnownColors());
396+
$names = implode(', ', self::getKnownColors());
391397
throw new InvalidArgumentException(sprintf($errTpl, $fg, $names));
392398
}
393399

@@ -398,7 +404,7 @@ public static function stringToCode(string $string): string
398404
// check color name is valid
399405
if (!isset(static::$knownColors[$bg])) {
400406
$errTpl = 'Invalid background color "%1$s" [%2$s]';
401-
$names = implode(', ', self::getKnownColors());
407+
$names = implode(', ', self::getKnownColors());
402408
throw new InvalidArgumentException(sprintf($errTpl, $bg, $names));
403409
}
404410

Diff for: src/ColorCode.php

+264
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
<?php declare(strict_types=1);
2+
/**
3+
* Created by PhpStorm.
4+
*/
5+
6+
namespace Toolkit\Cli;
7+
8+
use InvalidArgumentException;
9+
use RuntimeException;
10+
use function array_keys;
11+
use function count;
12+
use function explode;
13+
use function implode;
14+
use function str_replace;
15+
16+
/**
17+
* Class Color
18+
* - fg unset 39
19+
* - bg unset 49
20+
*
21+
* @package Inhere\Console\Component\Style
22+
*/
23+
class ColorCode
24+
{
25+
/** Foreground base value */
26+
public const FG_BASE = 30;
27+
28+
/** Background base value */
29+
public const BG_BASE = 40;
30+
31+
/** Extra Foreground base value */
32+
public const FG_EXTRA = 90;
33+
34+
/** Extra Background base value */
35+
public const BG_EXTRA = 100;
36+
37+
// color
38+
public const BLACK = 'black';
39+
40+
public const RED = 'red';
41+
42+
public const GREEN = 'green';
43+
44+
public const YELLOW = 'yellow'; // BROWN
45+
46+
public const BLUE = 'blue';
47+
48+
public const MAGENTA = 'magenta';
49+
50+
public const CYAN = 'cyan';
51+
52+
public const WHITE = 'white';
53+
54+
public const NORMAL = 'normal';
55+
56+
// color option
57+
public const BOLD = 'bold'; // 加粗
58+
59+
public const FUZZY = 'fuzzy'; // 模糊(不是所有的终端仿真器都支持)
60+
61+
public const ITALIC = 'italic'; // 斜体(不是所有的终端仿真器都支持)
62+
63+
public const UNDERSCORE = 'underscore'; // 下划线
64+
65+
public const BLINK = 'blink'; // 闪烁
66+
67+
public const REVERSE = 'reverse'; // 颠倒的 交换背景色与前景色
68+
69+
public const CONCEALED = 'concealed'; // 隐匿的
70+
71+
/** @var array Known color list */
72+
private static $knownColors = [
73+
'black' => 0,
74+
'red' => 1,
75+
'green' => 2,
76+
'yellow' => 3,
77+
'blue' => 4,
78+
'magenta' => 5, // 洋红色 洋红 品红色
79+
'cyan' => 6, // 青色 青绿色 蓝绿色
80+
'white' => 7,
81+
'normal' => 9,
82+
];
83+
84+
/** @var array Known style option */
85+
private static $knownOptions = [
86+
'bold' => 1, // 22 加粗
87+
'fuzzy' => 2, // 模糊(不是所有的终端仿真器都支持)
88+
'italic' => 3, // 斜体(不是所有的终端仿真器都支持)
89+
'underscore' => 4, // 24 下划线
90+
'blink' => 5, // 25 闪烁
91+
'reverse' => 7, // 27 颠倒的 交换背景色与前景色
92+
'concealed' => 8, // 28 隐匿的
93+
];
94+
95+
/** @var int Foreground color */
96+
private $fgColor = 0;
97+
98+
/** @var int Background color */
99+
private $bgColor = 0;
100+
101+
/** @var array Array of style options */
102+
private $options = [];
103+
104+
/**
105+
* @param string $fg
106+
* @param string $bg
107+
* @param array $options
108+
* @param bool $extra
109+
*
110+
* @return ColorCode
111+
* @throws InvalidArgumentException
112+
*/
113+
public static function make($fg = '', $bg = '', array $options = [], bool $extra = false): ColorCode
114+
{
115+
return new self($fg, $bg, $options, $extra);
116+
}
117+
118+
/**
119+
* Create a color style from a parameter string.
120+
*
121+
* @param string $string e.g 'fg=white;bg=black;options=bold,underscore;extra=1'
122+
*
123+
* @return static
124+
* @throws InvalidArgumentException
125+
* @throws RuntimeException
126+
*/
127+
public static function fromString($string)
128+
{
129+
$extra = false;
130+
$options = [];
131+
$parts = explode(';', str_replace(' ', '', $string));
132+
133+
$fg = $bg = '';
134+
foreach ($parts as $part) {
135+
$subParts = explode('=', $part);
136+
if (count($subParts) < 2) {
137+
continue;
138+
}
139+
140+
switch ($subParts[0]) {
141+
case 'fg':
142+
$fg = $subParts[1];
143+
break;
144+
case 'bg':
145+
$bg = $subParts[1];
146+
break;
147+
case 'extra':
148+
$extra = (bool)$subParts[1];
149+
break;
150+
case 'options':
151+
$options = explode(',', $subParts[1]);
152+
break;
153+
default:
154+
throw new RuntimeException('Invalid option');
155+
break;
156+
}
157+
}
158+
159+
return new self($fg, $bg, $options, $extra);
160+
}
161+
162+
/**
163+
* Constructor
164+
*
165+
* @param string $fg Foreground color. e.g 'white'
166+
* @param string $bg Background color. e.g 'black'
167+
* @param array $options Style options. e.g ['bold', 'underscore']
168+
* @param bool $extra
169+
*
170+
* @throws InvalidArgumentException
171+
*/
172+
public function __construct($fg = '', $bg = '', array $options = [], bool $extra = false)
173+
{
174+
if ($fg) {
175+
if (!isset(static::$knownColors[$fg])) {
176+
throw new InvalidArgumentException(sprintf(
177+
'Invalid foreground color "%1$s" [%2$s]',
178+
$fg,
179+
implode(', ', $this->getKnownColors())
180+
));
181+
}
182+
183+
$this->fgColor = ($extra ? self::FG_EXTRA : self::FG_BASE) + static::$knownColors[$fg];
184+
}
185+
186+
if ($bg) {
187+
if (!isset(static::$knownColors[$bg])) {
188+
throw new InvalidArgumentException(sprintf(
189+
'Invalid background color "%1$s" [%2$s]',
190+
$bg,
191+
implode(', ', $this->getKnownColors())
192+
));
193+
}
194+
195+
$this->bgColor = ($extra ? self::BG_EXTRA : self::BG_BASE) + static::$knownColors[$bg];
196+
}
197+
198+
foreach ($options as $option) {
199+
if (!isset(static::$knownOptions[$option])) {
200+
throw new InvalidArgumentException(sprintf(
201+
'Invalid option "%1$s" [%2$s]',
202+
$option,
203+
implode(', ', $this->getKnownOptions())
204+
));
205+
}
206+
207+
$this->options[] = $option;
208+
}
209+
}
210+
211+
/**
212+
* Convert to a string.
213+
*/
214+
public function __toString()
215+
{
216+
return $this->toStyle();
217+
}
218+
219+
/**
220+
* Get the translated color code.
221+
*/
222+
public function toStyle(): string
223+
{
224+
$values = [];
225+
226+
if ($this->fgColor) {
227+
$values[] = $this->fgColor;
228+
}
229+
230+
if ($this->bgColor) {
231+
$values[] = $this->bgColor;
232+
}
233+
234+
foreach ($this->options as $option) {
235+
$values[] = static::$knownOptions[$option];
236+
}
237+
238+
return implode(';', $values);
239+
}
240+
241+
/**
242+
* Get the known colors.
243+
*
244+
* @param bool $onlyName
245+
*
246+
* @return array
247+
*/
248+
public function getKnownColors(bool $onlyName = true): array
249+
{
250+
return $onlyName ? array_keys(static::$knownColors) : static::$knownColors;
251+
}
252+
253+
/**
254+
* Get the known options.
255+
*
256+
* @param bool $onlyName
257+
*
258+
* @return array
259+
*/
260+
public function getKnownOptions(bool $onlyName = true): array
261+
{
262+
return $onlyName ? array_keys(static::$knownOptions) : static::$knownOptions;
263+
}
264+
}

Diff for: test/ColorTagTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,10 @@ public function testExists(): void
7272
$this->assertFalse(ColorTag::exists('<tag>text'));
7373
$this->assertFalse(ColorTag::exists('<tag>text<tag>'));
7474
}
75+
76+
public function testParse(): void
77+
{
78+
$text = ColorTag::parse('<info>INFO</info>');
79+
$this->assertSame("\033[0;32mINFO\033[0m", $text);
80+
}
7581
}

0 commit comments

Comments
 (0)