Clear PHP CLI output

前端 未结 10 1944
一整个雨季
一整个雨季 2020-11-29 22:15

I\'m trying to get a \"live\" progress indicator working on my php CLI app. Rather than outputting as

1Done
2Done
3Done

I would rather it c

10条回答
  •  醉话见心
    2020-11-29 22:58

    I recently wrote a function that will also keep track of the number of lines it last output, so you can feed it arbitrary string lengths, with newlines, and it will replace the last output with the current one.

    With an array of strings:

    $lines = array(
        'This is a pretty short line',
        'This line is slightly longer because it has more characters (i suck at lorem)',
        'This line is really long, but I an not going to type, I am just going to hit the keyboard... LJK gkjg gyu g uyguyg G jk GJHG jh gljg ljgLJg lgJLG ljgjlgLK Gljgljgljg lgLKJgkglkg lHGL KgglhG jh',
        "This line has newline characters\nAnd because of that\nWill span multiple lines without being too long",
        "one\nmore\nwith\nnewlines",
        'This line is really long, but I an not going to type, I am just going to hit the keyboard... LJK gkjg gyu g uyguyg G jk GJHG jh gljg ljgLJg lgJLG ljgjlgLK Gljgljgljg lgLKJgkglkg lHGL KgglhG jh',
        "This line has newline characters\nAnd because of that\nWill span multiple lines without being too long",
        'This is a pretty short line',
    );
    

    One can use the following function:

    function replaceable_echo($message, $force_clear_lines = NULL) {
        static $last_lines = 0;
    
        if(!is_null($force_clear_lines)) {
            $last_lines = $force_clear_lines;
        }
    
        $term_width = exec('tput cols', $toss, $status);
        if($status) {
            $term_width = 64; // Arbitrary fall-back term width.
        }
    
        $line_count = 0;
        foreach(explode("\n", $message) as $line) {
            $line_count += count(str_split($line, $term_width));
        }
    
        // Erasure MAGIC: Clear as many lines as the last output had.
        for($i = 0; $i < $last_lines; $i++) {
            // Return to the beginning of the line
            echo "\r";
            // Erase to the end of the line
            echo "\033[K";
            // Move cursor Up a line
            echo "\033[1A";
            // Return to the beginning of the line
            echo "\r";
            // Erase to the end of the line
            echo "\033[K";
            // Return to the beginning of the line
            echo "\r";
            // Can be consolodated into
            // echo "\r\033[K\033[1A\r\033[K\r";
        }
    
        $last_lines = $line_count;
    
        echo $message."\n";
    }
    

    In a loop:

    foreach($lines as $line) {
        replaceable_echo($line);
        sleep(1);
    }
    

    And all lines replace each other.

    The name of the function could use some work, just whipped it up, but the idea is sound. Feed it an (int) as the second param and it will replace that many lines above instead. This would be useful if you were printing after other output, and you didn't want to replace the wrong number of lines (or any, give it 0).

    Dunno, seemed like a good solution to me.

    I make sure to echo the ending newline so that it allows the user to still use echo/print_r without killing the line (use the override to not delete such outputs), and the command prompt will come back in the correct place.

提交回复
热议问题