在C语言中重新输出终端输入

3
我正在编写一个终端聊天软件,并希望在异步接收到其他用户的新消息时重新显示用户输入的内容。如果有新消息到达,我会将 "\x1B[2K" 打印到标准输出中(ANSI 清除当前行的转义代码),以清除当前行,然后将 "\r" 打印到最左边的位置,最后使用换行符打印接收到的消息。
现在我想重新显示用户已经输入的字符 - 我发现有一个特殊的字符 VREPRINT (http://www.gnu.org/software/libc/manual/html_node/Editing-Characters.html) 可以使用,在按下 CTRL-R 时它确实有效...但是,如果使用 termios 结构体中 c_cc[VREPRINT] 中的字符将其打印到标准输出中,它就不起作用了 - 是否可能以这种方式实现?
我不想使用其他库,如 readline 或 ncurses,因为这会显得过于臃肿...如果可能的话,我只想使用 ICANON 终端模式来使我的解决方案生效。
感谢您的支持!
1个回答

1

虽然可以向正在读取的tty设备写入内容,但这并不意味着出现的字符将被处理为输入字符。

您可以使用两个单独的shell会话(使用screentmux或者如果您在MacOSX上,则使用iTERM.app会话)进行测试。

在Session 1中,获取当前tty名称:

tty

假设会话1的tty名称为/dev/ttys000
然后输入以下内容,不要换行或回车 - 只需保留待处理内容:
echo abc def-

在第二个会话中(使用来自第一个会话的tty名称),输入以下命令:
echo foo >/dev/ttys000

字符串foo应该出现在待处理行中的第一节,如下所示:

echo abc def-foo

现在,回到会话1,按下“enter”(或return)键,使输入缓冲区完成并发送到shell,shell将解析第一个单词作为echo命令,并将后续参数作为要打印的文本。您应该看到字符串“abc def-”被回显,但不会看到foo。
这个测试清楚地表明,尽管它被发送到用于输入(和输出)的相同tty,但字符串foo从未放入输入缓冲区。
您可以尝试查看是否识别和处理特殊控制字符,但它们不会被处理。这些字符只被输出到终端,而不被处理。
为了处理特殊字符,它们必须通过连接到输入设备的套接字接收。
为了完成你想要做的事情,你需要走非规范化(stty -icanon)的路线,并处理代码中的每个字符,以便收集待处理输入并能够产生异步输出。
另外,使用nurses也不难,如果你正在编写基于终端的聊天程序,建议至少创建两个面板:一个“聊天”面板用于所有输出,以及一个“输入”面板用于用户输入。这样可以异步地接收来自其他用户的输出,以及来自“输入”面板的已完成命令,并将它们写入“聊天”面板,而不会干扰用户在“输入”面板中进行的当前命令。

所以在C中没有界面可以用来重新打印终端输入缓冲区? 我发现,如果我使用struct termios并设置“PENDIN” c_lflag,它几乎表现出我想要的行为。 如果我按任何键,它会重新打印输入缓冲区! - Termio
根据man页面,如果接收到特殊字符“VREPRINT”,则将设置此位域(“PENDIN”)。因此,我认为并希望有一种方法可以重新打印输入缓冲区,而不使用非规范模式。 - Termio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接