Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 91bacf9

Browse filesBrowse files
[Console] Add support of RGB functional notation for output colors
1 parent 6c2608b commit 91bacf9
Copy full SHA for 91bacf9

File tree

3 files changed

+58
-0
lines changed
Filter options

3 files changed

+58
-0
lines changed

‎src/Symfony/Component/Console/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Add `TesterTrait::assertCommandIsSuccessful()` to test command
88
* Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement
9+
* Add `rgb(r, g, b)` notation support to output colors
910

1011
5.3
1112
---

‎src/Symfony/Component/Console/Color.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Color.php
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ final class Color
4949
'conceal' => ['set' => 8, 'unset' => 28],
5050
];
5151

52+
private const RGB_FUNCTIONAL_NOTATION_REGEX = '/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/';
53+
5254
private $foreground;
5355
private $background;
5456
private $options = [];
@@ -116,6 +118,10 @@ private function parseColor(string $color, bool $background = false): string
116118
return '';
117119
}
118120

121+
if (str_starts_with($color, 'rgb(')) {
122+
$color = $this->rgbToHex($color);
123+
}
124+
119125
if ('#' === $color[0]) {
120126
$color = substr($color, 1);
121127

@@ -177,4 +183,23 @@ private function getSaturation(int $r, int $g, int $b): int
177183

178184
return (int) $diff * 100 / $v;
179185
}
186+
187+
private function rgbToHex(string $color): string
188+
{
189+
if (!preg_match(self::RGB_FUNCTIONAL_NOTATION_REGEX, $color, $matches)) {
190+
throw new InvalidArgumentException(sprintf('Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "%s".', $color));
191+
}
192+
193+
$rgb = \array_slice($matches, 1);
194+
195+
$hexString = array_map(function ($element) {
196+
if ($element > 255 || $element < 0) {
197+
throw new InvalidArgumentException(sprintf('Invalid color component; value should be between 0 and 255, got %d.', $element));
198+
}
199+
200+
return str_pad(dechex((int) $element), 2, '0', \STR_PAD_LEFT);
201+
}, $rgb);
202+
203+
return '#'.implode('', $hexString);
204+
}
180205
}

‎src/Symfony/Component/Console/Tests/ColorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/ColorTest.php
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Console\Color;
16+
use Symfony\Component\Console\Exception\InvalidArgumentException;
1617

1718
class ColorTest extends TestCase
1819
{
@@ -42,6 +43,9 @@ public function testTrueColors()
4243

4344
$color = new Color('#ffffff', '#000000');
4445
$this->assertSame("\033[38;2;255;255;255;48;2;0;0;0m \033[39;49m", $color->apply(' '));
46+
47+
$color = new Color('rgb(255, 255, 255)', 'rgb(0, 0, 0)');
48+
$this->assertSame("\033[38;2;255;255;255;48;2;0;0;0m \033[39;49m", $color->apply(' '));
4549
}
4650

4751
public function testDegradedTrueColors()
@@ -59,4 +63,32 @@ public function testDegradedTrueColors()
5963
putenv('COLORTERM='.$colorterm);
6064
}
6165
}
66+
67+
/**
68+
* @dataProvider provideMalformedRgbStrings
69+
*/
70+
public function testMalformedRgbString(string $color, string $exceptionMessage)
71+
{
72+
$this->expectException(InvalidArgumentException::class);
73+
$this->expectExceptionMessage($exceptionMessage);
74+
75+
new Color($color);
76+
}
77+
78+
public function provideMalformedRgbStrings(): \Generator
79+
{
80+
yield ['rgb()', 'Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "rgb()".'];
81+
82+
yield ['rgb(0, 0)', 'Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "rgb(0, 0)".'];
83+
84+
yield ['rgb(0, 0, 0, 0)', 'Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "rgb(0, 0, 0, 0)".'];
85+
86+
yield ['rgb(-1, 0, 0)', 'Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "rgb(-1, 0, 0)".'];
87+
88+
yield ['rgb(invalid, 0, 0)', 'Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "rgb(invalid, 0, 0)".'];
89+
90+
yield ['rgb(256, 0, 0)', 'Invalid color component; value should be between 0 and 255, got 256.'];
91+
92+
yield ['rgb(0, 0, 0', 'Invalid RGB functional notation; should be of the form "rgb(r, g, b)", got "rgb(0, 0, 0".'];
93+
}
6294
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.