Skip to content

Commit dd049d3

Browse files
committed
add overwrite flag to allow non-decorated output
1 parent a5d09c3 commit dd049d3

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

Helper/ProgressBar.php

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\Console\Helper;
1313

14-
use Symfony\Component\Console\Output\NullOutput;
1514
use Symfony\Component\Console\Output\OutputInterface;
1615

1716
/**
@@ -42,6 +41,7 @@ class ProgressBar
4241
private $lastMessagesLength = 0;
4342
private $formatLineCount;
4443
private $messages;
44+
private $overwrite = true;
4545

4646
private static $formatters;
4747
private static $formats;
@@ -54,10 +54,19 @@ class ProgressBar
5454
*/
5555
public function __construct(OutputInterface $output, $max = 0)
5656
{
57-
// Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
58-
$this->output = $output->isDecorated() ? $output : new NullOutput();
57+
$this->output = $output;
5958
$this->setMaxSteps($max);
6059

60+
if (!$this->output->isDecorated()) {
61+
// disable overwrite when output does not support ANSI codes.
62+
$this->overwrite = false;
63+
64+
if ($this->max > 10) {
65+
// set a reasonable redraw frequency so output isn't flooded
66+
$this->setRedrawFrequency($max / 10);
67+
}
68+
}
69+
6170
$this->setFormat($this->determineBestFormat());
6271

6372
$this->startTime = time();
@@ -360,6 +369,16 @@ public function setCurrent($step)
360369
$this->setProgress($step);
361370
}
362371

372+
/**
373+
* Sets whether to overwrite the progressbar, false for new line
374+
*
375+
* @param bool $overwrite
376+
*/
377+
public function setOverwrite($overwrite)
378+
{
379+
$this->overwrite = (bool) $overwrite;
380+
}
381+
363382
/**
364383
* Sets the current progress.
365384
*
@@ -396,6 +415,11 @@ public function finish()
396415
$this->max = $this->step;
397416
}
398417

418+
if ($this->step === $this->max && !$this->overwrite) {
419+
// prevent double 100% output
420+
return;
421+
}
422+
399423
$this->setProgress($this->max);
400424
}
401425

@@ -438,6 +462,10 @@ public function display()
438462
*/
439463
public function clear()
440464
{
465+
if (!$this->overwrite) {
466+
return;
467+
}
468+
441469
$this->overwrite(str_repeat("\n", $this->formatLineCount));
442470
}
443471

@@ -470,8 +498,14 @@ private function overwrite($message)
470498
}
471499
}
472500

473-
// move back to the beginning of the progress bar before redrawing it
474-
$this->output->write("\x0D");
501+
if ($this->overwrite) {
502+
// move back to the beginning of the progress bar before redrawing it
503+
$this->output->write("\x0D");
504+
} elseif ($this->step > 0) {
505+
// move to new line
506+
$this->output->writeln('');
507+
}
508+
475509
if ($this->formatLineCount) {
476510
$this->output->write(sprintf("\033[%dA", $this->formatLineCount));
477511
}

Tests/Helper/ProgressBarTest.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,63 @@ public function testPercentNotHundredBeforeComplete()
311311
}
312312

313313
public function testNonDecoratedOutput()
314+
{
315+
$bar = new ProgressBar($output = $this->getOutputStream(false), 200);
316+
$bar->start();
317+
318+
for ($i = 0; $i < 200; $i++) {
319+
$bar->advance();
320+
}
321+
322+
$bar->finish();
323+
324+
rewind($output->getStream());
325+
$this->assertEquals(
326+
" 0/200 [>---------------------------] 0%\n".
327+
" 20/200 [==>-------------------------] 10%\n".
328+
" 40/200 [=====>----------------------] 20%\n".
329+
" 60/200 [========>-------------------] 30%\n".
330+
" 80/200 [===========>----------------] 40%\n".
331+
" 100/200 [==============>-------------] 50%\n".
332+
" 120/200 [================>-----------] 60%\n".
333+
" 140/200 [===================>--------] 70%\n".
334+
" 160/200 [======================>-----] 80%\n".
335+
" 180/200 [=========================>--] 90%\n".
336+
" 200/200 [============================] 100%",
337+
stream_get_contents($output->getStream())
338+
);
339+
}
340+
341+
public function testNonDecoratedOutputWithClear()
342+
{
343+
$bar = new ProgressBar($output = $this->getOutputStream(false), 50);
344+
$bar->start();
345+
$bar->setProgress(25);
346+
$bar->clear();
347+
$bar->setProgress(50);
348+
$bar->finish();
349+
350+
rewind($output->getStream());
351+
$this->assertEquals(
352+
" 0/50 [>---------------------------] 0%\n".
353+
" 25/50 [==============>-------------] 50%\n".
354+
" 50/50 [============================] 100%",
355+
stream_get_contents($output->getStream())
356+
);
357+
}
358+
359+
public function testNonDecoratedOutputWithoutMax()
314360
{
315361
$bar = new ProgressBar($output = $this->getOutputStream(false));
316362
$bar->start();
317363
$bar->advance();
318364

319365
rewind($output->getStream());
320-
$this->assertEquals('', stream_get_contents($output->getStream()));
366+
$this->assertEquals(
367+
" 0 [>---------------------------]\n".
368+
" 1 [->--------------------------]",
369+
stream_get_contents($output->getStream())
370+
);
321371
}
322372

323373
public function testParallelBars()

0 commit comments

Comments
 (0)