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

Skip to content

Commit 54427d7

Browse files
Merge branch '6.4' into 7.4
* 6.4: [Console] Make `ConsoleSectionOutput::overwrite()` atomic
2 parents d7d2b64 + 997de0a commit 54427d7

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

Output/ConsoleSectionOutput.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,31 @@ public function clear(?int $lines = null): void
8484
*/
8585
public function overwrite(string|iterable $message): void
8686
{
87-
$this->clear();
88-
$this->writeln($message);
87+
if (!$this->content || !$this->isDecorated()) {
88+
$this->writeln($message);
89+
90+
return;
91+
}
92+
93+
// Replace own content and write everything in a single cursor-up + erase
94+
// pass, to avoid the flicker (and the line-eating artifacts on some
95+
// terminals) caused by calling clear() then writeln() back-to-back.
96+
$linesCleared = $this->lines;
97+
$this->content = [];
98+
$this->lines = 0;
99+
100+
if (!is_iterable($message)) {
101+
$message = [$message];
102+
}
103+
104+
foreach ($message as $line) {
105+
$this->addContent($line, true);
106+
}
107+
108+
$erasedContent = $this->popStreamContentUntilCurrentSection($this->maxHeight ? min($this->maxHeight, $linesCleared) : $linesCleared);
109+
110+
parent::doWrite($this->getVisibleContent(), false);
111+
parent::doWrite($erasedContent, false);
89112
}
90113

91114
public function getContent(): string

Tests/Output/ConsoleSectionOutputTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,20 @@ public function testOverwriteMultipleLines()
200200
$this->assertEquals('Foo'.\PHP_EOL.'Bar'.\PHP_EOL.'Baz'.\PHP_EOL.\sprintf("\x1b[%dA", 3)."\x1b[0J".'Bar'.\PHP_EOL, stream_get_contents($output->getStream()));
201201
}
202202

203+
public function testOverwriteWithMaxHeightOverflow()
204+
{
205+
$sections = [];
206+
$output = new ConsoleSectionOutput($this->stream, $sections, OutputInterface::VERBOSITY_NORMAL, true, new OutputFormatter());
207+
$output->setMaxHeight(2);
208+
209+
$output->writeln(['One', 'Two']);
210+
// overwrite with more lines than the max height: only the last lines stay visible
211+
$output->overwrite('A'.\PHP_EOL.'B'.\PHP_EOL.'C');
212+
213+
rewind($output->getStream());
214+
$this->assertEquals('One'.\PHP_EOL.'Two'.\PHP_EOL."\x1b[2A\x1b[0J".'B'.\PHP_EOL.'C'.\PHP_EOL, stream_get_contents($output->getStream()));
215+
}
216+
203217
public function testAddingMultipleSections()
204218
{
205219
$sections = [];
@@ -223,7 +237,7 @@ public function testMultipleSectionsOutput()
223237
$output2->overwrite('Foobar');
224238

225239
rewind($output->getStream());
226-
$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()));
240+
$this->assertEquals('Foo'.\PHP_EOL.'Bar'.\PHP_EOL."\x1b[2A\x1b[0JBaz".\PHP_EOL.'Bar'.\PHP_EOL."\x1b[1A\x1b[0JFoobar".\PHP_EOL, stream_get_contents($output->getStream()));
227241
}
228242

229243
public function testMultipleSectionsOutputWithoutNewline()

0 commit comments

Comments
 (0)