Permalink
Browse files

feature #29168 [Console] Add hyperlinks support (ostrolucky)

This PR was squashed before being merged into the 4.3-dev branch (closes #29168).

Discussion
----------

[Console] Add hyperlinks support

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21207
| License       | MIT
| Doc PR        |

For details about this see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda

Here's one idea/use case which could utilize this feature (not implemented in this PR as it requires more work)
![stack trace with anchors](https://user-images.githubusercontent.com/496233/48305600-00d4c300-e52e-11e8-94e6-33713ff09d50.png)

I checked this in cmd.exe as well and no sideffects there

Commits
-------

db750ed [Console] Add hyperlinks support
  • Loading branch information...
fabpot committed Dec 10, 2018
2 parents 0d01a5f + db750ed commit 58b29d6a111230ae61ff628ddd9ffa3f161ebf74
@@ -1,6 +1,11 @@
CHANGELOG
=========

4.3.0
-----

* added support for hyperlinks

4.2.0
-----

@@ -141,7 +141,7 @@ public function formatAndWrap(string $message, int $width)
{
$offset = 0;
$output = '';
$tagRegex = '[a-z][a-z0-9,_=;-]*+';
$tagRegex = '[a-z][^<>]*+';
$currentLineLength = 0;
preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as $i => $match) {
@@ -215,6 +215,8 @@ private function createStyleFromString(string $string)
$style->setForeground($match[1]);
} elseif ('bg' == $match[0]) {
$style->setBackground($match[1]);
} elseif ('href' === $match[0]) {
$style->setHref($match[1]);
} elseif ('options' === $match[0]) {
preg_match_all('([^,;]+)', $match[1], $options);
$options = array_shift($options);
@@ -52,6 +52,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
private $foreground;
private $background;
private $href;
private $options = array();
/**
@@ -118,6 +119,11 @@ public function setBackground($color = null)
$this->background = static::$availableBackgroundColors[$color];
}
public function setHref(string $url): void
{
$this->href = $url;
}
/**
* Sets some specific style option.
*
@@ -187,11 +193,14 @@ public function apply($text)
$setCodes[] = $this->background['set'];
$unsetCodes[] = $this->background['unset'];
}
if (\count($this->options)) {
foreach ($this->options as $option) {
$setCodes[] = $option['set'];
$unsetCodes[] = $option['unset'];
}
foreach ($this->options as $option) {
$setCodes[] = $option['set'];
$unsetCodes[] = $option['unset'];
}
if (null !== $this->href) {
$text = "\033]8;;$this->href\033\\$text\033]8;;\033\\";
}
if (0 === \count($setCodes)) {
@@ -228,47 +228,34 @@ public function testFormatToStringObject()
);
}
public function testNotDecoratedFormatter()
public function testFormatterHasStyles()
{
$formatter = new OutputFormatter(false);
$this->assertTrue($formatter->hasStyle('error'));
$this->assertTrue($formatter->hasStyle('info'));
$this->assertTrue($formatter->hasStyle('comment'));
$this->assertTrue($formatter->hasStyle('question'));
}
$this->assertEquals(
'some error', $formatter->format('<error>some error</error>')
);
$this->assertEquals(
'some info', $formatter->format('<info>some info</info>')
);
$this->assertEquals(
'some comment', $formatter->format('<comment>some comment</comment>')
);
$this->assertEquals(
'some question', $formatter->format('<question>some question</question>')
);
$this->assertEquals(
'some text with inline style', $formatter->format('<fg=red>some text with inline style</>')
);
$formatter->setDecorated(true);
/**
* @dataProvider provideDecoratedAndNonDecoratedOutput
*/
public function testNotDecoratedFormatter(string $input, string $expectedNonDecoratedOutput, string $expectedDecoratedOutput)
{
$this->assertEquals($expectedDecoratedOutput, (new OutputFormatter(true))->format($input));
$this->assertEquals($expectedNonDecoratedOutput, (new OutputFormatter(false))->format($input));
}
$this->assertEquals(
"\033[37;41msome error\033[39;49m", $formatter->format('<error>some error</error>')
);
$this->assertEquals(
"\033[32msome info\033[39m", $formatter->format('<info>some info</info>')
);
$this->assertEquals(
"\033[33msome comment\033[39m", $formatter->format('<comment>some comment</comment>')
);
$this->assertEquals(
"\033[30;46msome question\033[39;49m", $formatter->format('<question>some question</question>')
);
$this->assertEquals(
"\033[31msome text with inline style\033[39m", $formatter->format('<fg=red>some text with inline style</>')
public function provideDecoratedAndNonDecoratedOutput()
{
return array(
array('<error>some error</error>', 'some error', "\033[37;41msome error\033[39;49m"),
array('<info>some info</info>', 'some info', "\033[32msome info\033[39m"),
array('<comment>some comment</comment>', 'some comment', "\033[33msome comment\033[39m"),
array('<question>some question</question>', 'some question', "\033[30;46msome question\033[39;49m"),
array('<fg=red>some text with inline style</>', 'some text with inline style', "\033[31msome text with inline style\033[39m"),
array('<href=idea://open/?file=/path/somefile.php&line=12>some URL</>', 'some URL', "\033]8;;idea://open/?file=/path/somefile.php&line=12\033\\some URL\033]8;;\033\\"),
);
}

0 comments on commit 58b29d6

Please sign in to comment.