Я использую GNU Readline способом «выбора», регистрируя функцию обратного вызова следующим образом:
rl_callback_handler_install("", on_readline_input);
И затем подключение rl_callback_read_char
в качестве обратного вызова для моего select()
цикла для STDIN_FILENO
. Это все довольно стандартные вещи и отлично работает.
Теперь моя программа асинхронно печатает сообщения на экране, иногда чередующиеся с вводом от пользователя. «Чистая» сессия выглядела бы так:
user input
SERVER OUTPUT
SERVER OUTPUT
user input
SERVER OUTPUT
Но что, если пользователь находится посередине строки, когда приходит ответ сервера? Тогда становится некрасиво:
user input
SERVER OUTPUT
user inSERVER OUTPUT
put
SERVER OUTPUT
Я исправил это, просто напечатав новую строку перед выводом на сервер, если пользователь что-то набрал (это легко узнать, проверив rl_line_buffer
), а затем выполнил rl_forced_update_display()
после печати вывода на сервере. Теперь это выглядит так:
user input
SERVER OUTPUT
user in
SERVER OUTPUT
user input
SERVER OUTPUT
Это лучше, но все же не идеально. Проблема возникает, когда пользователь набрал всю строку, но еще не нажал Enter - тогда это выглядит так:
user input
SERVER OUTPUT
user input
SERVER OUTPUT
user input
SERVER OUTPUT
Это плохо, потому что пользователю кажется, что он набрал три команды (три ответа для трех входов - это как три ответа для двух входов, что на самом деле и произошло).
Гадкий хак (который работает) должен сделать это:
user input
SERVER OUTPUT
user input - INCOMPLETE
SERVER OUTPUT
user input
SERVER OUTPUT
Я подумал, что мог бы улучшить это, печатая символы backspace ('\ b') вместо " - INCOMPLETE"
, но это, похоже, ничего не делает на моем терминале (gnome-terminal на Ubuntu Hardy). printf("ABC\b");
просто печатает ABC
по любой причине.
Так как я могу стереть неполную строку ввода? Либо, печатая символы возврата (как я могу выяснить, сколько печатать - это strlen(rl_line_buffer)
), либо используя какое-либо средство Readline, о котором я еще не знаю?