【问题标题】:How can I suppress readline to print something and then restore it?我怎样才能抑制 readline 打印一些东西然后恢复它?
【发布时间】:2013-03-13 23:54:25
【问题描述】:

我正在尝试仅使用 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 输入不换行,上述方法就有效。当它包裹恢复保存的光标位置时并没有按预期工作,它似乎只恢复了水平位置,而不是垂直位置。

即使输入行换行,我如何调整上述代码工作?

【问题讨论】:

  • 请参阅this question 以获得对所需行为的更好描述。但是,当用户输入包含多行时,该问题并未涵盖或解决我的具体问题。

标签: c readline ansi-escape


【解决方案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 > ");

我不知道在发布我的问题之前我怎么没看到。

【讨论】:

    【解决方案2】:

    我的灵感来自于如何 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 > ");
    

    【讨论】:

      猜你喜欢
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      • 2011-01-31
      • 2023-03-22
      相关资源
      最近更新 更多