我正在尝试仅使用 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 输入不包装,上述操作就会起作用。当它包装恢复保存的光标位置不能按预期工作时,它似乎只恢复水平位置,而不是垂直位置。
即使输入行换行,如何使上述代码适应?
答案 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 > ");