CLI进度条,带有可读的多行消息/信息

时间:2016-02-25 22:53:43

标签: symfony laravel

我的Laravel应用程序的一部分使用cli进行批处理。我正在尝试制作一个进度条,它会提供有用的信息,说明你在这个过程中走了多远。我正在进行批量处理的一件事是地址。我想格式化它有点类似于:

Processing addresses...

Local Shopping Mall
123 Fake street
Cityville, USA
12345
4/378 [>---------------------------]   1%

在第一个地址之后,我想在“处理地址”之后将光标移回到右边...'我想用新的地址覆盖旧地址。

现在,我得到了这个:

Processing addresses...
124 Fake street
Cityville, USA
12345

125 Fake street
Cityville, USA
12345

126 Fake street
Cityville, USA
12345

127 Fake street
Cityville, USA
12345

4/378 [>---------------------------]   1%

这里是(略微修改过的)代码我使用:

    public function handle()
    {
        $this->info('Processing addresses...');

        $addresses = \App\Address::all();
        $bar = $this->output->createProgressBar(count($addresses));
        foreach ($addresses as $address) {
            $bar->clear();
            $this->info("\r" . $this->_getFormattedAddress($address));
            $bar->advance();
            sleep(1);
        }
    }

    private function _getFormattedAddress(\App\Address $address){
        $out = "";
        $out .= $address->address1 . "\n";
        $out .= $address->address2 . "\n";
        $out .= $address->city . "\n";
        $out .= $address->region . "\n";
        $out .= $address->iso_code . "\n";
        $out .= $address->postal_code . "\n";
        return $out;
    }

1 个答案:

答案 0 :(得分:0)

" \ R" - 返回点到起始行和$ this-> info() - 将PHP_EOL添加到结束行。

如果需要将光标返回到顶部输出。我不知道Laravel可以做到与否。但是这门课帮助你:

class OutputCliHelper
{
    protected static $lastLines = 0;

    /**
     * @param $data
     * @return string
     */
    public static function replaceSingleLine($data){
        return "\r".$data;
    }

    /**
     * @return int
     */
    public static function getLastLines()
    {
        return static::$lastLines;
    }

    /**
     * @param      $data
     * @param null $lastLines
     * @return string
     */
    public static function replaceMultiLine($data, $lastLines = null)            {
        if(!is_null($lastLines)) {
            static::$lastLines = $lastLines;
        }

        $term_width = exec('tput cols', $toss, $status);
        if($status) {
            $term_width = 64; // Arbitrary fall-back term width.
        }

        $lineCount = 0;
        foreach(explode(PHP_EOL, $data) as $line) {
            $lineCount += count(str_split($line, $term_width));
        }

        $magic = '';
        // Erasure MAGIC: Clear as many lines as the last output had.
        for($i = 0; $i < static::$lastLines; $i++) {
            // Return to the beginning of the line
            $magic .= "\r";
            // Erase to the end of the line
            $magic .= "\033[K";
            // Move cursor Up a line
            $magic .= "\033[1A";
            // Return to the beginning of the line
            $magic .= "\r";
            // Erase to the end of the line
            $magic .= "\033[K";
            // Return to the beginning of the line
            $magic .= "\r";
            // Can be consolodated into
            // $magic .= "\r\033[K\033[1A\r\033[K\r";
        }
        static::$lastLines = $lineCount;

        return $magic.$data."\n";
    }
}

现在你需要获取输出字符串(内部PHP_EOL),然后调用:

$text = "{$id} Fake street\nCityville, USA\n12345";
$progressOutputString = ...;
$yourOutputString = $text.PHP_EOL.$progressOutputString;
echo OutputCliHelper::replaceMultiLine($yourOutputString);

例如:

public function handle()
{
    $output = new BufferedOutput(); //Symfony
    $progress = new ProgressBar($output); //Symfony
    $progress->start(10);
    for ($i = 0; $i < 10; $i++) {
        $progress->advance();
        $tmp = explode(PHP_EOL, $output->fetch());
        $string = array_pop($tmp);
        echo static::replaceMultiLine($string.PHP_EOL.mt_rand());
    }
}