Промежуточные интерфейсы командной строки - PullRequest
6 голосов
/ 26 октября 2011

Я некоторое время работал с C и достаточно опытен в простых интерфейсах командной строки.У меня также была игра с библиотекой curses для терминальных приложений, которые делают больше, чем просто записывают текст в stdout.Однако я не могу понять, где находится промежуточная точка - приложения, такие как wget или make, имеют, например, возможность обновлять текст, который они выводят (как, например, счетчик загрузок wget ииндикатор выполнения), не занимая весь экран.

Является ли этот тип интерфейса тем, для которого я должен использовать curses, или между ними есть какой-то шаг?Предпочтительно тот, который является кроссплатформенным.

Ответы [ 3 ]

10 голосов
/ 26 октября 2011

Вы можете сделать несколько простых вещей, просто напечатав символы возврата на обратную сторону '\b' и возврат каретки '\r' (без перевода строки). Backspace перемещает курсор назад на один символ, позволяя перезаписать вывод, а возврат каретки возвращает курсор назад к началу текущей строки, позволяя перезаписать текущую строку.

Вот простой пример индикатора выполнения:

int progress = 0;
while(progress < 100)
{
    // Note the carriage return at the start of the string and the lack of a
    // newline
    printf("\rProgress: %d%%", progress);
    fflush(stdout);

    // Do some work, and compute the new progress (0-100)
    progress = do_some_work();
}
printf("\nDone\n");

Обратите внимание, что вы должны делать это только в том случае, если вы пишете на реальный терминал (а не перенаправляетесь в файл или канал). Вы можете проверить это с помощью if(isatty(fileno(stdout)) { ... }. Конечно, то же самое было бы верно, если бы вы использовали любую другую библиотеку, такую ​​как curses или ncurses.

4 голосов
/ 26 октября 2011

От stdio до curses - это стандартная библиотека Unix / POSIX termios.Тривиальный пример программы, которая отключает эхо-символы и читает строку (примечание, без ошибок):

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

void munch_line()
{
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        ;
}

int main()
{
    int fd;
    struct termios tio;

    printf("Enter something: ");
    tcgetattr(fileno(stdin), &tio);
    tio.c_lflag &= ~ECHO;
    tcsetattr(fileno(stdin), TCSANOW, &tio);

    munch_line();
    putchar('\n');
}

Не забудьте снова включить эхо перед выходом из программы;)

3 голосов
/ 26 октября 2011

Если ваш терминал поддерживает escape-последовательности VT100 , вы можете использовать их для перемещения курсора:

printf("\x1b[%uD", n);  /* move cursor n steps to the left */
printf("\x1b[%uC", n);  /* move cursor n steps to the right */
printf("\x1b[K");       /* clear line from cursor to the right */
printf("\x1b[1K");      /* clear line from cursor to the left */
printf("\x1b[2K");      /* clear entire line */

Быстрый пример (curtest.c):

#include <stdio.h>

int main(void)
{
    printf("ZZZZZZZZZZ");
    printf("\x1b[%dD", 10U);  /* move cursor 10 steps to the left */
    printf("YYYYYYYYY");
    printf("\x1b[%dD", 9U);   /* move cursor 9 steps to the left */
    printf("XXXXXXXX");
    printf("\x1b[%dD", 2U);   /* move cursor 2 steps to the left */
    printf("\x1b[1K");       /* clear line from cursor to the left */
    printf("\r\n");
    return 0;
}

Если ваш терминал поддерживает эти управляющие коды, он должен напечатать

mizo@host:~/test> gcc curtest.c 
mizo@host:~/test> ./a.out
       XYZ
mizo@host:~/test>

В командной строке Windows нет встроенной поддержки VT100.

...