4

我正在尝试仅使用readline和 ANSI 转义码编写控制台聊天客户端。

我的目标是让终端处理聊天历史记录的回滚和滚动,同时始终在消息后提供readline提示以供新输入。

我已经用我的两个线程尝试了以下操作。我的控制台输入线程:

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 回答