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

Keep stdin line at top or bottom of terminal screen

所以我正在编写一个项目,其中我 运行 一个程序不断 receives/sends 向其他计算机 运行 发送消息 运行 同一个程序。

receiver/sender 数据在线程上 运行 并打印到标准输出。 我得到这样的东西:

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

现在的问题是,有时我希望在终端中输入命令,问题是当我尝试输入命令时,新的信息消息或 MSG REC 被打印到标准输出。我有 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

然后我会按回车键并执行命令 status 但在终端中看起来很差。每 2-4 秒出现一条消息,因此这是一个问题。有解决这个问题的好方法吗?我尝试使用 ANSI 游标命令尝试在最后一行之前插入一个新行,这样最后一行将始终保留为输入行,我可以输入 "stat",稍等片刻,然后用 "us" 没有任何问题。

我也看到有人推荐 curses 但试图将其与我的程序集成完全弄乱了我的输出格式等(我认为它可能有点过头了)。

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

在 Linux.

上使用 Python2.7

编辑:让 James Mills 回答有效的更改: 每当我的线程打印新行时,我都必须使用它。

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

这是一个基本示例:

代码:

#!/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; all of the API I used in this example is straight from this standard library. Whilst using curses may or may not be "overkill" IHMO I would recommend the use of urwid 尤其是当您的应用程序的复杂性开始超出普通的诅咒时。