Skip to content

Instantly share code, notes, and snippets.

@Leko
Last active August 29, 2015 14:10
Show Gist options
  • Save Leko/facae857497953c43cac to your computer and use it in GitHub Desktop.
Save Leko/facae857497953c43cac to your computer and use it in GitHub Desktop.
PHPでCLIのプログレスバーを作るぞーうおー
<?php
$max = 100;
$progress = new \Cli\ProgressBar(STDOUT, $max);
for($i = 1; $i <= $max; $i++) {
$progress->current($i);
sleep(1);
}
$progress->done();
<?php
namespace Cli;
class ProgressBar
{
public $precision = 4;
public $fillChar = '#';
public $blankChar = ' ';
protected $max;
protected $width = 0;
protected $stream = null;
public function __construct($stream = STDOUT, $max = 0)
{
$this->stream = $stream;
$this->max = $max;
list($h, $this->width) = $this->getScreenSize();
}
public function current($current)
{
$line = $this->generateLine($current);
$this->write($line."\r");
}
public function done()
{
$this->write(PHP_EOL);
}
protected function getScreenSize()
{
$line = exec('stty -a | grep columns');
preg_match_all('/rows (\d+).*?columns (\d+)/', $line, $matches);
$sizes = [];
foreach(array_slice($matches, 1) as $match) $sizes[] = (int)$match[0];
return $sizes;
}
protected function generateLine($current)
{
$ratio = $current / $this->max;
$percent = round($ratio * 100, $this->precision);
$template = $this->template();
// shellの幅から必要な文字列の幅を引いて動的に幅を決定
$tokens = array_map('strlen', [$current, $this->max, $percent, $template]);
$rest = $this->width - array_sum($tokens);
$bar = $this->generateBar($percent, $rest);
$line = sprintf($template, $bar, $current, $this->max, $percent);
return $line;
}
protected function template()
{
return '[%s] %d/%d (%.'.$this->precision.'f%%)';
}
protected function generateBar($percent, $width)
{
$fill = (int)(($width) * ($percent / 100));
$filled = str_repeat($this->fillChar, $fill);
$blancked = str_repeat($this->blankChar, $width - $fill);
$bar = "{$filled}{$blancked}";
return $bar;
}
protected function write($line)
{
fwrite($this->stream, $line);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment