Обновить многострочный вывод в Perl

Я работаю над сценарием, который предназначен для проверки определенного состояния, вывода результата, непродолжительного сна и затем запускает все заново. Выходные данные состоят из нескольких строк, и я хочу, чтобы скрипт обновлял выходные данные, что означает повторную печать на тех же строках. Он должен работать на Mac и Linux. Это то, что я до сих пор:

#! /usr/bin/perl

use strict;

print `tput sc`; # Store cursor position

my @lines;

while (1) {
    @lines = ();

    push(@lines, `tput rc`); # Restore cursor position
    push(@lines, `tput ed`); # Clear from cursor to end of screen
    push(@lines, `dd if=/dev/urandom bs=1 count=1`); # This is just an example

    print @lines;

    sleep 1;
}

Он работает нормально, пока я не вызываю скрипт с курсором в конце окна терминала. В последнем случае курсор остается в конце окна после печати, поэтому восстановление его исходного положения практически ничего не делает, а следующий вывод просто переходит на новую строку.

Как я могу избежать этого?

Я не хочу звонить tput clear или же tput init так как это может потерять все предыдущие команды и вывод. Я думал о прокрутке окна, чтобы подсказка находилась в верхней строке, прежде чем я начал выводить, но для этого потребовалась бы текущая строка курсора, и я не могу понять, как получить это с tput,

Кроме того, я могу запомнить количество напечатанных строк, а затем переместить курсор назад, используя tput rin, Однако это не работает, если вывод слишком длинный и прерывается на две или более клеммных линий.

1 ответ

Решение

Обычно программы, которые делают подобные вещи, либо используют фиксированное положение на экране, либо запоминают, сколько строк они вывели, и возвращаются к соответствующему количеству.

Также может быть полезно отметить, что большинство окон эмуляции терминала реагируют на команду "Очистить экран", просто прокручивая ее настолько, чтобы окно выглядело пустым. Это означает, что любая информация, ранее отображавшаяся на экране, по-прежнему доступна "вверху". Просто не очищайте экран при каждом проходе через while петля. Начиная с комбинации "Очистить / хранить", может быть именно то, что вам нужно.

Вместо того, чтобы обстреливать управление курсором, вы можете попробовать use Curses или же use Term::ANSIScreen для более точного управления вашим терминалом без всех этих дополнительных процессов.

Дополнительный кредит: если вы настаиваете на выделении для строк управления курсором, не порождайте tput Команды с каждой итерацией цикла. Запишите его вывод и просто напечатайте его заново для каждого прохода.

Изменение линии печати на что-то вроде print @ANSI_control_strings, @lines; может иметь дополнительное преимущество, которое scalar @lines будет точным счетом того, сколько строк вы можете захотеть отскочить назад, если вы переключитесь с обратных галочек на открытые каналы.

Другие вопросы по тегам