当行开头有输出时,“readline”

时间:2016-12-17 12:51:22

标签: c readline libreadline

我在我自己的程序中使用readline(版本6.3,默认[非vi]模式,Ubuntu 14.04)库,在终端窗口(在PC上)运行。当调用readline()时,如果前一个输出未被换行符终止,则会出现问题。

#include <stdio.h>
#include <readline/readline.h>

void main(void)
{
  // Previous output from some other part of application
  // which *may* have output stuff *not* terminated with a '\n'
  printf("Hello ");
  fflush(stdout);

  char *in = readline("OK> ");
}

所以这条线看起来像:

Hello OK> <caret here>

如果您键入少量字符(最多5个?)然后,比如说,Ctrl+U(可能是其他人)删除您的输入到目前为止一切似乎都很好--- readline()将插入符移回其自己的提示后,即删除5个字符。但是,请尝试输入,例如:

123456 <Ctrl+U>

现在它将删除回 Hello,只留下Hell,然后是插入符号,即删除6 + 6 == 12。所以你看:

Hello OK> 123456 <Ctrl+U>
Hell<caret here>

我需要两种可能的解决方案之一:

  1. 我已经意识到这取决于在出错的行上键入了多少个字符。任何修复/解决方法?

  2. 或者,我可以进行readline库调用,它会告诉我在调用readline()之前插入符号的位置/列是什么?然后至少我可以认识到这样一个事实,即我在现有线的末尾并输出\n,以便首先将自己定位在新线的开头。

  3. 我想我可以猜测,对于最多5个字符的类型,它最多会有5个退格空间,但是如果它没有从行首开始那么它会选择做一些混乱的事情吗?

    我看到GNU Readline: how to clear the input line?。这是同样的情况吗?解决方案似乎相当复杂。在启动readline()时,是否无法询问您所在的列,或者告诉它不要试图如此聪明地删除并坚持只删除实际输入的字符数?

1 个答案:

答案 0 :(得分:3)

事实证明,readline无法识别它是否从第1列开始,从而阻止自己弄乱线上的先前输出。

解决这个问题的唯一方法是自己识别起始列,如果当前位置列#1,则移动到下一行的开头。然后它总是从最左边的列开始,而不是在它已经在#1列时输出不必要的换行符。

我们可以为标准的“终端”执行此操作,因为它了解ANSI转义序列以查询当前行和&amp;终端列。查询通过字符发送到stdout,并通过终端插入stdin的字符读取响应。我们必须将终端设置为“原始”输入模式,以便可以立即读取响应字符并且不会回显。

所以这是代码:

rl_prep_terminal(1);       // put the terminal into "raw" mode
fputs("\033[6n", stdout);  // <ESC>[6n is ANSI sequence to query terminal position
int row, col;              // terminal will reply with <ESC>[<row>;<col>R
fscanf(stdin, "\033[%d;%dR", &row, &col);
rl_deprep_terminal();      // restore terminal "cooked" mode
if (col > 1)               // if beyond the first column...
  fputc('\n', stdout);     // output '\n' to move to start of next line

in = readline(prompt);     // now we can invoke readline() with our prompt