6

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>

次の 2 つの解決策のいずれかが必要です。

  1. 私は、それが間違っている行に入力された文字数に依存することに気付きました。修正/回避策はありますか?

  2. または、readline呼び出す前にキャレットがどの位置/列にあるかを教えてくれるライブラリ呼び出しはありますreadline()か? そうすれば、少なくとも、自分が既存の行の最後にいるという事実を認識し、\n最初に新しい行の先頭に位置するように a を出力することができました。

入力された最大5文字に対して最大5つのバックスペースが実行されると推測できると思いますが、それ以上に、行頭で開始されなかった場合に台無しになる何か他のことを選択しますか?

GNU Readline: 入力行をクリアするには? . これも同じ状況ですか?ソリューションはかなり複雑に見えます。を開始するときに現在どの列にいるのかを尋ねることはできませんか?readline()または、削除するのにそれほど賢くなく、実際に入力された文字数だけを削除することに固執するように指示することはできませんか?

4

1 に答える 1

4

は、列 #1 から始まってreadlineいないかどうかを認識できないため、行の前の出力を台無しにするのを停止します。

これに対処する唯一の方法は、開始列を自分で認識し、現在の位置が列 #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
于 2016-12-24T09:24:56.477 に答える