Skip to content

Commit

Permalink
feature #19495 [master][console] Allow multiple options to be set. (S…
Browse files Browse the repository at this point in the history
…pacePossum)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[master][console] Allow multiple options to be set.

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| License       | MIT

This PR add the possibility to set multiple options on a formatted string output.
Example:
```php
$output->writeln('<fg=green;options=bold,underscore>Test</>');
```

Secondly it makes the behavior on invalid values consistent.
```php
// current
$output->writeln('<fg=lime;>Test</>'); // throws exception
$output->writeln('<options=italic;>Test</>'); // silent ignore

// new
$output->writeln('<fg=lime;>Test</>'); // throws exception
$output->writeln('<options=italic;>Test</>'); // throws exception
```

All other changes are about making the code more strict or other SCA/CS fixes.

Commits
-------

1430138 Allow multiple options to be set.
  • Loading branch information
fabpot committed Sep 14, 2016
2 parents 0e63f47 + 1430138 commit a5108f4
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 7 deletions.
22 changes: 15 additions & 7 deletions src/Symfony/Component/Console/Formatter/OutputFormatter.php
Expand Up @@ -139,7 +139,7 @@ public function format($message)
$message = (string) $message;
$offset = 0;
$output = '';
$tagRegex = '[a-z][a-z0-9_=;-]*+';
$tagRegex = '[a-z][a-z0-9,_=;-]*+';
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as $i => $match) {
$pos = $match[1];
Expand Down Expand Up @@ -202,7 +202,7 @@ private function createStyleFromString($string)
return $this->styles[$string];
}

if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) {
return false;
}

Expand All @@ -214,12 +214,20 @@ private function createStyleFromString($string)
$style->setForeground($match[1]);
} elseif ('bg' == $match[0]) {
$style->setBackground($match[1]);
} else {
try {
$style->setOption($match[1]);
} catch (\InvalidArgumentException $e) {
return false;
} elseif ('options' === $match[0]) {
preg_match_all('([^,;]+)', $match[1], $options);
$options = array_shift($options);
foreach ($options as $option) {
try {
$style->setOption($option);
} catch (\InvalidArgumentException $e) {
trigger_error(sprintf('Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED);

return false;
}
}
} else {
return false;
}
}

Expand Down
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Bridge\PhpUnit\ErrorAssert;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

Expand Down Expand Up @@ -152,6 +153,72 @@ public function testInlineStyle()
$this->assertEquals("\033[34;41msome text\033[39;49m", $formatter->format('<fg=blue;bg=red>some text</fg=blue;bg=red>'));
}

/**
* @param string $tag
* @param string|null $expected
* @param string|null $input
*
* @dataProvider provideInlineStyleOptionsCases
*/
public function testInlineStyleOptions($tag, $expected = null, $input = null)
{
$styleString = substr($tag, 1, -1);
$formatter = new OutputFormatter(true);
$method = new \ReflectionMethod($formatter, 'createStyleFromString');
$method->setAccessible(true);
$result = $method->invoke($formatter, $styleString);
if (null === $expected) {
$this->assertFalse($result);
$expected = $tag.$input.'</'.$styleString.'>';
$this->assertSame($expected, $formatter->format($expected));
} else {
/* @var OutputFormatterStyle $result */
$this->assertInstanceOf(OutputFormatterStyle::class, $result);
$this->assertSame($expected, $formatter->format($tag.$input.'</>'));
$this->assertSame($expected, $formatter->format($tag.$input.'</'.$styleString.'>'));
}
}

public function provideInlineStyleOptionsCases()
{
return array(
array('<unknown=_unknown_>'),
array('<unknown=_unknown_;a=1;b>'),
array('<fg=green;>', "\033[32m[test]\033[39m", '[test]'),
array('<fg=green;bg=blue;>', "\033[32;44ma\033[39;49m", 'a'),
array('<fg=green;options=bold>', "\033[32;1mb\033[39;22m", 'b'),
array('<fg=green;options=reverse;>', "\033[32;7m<a>\033[39;27m", '<a>'),
array('<fg=green;options=bold,underscore>', "\033[32;1;4mz\033[39;22;24m", 'z'),
array('<fg=green;options=bold,underscore,reverse;>', "\033[32;1;4;7md\033[39;22;24;27m", 'd'),
);
}

/**
* @group legacy
* @dataProvider provideInlineStyleTagsWithUnknownOptions
* @requires function Symfony\Bridge\PhpUnit\ErrorAssert::assertDeprecationsAreTriggered
*/
public function testInlineStyleOptionsUnknownAreDeprecated($tag, $option)
{
ErrorAssert::assertDeprecationsAreTriggered(
array(sprintf('Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "Invalid option specified: "%s". Expected one of (bold, underscore, blink, reverse, conceal)".', $option)),
function () use ($tag) {
$formatter = new OutputFormatter(true);
$formatter->format($tag);
}
);
}

public function provideInlineStyleTagsWithUnknownOptions()
{
return array(
array('<options=abc;>', 'abc'),
array('<options=abc,def;>', 'abc'),
array('<fg=green;options=xyz;>', 'xyz'),
array('<fg=green;options=efg,abc>', 'efg'),
);
}

public function testNonStyleTag()
{
$formatter = new OutputFormatter(true);
Expand Down

0 comments on commit a5108f4

Please sign in to comment.