4

readlineとANSIエスケープコードのみを使用してコンソールチャットクライアントを作成しようとしています。

私の目標は、新しい入力のメッセージの後に常にreadlineプロンプトを表示しながら、端末にチャット履歴のスクロールバックとスクロールを処理させることです。

私は2つのスレッドで次のことを試しました。私のコンソール入力スレッドは次のことを行います。

printf("\x1B[s"); // Save cursor position
message = readline("Prompt > ");

そして、私のメッセージ受信スレッドは次のことを行います。

message = receive_message(); // Blocks for next message
printf("\x1B[u"); // Restore cursor to before the prompt
printf("\x1B[J"); // Erase readline prompt and input (down to bottom of screen)
printf("%s\n", message); // Print the message (where readline was)
printf("\x1B[s"); // Save new cursor position
rl_forced_update_display(); // Restore readline

上記は、 readline入力が折り返されない限り機能します。折り返すと、保存されたカーソル位置の復元が期待どおりに機能せず、垂直位置ではなく、水平位置のみが復元されるように見えます。

入力行が折り返されている場合でも、上記のコードを機能するようにするにはどうすればよいですか?

4

2 に答える 2

1

この質問には、はるかに優れた解決策が含まれていることがわかりました。私はここでこの質問に答えることに関連する引用された解決策からコードを複製しました:

message = receive_message();

// Solution
int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0;

int saved_point = rl_point;
char *saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();

printf(message);

rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);

完全を期すために、入力スレッドはカーソル保存がクリアされ、単純に次のようになります。

message = readline("Prompt > ");

質問を投稿する前に、どうして見えなかったのかわかりません。

于 2013-03-21T07:41:17.647 に答える
0

ラップしたかどうかを手動で把握するために、Cで端子幅を取得する方法に触発されました。

readlineプロンプトの前に何かを印刷する必要がある場合は、次のようにします。

message = receive_message(); // Blocks for next message

/* Solution */
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // Get terminal dimensions
printf("\r"); // Move cursor to the begining of the line
// Calculate the length of the prompt and cursor position
int readline_length = rl_point + strlen(rl_prompt);
// Integer divide cursor position by the terminal width
int wrapped_lines = readline_length/w.ws_col;
// If there are wraped lines
if (wrapped_lines > 0)
    // move the cursor up by that number of lines
    printf("\x1B[%dA", wrapped_lines);
printf("\r"); // Move cursor to the beginning of the line
printf("\x1B[J"); // Erase readline prompt and input (down to bottom of screen)

printf("%s\n", message); // Print the message (where readline was)
rl_forced_update_display(); // Restore readline

完全を期すために、入力スレッドはカーソル保存がクリアされ、単純に次のようになります。

message = readline("Prompt > ");
于 2013-03-14T02:32:12.453 に答える