[Console] ProgressIndicator fails to clear properly when used in sections
Symfony version(s) affected
symfony/console v6.4.4
Description
Multiple ProgressIndicator work as expected for the first handful of advance() calls, but eventually begin to eat up all previous console output.
Run the script below to observe. Progress indicators will update as expected, but after a few iterations, all previous output already in the console window will disappear line by line.
How to reproduce
$section1 = $output->section();
$section2 = $output->section();
$progress1 = new ProgressIndicator($section1);
$progress2 = new ProgressIndicator($section2);
$progress1->start('Indicator 1');
$progress2->start('Indicator 2');
$i = 0;
while (++$i < 100) {
$progress1->advance();
$progress2->advance();
usleep(50000);
}
Possible Solution
The problem appears to be how ProgressIndicator::overwrite() handles clearing the line.
Currently, it does the following:
$this->output->write("\x0D\x1B[2K");
This doesn't seem to be correct when used in a section. Changing it to the following fixes the bug:
use Symfony\Component\Console\Output\ConsoleSectionOutput;
...
if ($this->output instanceof ConsoleSectionOutput) {
$this->output->clear(1);
} else {
$this->output->write("\x0D\x1B[2K");
}
Additional Context
No response
Hello,
Thank you for spotting this issue and posting this message.
I was able to reproduce the issue, and even worst, it happens without sections too. The output is a bit different, but the problem is related on how the ProgressIndicator clear the lines:
$progress3 = new ProgressIndicator($output);
$progress4 = new ProgressIndicator($output);
$progress3->start('Indicator 3');
$progress4->start('Indicator 4');
$i = 0;
while (++$i < 100) {
$progress4->advance();
$progress3->advance();
usleep(50000);
}
$progress3->finish('Finished');
$progress4->finish('Finished');
It only shows the output for the Indicator 4 and writes Finished twice at the end.
I'm not really sure how to fix this issue but I've been thinking about a possible solution:
// Each time we call the advance method:
// Retrieve the position of the old indicator
// Remove the line / the old indicator
// Move cursor at last position
// Write the updated indicator
In this way, it would be possible to write new entries between each modification of the indicator, and it would always be displayed in the last position.
And since the updated indicator would always be in last position, if we use two indicators at the same time, they should not conflict with each other.
Hey, thanks for your report! There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?
Friendly reminder that this issue exists. If I don't hear anything I'll close this.
@NeilPeyssard up for a PR?
Hey, thanks for your report! There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?
I've experienced the issue as well. No workaround so far.
Hey, thanks for your report! There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?
It's still relevant and no workaround so far.