Очистить последние две (и более) напечатанные строки в эмуляторе терминала Linux - PullRequest
0 голосов
/ 06 мая 2018

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

Один индикатор прогресса прост

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

"использовать ncurses"

Все говорят: "Используйте ncurses". Но, насколько я знаю, каждая программа ncurses должна начинаться с вызова initscr(), который действительно очищает весь экран. Ваше приглашение исчезло, история вашего терминала исчезла. Это не то, что я хочу.

Использовать terminfo из ncurses

Используйте возможности sc, ed и rc из terminfo, чтобы проиллюстрировать этот скрипт Bash (скрипт взят из этого вопроса ):

tput sc; while [ true ]; do tput ed; echo -e "$SECONDS\n$SECONDS\n$SECONDS"; sleep 1; tput rc; done

Это работает, но только в xterm. Мой термин urxvt игнорирует его, как, например, terminator.

Так, каковы другие варианты?

1 Ответ

0 голосов
/ 06 мая 2018

Как правильно заметил пользователь @Marged, escape-последовательности ANSI являются ответом.

Вот код C, который работает для меня. Решающим является строка 19, которая печатает последовательность ANSI, которая стирает последние две строки (число строк произвольно, это указано в последовательности):

#include <stdio.h>
#include <unistd.h>

void progressBar(int done, int total) {
    int i;
    printf("[");
    for (i=0; i<total; ++i) {
        printf((done < i) ? " " : "=");
    }
    printf("]\n");
}

int main() {
    int i;
    for (i=0; i<5; ++i) {
        progressBar(i, 4);
        progressBar(2*i, 8);
        if (i != 4) {
            printf("\033[2A");  // This erases last two lines!
            sleep(1);
        }
    }
    return 0;
}
...