2012-02-15 8 views
1

出力メッセージを表示、私は別のスレッドからの非同期コンソールにテキストの出力ラインにたいです。さらに、私は、出力ラインが書き込まれた後、readlineプロンプトと部分的なユーザラインが復元され、出力が "上に"書かれたように見えるように、プロンプト。 readlineの再表示機能(またはその他)のどんな組み合わせによってGNU Readlineの(libreadline):ユーザ入力のためのreadline(ブロッキング)を使用しているが、非同期

はこれを達成することができますか?

(再表示機能ドキュメント:http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC35

問題のデモ

#include <readline/readline.h> 
    #include <readline/history.h> 
    #include <unistd.h> 
    #include <stdlib.h> 
    #include <pthread.h> 

    bool run = true; 

    void* log_thread(void*) 
    { 
      while (run) 
      { 
        sleep(1); 
        // WHAT TO DO HERE? 
        write(1, "tick\n", 5); 
      } 
    } 

    int main() 
    { 
      pthread_t t; 
      pthread_create(&t, 0, log_thread, 0); 

      while (true) 
      { 
        char* p = readline("? "); 
        free(p); 

        if (!p) 
          break; 
      } 

      run = false; 
      pthread_join(t,0); 
    } 

ビルド

$ g++ -pthread -lreadline test.cpp 
$ ./a.out 

観測出力:(入力「FOO \ NBAR \ n "はゆっくりと入力する)

? tick 
ftick 
otick 
otick 

? tick 
tick 
bartick 
tick 

? tick 
^C 

所望の出力:(ゆっくりと型指定された入力 "\ NBAR \ n個のfoo")

tick 
tick 
tick 
tick 
tick 
? foo 

tick 
tick 
tick 
tick 
tick 
? bar 

tick 
? ^C 
+0

あなたはすでに何を試しましたか? ;-) – alk

答えて

1

私は私のプログラムのオンパロスのコンソール版でこれをやっている(https://でgithubの.com/dankamongmen/omphalos)。この特定のコードはhttps://github.com/dankamongmen/omphalos/blob/master/src/ui/tty/tty.cから来ます。

私が持っている:

// Call whenever we generate output, so that the prompt is updated 
static inline void 
wake_input_thread(void){ 
    if(input_tid){ 
      pthread_kill(*input_tid,SIGWINCH); 
      rl_redisplay(); // FIXME probably need call from readline contex 
    } 
    pthread_mutex_unlock(&promptlock); 

}

static inline void 
clear_for_output(FILE *fp){ 
    assert(fputc('\r',fp) != EOF); 
} 

を何かが印刷したいときはいつでも)、それはロックがかかり、(clear_for_outputを呼び出し、の先頭にカーソルを移動現在の行。 rl_set_prompt()を呼び出すことによって、必要に応じてこの時点でプロンプトを変更することができます。完了すると、wake_input_thread()を呼び出してロックを解除し、再表示を行います。

テキストの行以上を入力した疑いがある場合にこれが機能するかどうかはわかりませんが、正にこの時点で新しいバグと恐ろしいバグを正式に発見するのは気にしませんあなた自身でそれを試すことができます。

+0

私は、SIGWINCH(すなわち、libreadlineコンテキストのスレッド)を適切に配信するなら、rl_redisplay()は必要ないと判断しました。私は自分のコードから削除し、以前と同じように動作しています。 –

+2

'assert(fputc( '\ r'、fp)!= EOF);'私のバグのようです。 assertがコンパイルされたときに、関数呼び出しも同様になるという明白な理由から、 'assert()'の中で呼び出される関数の副作用に頼るべきではありません。 – Alastair

+0

nice catch、@Alastair;あなたはもちろん正しい。 –

関連する問題