次のようなコールバック関数を登録することにより、GNUReadlineを「選択」方式で使用します。
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
ユーザーには3つのコマンドを入力したように見えるため、これは悪いことです(3つの入力に対する3つの応答は、実際に起こったことである2つの入力に対する3つの応答と同じくらい可能です)。
厄介なハック(これは機能します)はこれを行うことです:
user input
SERVER OUTPUT
user input - INCOMPLETE
SERVER OUTPUT
user input
SERVER OUTPUT
の代わりにバックスペース('\ b')文字を印刷することでこれを改善できると思いまし" - INCOMPLETE"
たが、それは私のターミナル(Ubuntu Hardyのgnome-terminal)ではまったく何もしないようです。 なんらかの理由で、printf("ABC\b");
ただ印刷します。ABC
では、どうすれば不完全な入力行を消去できますか?なんらかの方法でバックスペースを印刷するか(印刷する数を把握できます-それはstrlen(rl_line_buffer)
)、またはまだ知らないReadline機能を使用しますか?