Jon*_*ave 6 c readline libreadline
我readline在我自己的程序中使用(版本 6.3,默认 [non-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> ");
}
Run Code Online (Sandbox Code Playgroud)
所以这条线看起来像:
Hello OK> <caret here>
Run Code Online (Sandbox Code Playgroud)
如果您键入少量字符(最多 5 个?),然后说Ctrl+U(可能是其他字符)删除您的输入,到目前为止一切似乎都很好 ---readline()将插入符号移回到它自己的提示之后,即删除5 个字符。但是,请尝试输入,例如:
123456 <Ctrl+U>
Run Code Online (Sandbox Code Playgroud)
现在,它会删除回进了Hello,只留下Hell就行了,然后插入符号,即删除6 + 6 = = 12。所以你看:
Hello OK> 123456 <Ctrl+U>
Hell<caret here>
Run Code Online (Sandbox Code Playgroud)
我需要两种可能的解决方案之一:
我意识到这取决于在出错的行上输入了多少个字符。任何修复/解决方法?
或者,是否有一个readline库调用可以告诉我插入符号在我调用之前的位置/列readline()?然后至少我可以认识到我在现有行的末尾并输出 a\n以便首先将自己定位在新行的开头这一事实。
我想我可以猜测最多输入 5 个字符,它最多可以执行 5 个退格,但除此之外,它选择做一些其他事情,如果它不是从行首开始就会搞砸?
我看到GNU Readline: how to clear the input line? . 这是同样的情况吗?解决方案看起来相当复杂。是否不能在开始时询问您在哪个列readline(),或者告诉它不要试图如此聪明地删除并坚持只删除实际输入的尽可能多的字符?
事实证明,它readline无法识别它是否不是从第 1 列开始,从而阻止自己弄乱该行之前的输出。
处理这个问题的唯一方法是我们自己识别起始列,如果当前位置不是第 1列,则向下移动到下一行的开头。然后它将始终从最左边的列开始,当它已经位于第 1 列时,不会输出不必要的换行符。
我们可以对标准“终端”执行此操作,因为它理解 ANSI 转义序列来查询终端的当前行和列。查询通过字符发送到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
Run Code Online (Sandbox Code Playgroud)