[Console] Progress helper enhancements

This commit is contained in:
Peter Kruithof 2013-03-08 11:24:33 +01:00 committed by Fabien Potencier
parent ea252671b0
commit 5ae76f0dbf
2 changed files with 143 additions and 16 deletions

View File

@ -177,8 +177,8 @@ class ProgressHelper extends Helper
/**
* Starts the progress output.
*
* @param OutputInterface $output An Output instance
* @param integer $max Maximum steps
* @param OutputInterface $output An Output instance
* @param integer $max Maximum steps
*/
public function start(OutputInterface $output, $max = null)
{
@ -236,6 +236,36 @@ class ProgressHelper extends Helper
}
}
/**
* Sets the current progress.
*
* @param integer $current The current progress
* @param Boolean $redraw Whether to redraw or not
*
* @throws \LogicException
*/
public function setCurrent($current, $redraw = false)
{
if (null === $this->startTime) {
throw new \LogicException('You must start the progress bar before calling setCurrent().');
}
$current = (int) $current;
if ($current < $this->current) {
throw new \LogicException('You can\'t regress the progress bar');
}
if ($this->current === 0) {
$redraw = true;
}
$this->current = $current;
if ($redraw || $this->current % $this->redrawFreq === 0) {
$this->display();
}
}
/**
* Outputs the current progress string.
*
@ -289,7 +319,7 @@ class ProgressHelper extends Helper
}
if ($this->max > 0) {
$this->widths['max'] = strlen($this->max);
$this->widths['max'] = $this->getLength($this->max);
$this->widths['current'] = $this->widths['max'];
} else {
$this->barCharOriginal = $this->barChar;
@ -325,7 +355,7 @@ class ProgressHelper extends Helper
}
}
$emptyBars = $this->barWidth - $completeBars - strlen($this->progressChar);
$emptyBars = $this->barWidth - $completeBars - $this->getLength($this->progressChar);
$bar = str_repeat($this->barChar, $completeBars);
if ($completeBars < $this->barWidth) {
$bar .= $this->progressChar;
@ -384,21 +414,41 @@ class ProgressHelper extends Helper
* Overwrites a previous message to the output.
*
* @param OutputInterface $output An Output instance
* @param string|array $messages The message as an array of lines or a single string
* @param string $messages The message
*/
private function overwrite(OutputInterface $output, $messages)
private function overwrite(OutputInterface $output, $message)
{
$length = $this->getLength($message);
// append whitespace to match the last line's length
if (($this->lastMessagesLength !== null) && ($this->lastMessagesLength > $length)) {
$message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
}
// carriage return
$output->write("\x0D");
if ($this->lastMessagesLength!==null) {
// clear the line with the length of the last message
$output->write(str_repeat("\x20", $this->lastMessagesLength));
// carriage return
$output->write("\x0D");
}
$output->write($messages);
$output->write($message);
$this->lastMessagesLength=strlen($messages);
$this->lastMessagesLength = $this->getLength($message);
}
/**
* Wrapper arround strlen: uses multi-byte function if available
*
* @param string $string
* @return integer
*/
private function getLength($string)
{
if (!function_exists('mb_strlen')) {
return strlen($string);
}
if (false === $encoding = mb_detect_encoding($string)) {
return strlen($string);
}
return mb_strlen($string, $encoding);
}
/**

View File

@ -74,6 +74,83 @@ class ProgressHelperTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($this->generateOutput(' 0/50 [>---------------------------] 0%').$this->generateOutput(' 1/50 [>---------------------------] 2%').$this->generateOutput(' 2/50 [=>--------------------------] 4%'), stream_get_contents($output->getStream()));
}
public function testOverwriteWithShorterLine()
{
$progress = new ProgressHelper();
$progress->setFormat(' %current%/%max% [%bar%] %percent%%');
$progress->start($output = $this->getOutputStream(), 50);
$progress->display();
$progress->advance();
// set shorter format
$progress->setFormat(' %current%/%max% [%bar%]');
$progress->advance();
rewind($output->getStream());
$this->assertEquals(
$this->generateOutput(' 0/50 [>---------------------------] 0%') .
$this->generateOutput(' 1/50 [>---------------------------] 2%') .
$this->generateOutput(' 2/50 [=>--------------------------] '),
stream_get_contents($output->getStream())
);
}
public function testSetCurrentProgress()
{
$progress = new ProgressHelper();
$progress->start($output = $this->getOutputStream(), 50);
$progress->display();
$progress->advance();
$progress->setCurrent(15);
$progress->setCurrent(25);
rewind($output->getStream());
$this->assertEquals(
$this->generateOutput(' 0/50 [>---------------------------] 0%') .
$this->generateOutput(' 1/50 [>---------------------------] 2%') .
$this->generateOutput(' 15/50 [========>-------------------] 30%') .
$this->generateOutput(' 25/50 [==============>-------------] 50%'),
stream_get_contents($output->getStream())
);
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage You must start the progress bar
*/
public function testSetCurrentBeforeStarting()
{
$progress = new ProgressHelper();
$progress->setCurrent(15);
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage You can't regress the progress bar
*/
public function testRegressProgress()
{
$progress = new ProgressHelper();
$progress->start($output = $this->getOutputStream(), 50);
$progress->setCurrent(15);
$progress->setCurrent(10);
}
public function testMultiByteSupport()
{
if (!function_exists('mb_strlen') || (false === $encoding = mb_detect_encoding('■'))) {
$this->markTestSkipped('The mbstring extension is needed for multi-byte support');
}
$progress = new ProgressHelper();
$progress->start($output = $this->getOutputStream());
$progress->setBarCharacter('■');
$progress->advance(3);
rewind($output->getStream());
$this->assertEquals($this->generateOutput(' 3 [■■■>------------------------]'), stream_get_contents($output->getStream()));
}
protected function getOutputStream()
{
return new StreamOutput(fopen('php://memory', 'r+', false));
@ -86,10 +163,10 @@ class ProgressHelperTest extends \PHPUnit_Framework_TestCase
$expectedout = $expected;
if ($this->lastMessagesLength !== null) {
$expectedout = str_repeat("\x20", $this->lastMessagesLength)."\x0D".$expected;
$expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
}
$this->lastMessagesLength = strlen($expected);
$this->lastMessagesLength = strlen($expectedout);
return "\x0D".$expectedout;
}