如何禁止readline打印然后恢复?

时间:2013-03-13 23:54:26

标签: c readline ansi-escape

我正在尝试仅使用 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 输入不包装,上述操作就会起作用。当它包装恢复保存的光标位置不能按预期工作时,它似乎只恢复水平位置,而不是垂直位置。

即使输入行换行,如何使上述代码适应?

2 个答案:

答案 0 :(得分:1)

This question原来包含了更好的解决方案。我已经复制了与回答此问题相关的引用解决方案中的代码:

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 > ");

我不知道在发布问题之前我没有看到。

答案 1 :(得分:0)

我的灵感来自如何get terminal width in 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 > ");