Как вывести сообщения в стандартный поток вывода на другой поток при чтении из стандартного ввода GNU readline, не путая входные данные? - PullRequest
6 голосов
/ 21 февраля 2011

Извините за длинный заголовок.Я разрабатываю сетевую программу на C, которая может отображать сообщения, полученные из сети на stdout, и принимать пользовательский ввод на stdin через библиотеку readline GNU.Проблема заключается в том, что когда пользователь вводит команды в главном потоке через readline, сетевое сообщение поступает и выводится на стандартный вывод, который выдает что-то вроде этого:

Сценарий:

Ввод: 1234567890
Сетевое сообщение: Hello
Сетевое сообщение приходит, когда пользователь только что набрал "7"

Фактический вывод на терминале:

Input>1234567Hello
890_

Есть ли способ получить такой вывод?

Hello
Input> 1234567890_

ps _ - курсор.

Заранее спасибо!

Ответы [ 4 ]

6 голосов
/ 21 февраля 2011

ОК. Я нашел решение этой проблемы после поиска и сделал следующую замену printf (). Используя rl_replace_line ("", 0), он очистит текущую строку и поместит курсор в начало строки, затем я могу напечатать строку сообщения, а затем восстановить приглашение readline, заменить исходную строку на место восстановить позицию курсора.
Однако этот хак требует, чтобы любой вызов этой функции printf включал \ n в конце, иначе строка будет перезаписана readline.

#define printf(...) my_rl_printf(__VA_ARGS__)
void my_rl_printf(char *fmt, ...)
{
    int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0;
    char *saved_line;
    int saved_point;
    if (need_hack)
    {
        saved_point = rl_point;
        saved_line = rl_copy_text(0, rl_end);
        rl_save_prompt();
        rl_replace_line("", 0);
        rl_redisplay();
    }

    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);

    if (need_hack)
    {
        rl_restore_prompt();
        rl_replace_line(saved_line, 0);
        rl_point = saved_point;
        rl_redisplay();
        free(saved_line);
    }
}
1 голос
/ 21 февраля 2011

Дамп readline и чтение каждые char, которые вводит пользователь.Если вы получаете какие-либо сетевые сообщения, когда пользователь вводит очистить текущую строку, выведите сетевое сообщение, а затем перепечатайте строку, которую вводит пользователь.

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

Если вы делаете сброс readline, тогда вы можете использовать curses, что облегчает ...

0 голосов
/ 21 февраля 2011

Это можно сделать с помощью библиотеки curses (3) .

0 голосов
/ 21 февраля 2011

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

...