在使用readline(阻塞)进行用户输入时,我希望从另一个线程异步地将文本行输出到控制台。此外,我希望从控制台中删除readline提示和当前的部分输入行,写入输出行,然后恢复readline提示符和部分用户行,这样看起来输出是在提示的"上方"写入的。
通过什么样的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, "tickn", 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"键入缓慢)
? tick
ftick
otick
otick
? tick
tick
bartick
tick
? tick
^C
所需输出:(输入"foo\nbar"缓慢键入)
tick
tick
tick
tick
tick
? foo
tick
tick
tick
tick
tick
? bar
tick
? ^C
我在我的程序omphalos的控制台版本中执行此操作(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){
fputc('r',fp);
}
每当有东西想要打印时,它就会获取锁并调用clear_for_output[(],将光标移动到当前行的开头。如果需要,它可以在此时通过调用rl_set_prompt()来更改提示。完成后,它调用wake_input_thread(),释放锁并重新显示。
我不确定这是否适用于这样的情况:你已经输入了一行以上的文本,并对此表示怀疑,而且现在不想正式发现什么可能是新的、令人沮丧的错误,所以你可以自己尝试一下。
应该使用的函数:
- CCD_ 1。打印
r
效果不佳,因为它只是将光标移动到行的开头,而没有删除行内容,而且当有多个输入行时,它无法正常工作 rl_on_new_line(); rl_redisplay();
(或rl_forced_update_display();
):打印后
似乎可以从任何线程调用这两个函数;然而,它可能会引入竞争条件(文档中没有说明从多个线程使用readline函数是否安全),因此最好使用rl_event_hook
和rl_getc_function
(因为持有密钥时不会调用rl_event_hook
)来调用主线程的函数。还记得在没有运行readline
函数时处理says。