在向stdout显示消息时,请勿打扰用户输入

时间:2013-01-16 21:03:26

标签: python stdout stdin readline

我刚刚做了一个聊天CLI应用程序,实际上工作得非常好!

不幸的是,当一个人输入一条消息并同时接收其他消息时,这两个消息都是隔行扫描的......这很糟糕:

elton: Hey!
john: how are you doing?
fine anjohn: still not to bed?!
d john: haha
you?elton: fine and you?

我正在寻找避免此类问题的方法。例如“保留”用户输入的最后一行或在收到数据时处理某些操作以重新计算用户输入的位置。

经过一番研究后,我发现我将使用getch()逐个检索每个字符。这样我就可以定期检查新消息是否等待显示并处理这种情况。

但是如果我使用getch(),我必须手动重新定义基本操作(例如退格,左右移动......),某些字符需要多个字节。简而言之,它无法使用。

2 个答案:

答案 0 :(得分:1)

执行此类操作的常用方法是编写“控制台模式GUI”而不是纯CLI。

例如,您可以非常轻松地创建一个非常简单的界面,其中包含ROWS-2 x COLS输出窗口,1 x COLS分频器或模式线,以及1 x COLS输入窗口 - 如IRC客户端,emacs等所示。例如:

或者您可以执行拆分视图,其中ROWS/2 x COLS窗口可供其他人/人聊天,以及ROWS/2 x COLS窗口,用户的当前和以前的消息,如大多数早期Unix聊天程序中所示。

正如一些现代IRC客户所做的那样,在适当的地方弹出和离开的地方都会出现一些奇特的东西。

Python内置了curses支持,但不支持Windows。如果您需要跨平台解决方案或仅支持Windows的解决方案,请参阅curses-like library from cross-platform console app in python,答案可能就在那里。

这是来自IRC客户端BitchX的屏幕截图,让您了解在没有太多工作的情况下可能做到的事情: BitchX

答案 1 :(得分:1)

据我所知,你有几个选择。通常只是调用getch,你正在以所谓的“熟”模式运行终端。这意味着终端只按其到达的顺序显示字符,没有什么特别之处。但是,如你所发现的那样,你会遇到竞争条件。

选项1:您一次读取一个字符中的内容,缓冲整行。当一个新行到达并且你想打印出来时,你必须(a)抓住某种打印互斥(程序内部),(b)清除当前行(打印'\ r [空格] [空格] [空格] ... \ r'),(c)打印输入行+'\ n',(d)将前一个缓冲区恢复到屏幕(通过打印)并解锁互斥锁。< / p>

这变得丑陋。快速。正如您所发现的那样,没有行编辑支持或任何花哨的东西。这种方法唯一的好处是它可能在大约99%的终端中起作用。

选项2:您将终端设置为原始模式。在此模式下,您可以完全控制终端,但是您失去了非常基本的功能(例如,除非您手动输出,否则键入键不会显示它)。您仍然需要手动实现导航等功能,但至少它会起作用。这种方法可能是最灵活的,并且给你最大的控制权,但是很难像这样工作,这就是他们发明的原因......

选项3:您使用ncurses(或类似的终端库)。这些概念有点困难,但FAR比纯原始模式下的事情更容易学习。编辑和窗口(或者当你放置它时,保留一条线)是内置的。界面可以比熟食模式更漂亮。

编辑我在这里谈论很多关于* nix终端的内容,其中大多数都不适用于Windows。