2012-02-15 49 views
1

在使用readline(阻塞)進行用戶輸入時,我想從另一個線程異步輸出文本行到控制檯。此外,我希望從控制檯中刪除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」 慢慢鍵入)

tick 
tick 
tick 
tick 
tick 
? foo 

tick 
tick 
tick 
tick 
tick 
? bar 

tick 
? ^C 
+0

你已經嘗試了什麼? ;-) – alk 2012-03-04 10:35:08

回答

1

我在我的程序胗的控制檯版本做這個(https://開頭的github的.com/dankamongmen /浮飾)。這個特定的代碼來自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()就沒有必要了。我已經將它從我的代碼中刪除了,事情和以前一樣。 – 2012-06-25 20:39:06

+2

'assert(fputc('\ r',fp)!= EOF);'對我來說看起來像一個bug。你不應該依賴'assert()'中調用的函數的副作用,這是因爲當assert被編譯出來時,函數調用也將是... – Alastair 2013-05-13 17:08:00

+0

nice catch,@Alastair;你當然是對的。 – 2013-05-14 21:33:59