bug #35578 [Console][QuestionHelper] Use String width() to properly move the cursor backwards (fancyweb)

This PR was merged into the 5.1-dev branch.

Discussion
----------

[Console][QuestionHelper] Use String width() to properly move the cursor backwards

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | https://github.com/symfony/symfony/pull/35536#issuecomment-581343181
| License       | MIT
| Doc PR        | -

This bug can only be fixed on master since we need to require the String component. Once the component is required, we can iterate in the Console component to use it more where it is needed.

Commits
-------

67a1f55ce1 [Console][QuestionHelper] Use String width() to properly move the cursor backwards
This commit is contained in:
Fabien Potencier 2020-02-11 16:25:50 +01:00
commit da9f3af3e1
3 changed files with 25 additions and 3 deletions

View File

@ -22,6 +22,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Terminal;
use function Symfony\Component\String\s;
/**
* The QuestionHelper class provides helpers to interact with the user.
@ -242,9 +243,10 @@ class QuestionHelper extends Helper
} elseif ("\177" === $c) { // Backspace Character
if (0 === $numMatches && 0 !== $i) {
--$i;
$fullChoice = self::substr($fullChoice, 0, $i);
// Move cursor backwards
$output->write("\033[1D");
$output->write(sprintf("\033[%dD", s($fullChoice)->slice(-1)->width(false)));
$fullChoice = self::substr($fullChoice, 0, $i);
}
if (0 === $i) {

View File

@ -797,6 +797,25 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
$this->assertEquals(['AcmeDemoBundle', 'AsseticBundle'], $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
}
public function testAutocompleteMoveCursorBackwards()
{
// F<TAB><BACKSPACE><BACKSPACE><BACKSPACE>
$inputStream = $this->getInputStream("F\t\177\177\177");
$dialog = new QuestionHelper();
$helperSet = new HelperSet([new FormatterHelper()]);
$dialog->setHelperSet($helperSet);
$question = new Question('Question?', 'F⭐Y');
$question->setAutocompleterValues(['F⭐Y']);
$dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question);
$stream = $output->getStream();
rewind($stream);
$this->assertStringEndsWith("\033[1D\033[K\033[2D\033[K\033[1D\033[K", stream_get_contents($stream));
}
protected function getInputStream($input)
{
$stream = fopen('php://memory', 'r+', false);

View File

@ -19,7 +19,8 @@
"php": "^7.2.5",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8",
"symfony/service-contracts": "^1.1|^2"
"symfony/service-contracts": "^1.1|^2",
"symfony/string": "^5.1"
},
"require-dev": {
"symfony/config": "^4.4|^5.0",