I use GNU Readline in the "select" fashion, by registering a callback function like so:
rl_callback_handler_install("", on_readline_input);
And then hooking up rl_callback_read_char
as the callback for my select()
loop for STDIN_FILENO
. That's all pretty standard stuff, and works fine.
Now, my program asynchronously prints messages to the screen, sometimes interleaved with input from the user. A "clean" session would look like this:
user input
SERVER OUTPUT
SERVER OUTPUT
user input
SERVER OUTPUT
But what if the user is midway through a line when the server response arrives? Then it gets ugly:
user input
SERVER OUTPUT
user inSERVER OUTPUT
put
SERVER OUTPUT
I fixed this simply by printing a newline before the server output if the user had typed anything (this is easy to tell by checking rl_line_buffer
), and then doing rl_forced_update_display()
after printing the server output. Now it looks like this:
user input
SERVER OUTPUT
user in
SERVER OUTPUT
user input
SERVER OUTPUT
This is better, but still not perfect. The problem comes when the user typed an entire line but didn't yet press Enter--then it looks like this:
user input
SERVER OUTPUT
user input
SERVER OUTPUT
user input
SERVER OUTPUT
This is bad because it appears to the user that they typed three commands (three responses for three inputs is just as possible as three responses for two inputs, which is what actually happened).
A nasty hack (which works) is to do this:
user input
SERVER OUTPUT
user input - INCOMPLETE
SERVER OUTPUT
user input
SERVER OUTPUT
I figured I could improve this by printing backspace ('\b') characters instead of " - INCOMPLETE"
, but that doesn't seem to do anything at all on my terminal (gnome-terminal on Ubuntu Hardy). printf("ABC\b");
just prints ABC
, for whatever reason.
So how can I erase the incomplete input line? Either by printing backspaces somehow (I can figure out how many to print--it's strlen(rl_line_buffer)
), or by using some Readline facility I don't yet know about?