将stdin行保留在终端屏幕的顶部或底部

时间:2015-05-15 11:59:20

标签: python terminal curses

所以我正在编写一个项目,我运行的程序不断接收/发送消息到运行相同程序的其他计算机。

数据的接收方/发送方正在线程上运行并打印到stdout。 我得到这样的东西:

[INFO] User 'blah' wants to send message to you.
[INFO] some other info
[MSG REC] Message 'hello' received from blah.

现在的问题是,有时我希望将命令输入终端,问题是当我尝试输入命令和新的信息消息或MSG REC打印到stdout时。我有quitstatus等命令。

>>表示输入行。

这样的事情可能会发生:

[INFO] User 'blah' wants to send message to you.
[INFO] some other info
[MSG REC] Message 'hello' received from blah.
>> stat[MSG REC] Message 'sup' received from Bob.
us

然后我按Enter键,命令status被执行,但在终端看起来很差。每隔2-4秒会显示一条消息,因此这是一个问题。有没有好办法解决这个问题?我尝试使用ANSI游标命令尝试在最后一行之前插入一个新行,这样最后一行将始终作为输入行保留,我可以输入“stat”,等待一段时间并用“我们”完成它而不用任何的问题。

我也看到人们推荐curses但是试图将它与我的程序集成在一起完全搞砸了我的输出格式化等等(我认为它可能过度杀伤)。

因此有一种简单的方法可以让线程在最后一行上方插入新的MSG REC行1行,这样最后一行将始终作为输入行保留>>以及我输入的其他内容。

在Linux上使用Python2.7。

编辑:詹姆斯米尔斯回答的变化: 每当我的线程打印一个新行时,我都必须使用它。

myY, myX = stdscr.getyx();        
str = "blah blah"; #my message I want to print
stdscr.addstr(len(lines), 0, str)
lines.append(str)
stdscr.move(myY, myX) #move cursor back to proper position

1 个答案:

答案 0 :(得分:8)

这是基本示例:

<强>代码:

#!/usr/bin/env python

from string import printable
from curses import erasechar, wrapper

PRINTABLE = map(ord, printable)

def input(stdscr):
    ERASE = input.ERASE = getattr(input, "ERASE", ord(erasechar()))
    Y, X = stdscr.getyx()
    s = []

    while True:
        c = stdscr.getch()

        if c in (13, 10):
            break
        elif c == ERASE:
            y, x = stdscr.getyx()
            if x > X:
                del s[-1]
                stdscr.move(y, (x - 1))
                stdscr.clrtoeol()
                stdscr.refresh()
        elif c in PRINTABLE:
            s.append(chr(c))
            stdscr.addch(c)

    return "".join(s)

def prompt(stdscr, y, x, prompt=">>> "):
    stdscr.move(y, x)
    stdscr.clrtoeol()
    stdscr.addstr(y, x, prompt)
    return input(stdscr)

def main(stdscr):
    Y, X = stdscr.getmaxyx()

    lines = []
    max_lines = (Y - 3)

    stdscr.clear()

    while True:
        s = prompt(stdscr, (Y - 1), 0)  # noqa
        if s == ":q":
            break

        # scroll
        if len(lines) > max_lines:
            lines = lines[1:]
            stdscr.clear()
            for i, line in enumerate(lines):
                stdscr.addstr(i, 0, line)

        stdscr.addstr(len(lines), 0, s)
        lines.append(s)

        stdscr.refresh()

wrapper(main)

这基本上设置了一个演示curses应用程序,它提示用户输入并在(24, 0)显示提示。演示终止于用户输入:q。对于任何其他输入,它会将输入附加到屏幕顶部。请享用! ( <BACKSAPCE>也有效!):)

见:curses;我在本例中使用的所有API都直接来自此标准库。虽然使用诅咒可能会或可能不会过度杀伤&#34; IHMO我建议使用urwid,特别是如果您的应用程序的复杂性开始超过普通的诅咒。