Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c0f1da

Browse files
committed
Escape trailing \ in QuestionHelper autocompletion
Fixes #24652 Trailing backslash, being unescaped, used to escape closing formatting tag and, thus, formatting tag appeared in autocompletion
1 parent 0f9c6e6 commit 0c0f1da

File tree

2 files 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->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)