Skip to content

Commit

Permalink
bug #28638 [Console] Fix clearing sections containing questions (chal…
Browse files Browse the repository at this point in the history
…asr)

This PR was merged into the 4.1 branch.

Discussion
----------

[Console] Fix clearing sections containing questions

| Q             | A
| ------------- | ---
| Branch?       | 4.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #28615
| License       | MIT
| Doc PR        | n/a

Given:
```php
$section = $output->section();
$question = "What's your name?";
$name = (new QuestionHelper())->ask($input, $section, new Question($question));
$section->clear();
$section->writeln("$question (<info>$name</info>)");
```

Before:
![](https://i.imgur.com/nJdKXAo.gif)

After:
![](https://i.imgur.com/WdMtKvV.gif)

Commits
-------

81ec57d [Console] Fix clearing sections containing questions
  • Loading branch information
fabpot committed Oct 3, 2018
2 parents 3ae327c + 81ec57d commit b1f462f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 6 deletions.
5 changes: 5 additions & 0 deletions src/Symfony/Component/Console/Helper/QuestionHelper.php
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;
Expand Down Expand Up @@ -123,6 +124,10 @@ private function doAsk(OutputInterface $output, Question $question)
$ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
}

if ($output instanceof ConsoleSectionOutput) {
$output->addContent($ret);
}

$ret = \strlen($ret) > 0 ? $ret : $question->getDefault();

if ($normalizer = $question->getNormalizer()) {
Expand Down
18 changes: 13 additions & 5 deletions src/Symfony/Component/Console/Output/ConsoleSectionOutput.php
Expand Up @@ -77,6 +77,18 @@ public function getContent(): string
return implode('', $this->content);
}

/**
* @internal
*/
public function addContent(string $input)
{
foreach (explode(PHP_EOL, $input) as $lineContent) {
$this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1;
$this->content[] = $lineContent;
$this->content[] = PHP_EOL;
}
}

/**
* {@inheritdoc}
*/
Expand All @@ -88,11 +100,7 @@ protected function doWrite($message, $newline)

$erasedContent = $this->popStreamContentUntilCurrentSection();

foreach (explode(PHP_EOL, $message) as $lineContent) {
$this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1;
$this->content[] = $lineContent;
$this->content[] = PHP_EOL;
}
$this->addContent($message);

parent::doWrite($message, true);
parent::doWrite($erasedContent, false);
Expand Down
Expand Up @@ -13,17 +13,20 @@

use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Question\Question;

class ConsoleSectionOutputTest extends TestCase
{
private $stream;

protected function setUp()
{
$this->stream = fopen('php://memory', 'r+', false);
$this->stream = fopen('php://memory', 'r+b', false);
}

protected function tearDown()
Expand Down Expand Up @@ -137,4 +140,24 @@ public function testMultipleSectionsOutput()
rewind($output->getStream());
$this->assertEquals('Foo'.PHP_EOL.'Bar'.PHP_EOL."\x1b[2A\x1b[0JBar".PHP_EOL."\x1b[1A\x1b[0JBaz".PHP_EOL.'Bar'.PHP_EOL."\x1b[1A\x1b[0JFoobar".PHP_EOL, stream_get_contents($output->getStream()));
}

public function testClearSectionContainingQuestion()
{
$inputStream = fopen('php://memory', 'r+b', false);
fwrite($inputStream, "Batman & Robin\n");
rewind($inputStream);

$input = $this->getMockBuilder(StreamableInputInterface::class)->getMock();
$input->expects($this->once())->method('isInteractive')->willReturn(true);
$input->expects($this->once())->method('getStream')->willReturn($inputStream);

$sections = array();
$output = new ConsoleSectionOutput($this->stream, $sections, OutputInterface::VERBOSITY_NORMAL, true, new OutputFormatter());

(new QuestionHelper())->ask($input, $output, new Question('What\'s your favorite super hero?'));
$output->clear();

rewind($output->getStream());
$this->assertSame('What\'s your favorite super hero?'.PHP_EOL."\x1b[2A\x1b[0J", stream_get_contents($output->getStream()));
}
}

0 comments on commit b1f462f

Please sign in to comment.