8000 bug #24660 Escape trailing \ in QuestionHelper autocompletion (kamazee) · alexpott/symfony@aa49a00 · GitHub
[go: up one dir, main page]

Skip to content

Commit aa49a00

Browse files
bug symfony#24660 Escape trailing \ in QuestionHelper autocompletion (kamazee)
This PR was merged into the 2.7 branch. Discussion ---------- Escape trailing \ in QuestionHelper autocompletion | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#24652 | License | MIT Fixes symfony#24652 Trailing backslash, being unescaped, used to escape closing formatting tag and, thus, formatting tag appeared in autocompletion Output of the added test without the fix: ``` ./phpunit --filter testAutocompleteWithTrailingBackslash src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php #!/usr/bin/env php PHPUnit 6.0.13 by Sebastian Bergmann and contributors. Testing Symfony\Component\Console\Tests\Helper\QuestionHelperTest F 1 / 1 (100%) Time: 4.28 seconds, Memory: 6.00MB There was 1 failure: 1) Symfony\Component\Console\Tests\Helper\QuestionHelperTest::testAutocompleteWithTrailingBackslash Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'ExampleNamespace\' +'ExampleNamespace</hl>' ``` `OutputFormatter::escapeTrailingBackslash` is marked as `@internal`; however, this seems to be a valid use without exposing outside of the component. `OutputFormatter::escape`, which is not internal, doesn't fit here because escaping tags in autocompletion options is a deeper topic: there might be a valid use for tags in autocompletion and even if not, taking out the possibility to use them might be considered a BC break (even though it hasn't been advertised anywhere). Commits ------- 0c0f1da Escape trailing \ in QuestionHelper autocompletion
2 parents d3e419a + 0c0f1da commit aa49a00

File tree

2 file changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/Symfony/Component/Console/Helper/QuestionHelper.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Console\Helper;
1313

14+
use Symfony\Component\Console\Formatter\OutputFormatter;
1415
use Symfony\Component\Console\Input\InputInterface;
1516
use Symfony\Component\Console\Output\ConsoleOutputInterface;
1617
use Symfony\Component\Console\Output\OutputInterface;
@@ -303,7 +304,7 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu
303304
// Save cursor position
304305
$output->write("\0337");
305306
// Write highlighted text
306-
$output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
307+
$output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
307308
// Restore cursor position
308309
$output->write("\0338");
309310
}

src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,46 @@ public function testAskWithAutocompleteWithNonSequentialKeys()
156156
$this->assertEquals('AsseticBundle', $dialog->ask($this- 10000 >createInputInterfaceMock(), $this->createOutputInterface(), $question));
157157
}
158158

159+
public function testAutocompleteWithTrailingBackslash()
160+
{
161+
if (!$this->hasSttyAvailable()) {
162+
$this->markTestSkipped('`stty` is required to test autocomplete functionality');
163+
}
164+
165+
$inputStream = $this->getInputStream('E');
166+
167+
$dialog = new QuestionHelper();
168+
$dialog->setInputStream($inputStream);
169+
$helperSet = new HelperSet(array(new FormatterHelper()));
170+
$dialog->setHelperSet($helperSet);
171+
172+
$question = new Question('');
173+
$expectedCompletion = 'ExampleNamespace\\';
174+
$question->setAutocompleterValues(array($expectedCompletion));
175+
176+
$output = $this->createOutputInterface();
177+
$dialog->ask($this->createInputInterfaceMock(), $output, $question);
178+
179+
$outputStream = $output->getStream();
180+
rewind($outputStream);
181+
$actualOutput = stream_get_contents($outputStream);
182+
183+
// Shell control (esc) sequences are not so important: we only care that
184+
// <hl> tag is interpreted correctly and replaced
185+
$irrelevantEscSequences = array(
186+
"\0337" => '', // Save cursor position
187+
"\0338" => '', // Restore cursor position
188+
"\033[K" => '', // Clear line from cursor till the end
189+
);
190+
191+
$importantActualOutput = strtr($actualOutput, $irrelevantEscSequences);
192+
193+
// Remove colors (e.g. "\033[30m", "\033[31;41m")
194+
$importantActualOutput = preg_replace('/\033\[\d+(;\d+)?m/', '', $importantActualOutput);
195+
196+
$this->assertEquals($expectedCompletion, $importantActualOutput);
197+
}
198+
159199
public function testAskHiddenResponse()
160200
{
161201
if ('\\' === DIRECTORY_SEPARATOR) {

0 commit comments

Comments
 (0)
0