Skip to content

Commit 173b5ea

Browse files
bug #30354 [Console] handles multi-byte characters in autocomplete (jls-esokia)
This PR was merged into the 3.4 branch. Discussion ---------- [Console] handles multi-byte characters in autocomplete fixes #29966 | Q | A | ------------- | --- | Branch? | 3.4 <!-- see below --> | Bug fix? | yes | New feature? | no <!-- don't forget to update src/**/CHANGELOG.md files --> | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | #29966 <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | - <!-- required for new features --> I used the `mb_ord` to detect whether the amount of bytes read is valid before proceeding. I limit the number of bytes read to 4 before giving up because characters can use at most 4 bytes. The test passes with or without the fix though. Commits ------- 47320a6 handles multi-byte characters in autocomplete
2 parents 4cc1006 + 47320a6 commit 173b5ea

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu
308308

309309
continue;
310310
} else {
311+
if ("\x80" <= $c) {
312+
$c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]);
313+
}
314+
311315
$output->write($c);
312316
$ret .= $c;
313317
++$i;

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,43 @@ public function testAskWithAutocompleteWithExactMatch()
237237
$this->assertSame('b', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
238238
}
239239

240+
public function getInputs()
241+
{
242+
return [
243+
['$'], // 1 byte character
244+
['¢'], // 2 bytes character
245+
[''], // 3 bytes character
246+
['𐍈'], // 4 bytes character
247+
];
248+
}
249+
250+
/**
251+
* @dataProvider getInputs
252+
*/
253+
public function testAskWithAutocompleteWithMultiByteCharacter($character)
254+
{
255+
if (!$this->hasSttyAvailable()) {
256+
$this->markTestSkipped('`stty` is required to test autocomplete functionality');
257+
}
258+
259+
$inputStream = $this->getInputStream("$character\n");
260+
261+
$possibleChoices = [
262+
'$' => '1 byte character',
263+
'¢' => '2 bytes character',
264+
'' => '3 bytes character',
265+
'𐍈' => '4 bytes character',
266+
];
267+
268+
$dialog = new QuestionHelper();
269+
$dialog->setHelperSet(new HelperSet([new FormatterHelper()]));
270+
271+
$question = new ChoiceQuestion('Please select a character', $possibleChoices);
272+
$question->setMaxAttempts(1);
273+
274+
$this->assertSame($character, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
275+
}
276+
240277
public function testAutocompleteWithTrailingBackslash()
241278
{
242279
if (!$this->hasSttyAvailable()) {

0 commit comments

Comments
 (0)