Skip to content

Commit aaa3f37

Browse files
committed
[Console] Move & refactor some methods to the new AnsiColor enum
1 parent 9739164 commit aaa3f37

File tree

3 files changed

+108
-105
lines changed

3 files changed

+108
-105
lines changed

src/Symfony/Component/Console/Color.php

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Symfony\Component\Console;
1313

1414
use Symfony\Component\Console\Exception\InvalidArgumentException;
15-
use Symfony\Component\Console\Output\AnsiColor;
1615

1716
/**
1817
* @author Fabien Potencier <fabien@symfony.com>
@@ -128,7 +127,7 @@ private function parseColor(string $color, bool $background = false): string
128127
throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color));
129128
}
130129

131-
return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color));
130+
return ($background ? '4' : '3').Terminal::getTermColorSupport()->convertFromHexToAnsiColorCode($color);
132131
}
133132

134133
if (isset(self::COLORS[$color])) {
@@ -141,68 +140,4 @@ private function parseColor(string $color, bool $background = false): string
141140

142141
throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
143142
}
144-
145-
private function convertHexColorToAnsi(int $color): string
146-
{
147-
$r = ($color >> 16) & 255;
148-
$g = ($color >> 8) & 255;
149-
$b = $color & 255;
150-
151-
$termSupport = Terminal::getTermColorSupport();
152-
153-
if (AnsiColor::Ansi4 === $termSupport) {
154-
return (string) $this->degradeHexColorToAnsi4($r, $g, $b);
155-
}
156-
157-
if (AnsiColor::Ansi8 === $termSupport) {
158-
return '8;5;'.((string) $this->degradeHexColorToAnsi8($r, $g, $b));
159-
}
160-
161-
// Ansi24 true color
162-
return sprintf('8;2;%d;%d;%d', $r, $g, $b);
163-
}
164-
165-
private function degradeHexColorToAnsi4(int $r, int $g, int $b): int
166-
{
167-
if (0 === round($this->getSaturation($r, $g, $b) / 50)) {
168-
return 0;
169-
}
170-
171-
return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255);
172-
}
173-
174-
/**
175-
* Inspired from https://github.com/ajalt/colormath/blob/e464e0da1b014976736cf97250063248fc77b8e7/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/Ansi256.kt code (MIT license).
176-
*/
177-
private function degradeHexColorToAnsi8(int $r, int $g, int $b): int
178-
{
179-
if ($r === $g && $g === $b) {
180-
if ($r < 8) {
181-
return 16;
182-
} elseif ($r > 248) {
183-
return 231;
184-
} else {
185-
return (int) (round((($r - 8) / 247) * 24)) + 232;
186-
}
187-
} else {
188-
return 16 +
189-
(36 * (int) (round($r / 255 * 5))) +
190-
(6 * (int) (round($g / 255 * 5))) +
191-
(int) (round($b / 255 * 5));
192-
}
193-
}
194-
195-
private function getSaturation(int $r, int $g, int $b): int
196-
{
197-
$r = $r / 255;
198-
$g = $g / 255;
199-
$b = $b / 255;
200-
$v = max($r, $g, $b);
201-
202-
if (0 === $diff = $v - min($r, $g, $b)) {
203-
return 0;
204-
}
205-
206-
return (int) $diff * 100 / $v;
207-
}
208143
}
Lines changed: 105 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,105 @@
1-
<?php
2-
3-
/*
4-
* This file is part of the Symfony package.
5-
*
6-
* (c) Fabien Potencier <fabien@symfony.com>
7-
*
8-
* For the full copyright and license information, please view the LICENSE
9-
* file that was distributed with this source code.
10-
*/
11-
12-
namespace Symfony\Component\Console\Output;
13-
14-
/**
15-
* @author Julien Boudry <julien@condorcet.vote>
16-
*/
17-
enum AnsiColor {
18-
/*
19-
* Classical 4-bit Ansi colors, including 8 classical colors and 8 bright color. Output syntax is "ESC[${foreGroundColorcode};${backGroundColorcode}m"
20-
* Must be compatible with all terminals and it's the minimal version supported.
21-
*/
22-
case Ansi4;
23-
24-
/*
25-
* 8-bit Ansi colors (240 differents colors + 16 duplicate color codes, ensuring backward compatibility).
26-
* Output syntax is: "ESC[38;5;${foreGroundColorcode};48;5;${backGroundColorcode}m"
27-
* Should be compatible with most terminals.
28-
*/
29-
case Ansi8;
30-
31-
/*
32-
* 24-bit Ansi colors (RGB).
33-
* Output syntax is: "ESC[38;5;${foreGroundColorcodeRed};${foreGroundColorcodeGreen};${foreGroundColorcodeBlue};48;5;${backGroundColorcodeRed};${backGroundColorcodeGreen};${backGroundColorcodeBlue}m"
34-
* May be compatible with many modern terminals.
35-
*/
36-
case Ansi24;
37-
}
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Console\Output;
13+
14+
/**
15+
* @author Julien Boudry <julien@condorcet.vote>
16+
*/
17+
enum AnsiColor
18+
{
19+
/*
20+
* Classical 4-bit Ansi colors, including 8 classical colors and 8 bright color. Output syntax is "ESC[${foreGroundColorcode};${backGroundColorcode}m"
21+
* Must be compatible with all terminals and it's the minimal version supported.
22+
*/
23+
case Ansi4;
24+
/*
25+
* 8-bit Ansi colors (240 differents colors + 16 duplicate color codes, ensuring backward compatibility).
26+
* Output syntax is: "ESC[38;5;${foreGroundColorcode};48;5;${backGroundColorcode}m"
27+
* Should be compatible with most terminals.
28+
*/
29+
case Ansi8;
30+
/*
31+
* 24-bit Ansi colors (RGB).
32+
* Output syntax is: "ESC[38;5;${foreGroundColorcodeRed};${foreGroundColorcodeGreen};${foreGroundColorcodeBlue};48;5;${backGroundColorcodeRed};${backGroundColorcodeGreen};${backGroundColorcodeBlue}m"
33+
* May be compatible with many modern terminals.
34+
*/
35+
case Ansi24;
36+
37+
public function convertFromHexToAnsiColorCode(string $hexColor): string
38+
{
39+
$color = hexdec($hexColor);
40+
41+
$r = ($color >> 16) & 255;
42+
$g = ($color >> 8) & 255;
43+
$b = $color & 255;
44+
45+
return match ($this) {
46+
self::Ansi4 => (string) $this->convertFromRGB($r, $g, $b),
47+
self::Ansi8 => '8;5;'.((string) $this->convertFromRGB($r, $g, $b)),
48+
self::Ansi24 => sprintf('8;2;%d;%d;%d', $r, $g, $b)
49+
};
50+
}
51+
52+
private function convertFromRGB(int $r, int $g, int $b): int
53+
{
54+
return match ($this) {
55+
self::Ansi4 => $this->degradeHexColorToAnsi4($r, $g, $b),
56+
self::Ansi8 => $this->degradeHexColorToAnsi8($r, $g, $b)
57+
};
58+
}
59+
60+
private function degradeHexColorToAnsi4(int $r, int $g, int $b): int
61+
{
62+
if (0 === round($this->getSaturation($r, $g, $b) / 50)) {
63+
return 0;
64+
}
65+
66+
return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255);
67+
}
68+
69+
private function getSaturation(int $r, int $g, int $b): int
70+
{
71+
$r = $r / 255;
72+
$g = $g / 255;
73+
$b = $b / 255;
74+
$v = max($r, $g, $b);
75+
76+
if (0 === $diff = $v - min($r, $g, $b)) {
77+
return 0;
78+
}
79+
80+
return (int) $diff * 100 / $v;
81+
}
82+
83+
/**
84+
* Inspired from https://github.com/ajalt/colormath/blob/e464e0da1b014976736cf97250063248fc77b8e7/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/Ansi256.kt code (MIT license).
85+
*/
86+
private function degradeHexColorToAnsi8(int $r, int $g, int $b): int
87+
{
88+
if ($r === $g && $g === $b) {
89+
if ($r < 8) {
90+
return 16;
91+
}
92+
93+
if ($r > 248) {
94+
return 231;
95+
}
96+
97+
return (int) (round((($r - 8) / 247) * 24)) + 232;
98+
} else {
99+
return 16 +
100+
(36 * (int) (round($r / 255 * 5))) +
101+
(6 * (int) (round($g / 255 * 5))) +
102+
(int) (round($b / 255 * 5));
103+
}
104+
}
105+
}

src/Symfony/Component/Console/Tests/TerminalTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ public function testGetTermColorSupport(?string $testColorTerm, ?string $testTer
104104
$oriTerm = getenv('TERM');
105105

106106
try {
107-
putenv($testColorTerm ? "COLORTERM={$testColorTerm}" : "COLORTERM");
108-
putenv($testTerm ? "TERM={$testTerm}" : "TERM");
107+
putenv($testColorTerm ? "COLORTERM={$testColorTerm}" : 'COLORTERM');
108+
putenv($testTerm ? "TERM={$testTerm}" : 'TERM');
109109

110110
$this->assertSame($expected, Terminal::getTermColorSupport());
111111
} finally {

0 commit comments

Comments
 (0)