Python 3:捕获 `\x1b[6n` (`\033[6n`, `\e[6n`) ansi 序列的返回

Dau*_*les 4 python terminal ansi-escape python-3.4

我正在写一个“libansi”。我想捕获 ansi 序列 \x1b[6n 的返回代码我尝试了一些解决方法,但无济于事。

例子:

#!/usr/bin/python3.4
rep = os.popen("""a=$(echo "\033[6n") && echo $a""").read()
Run Code Online (Sandbox Code Playgroud)

代表返回“\033[6n”...

有人有主意吗?

感谢帮助。

编辑:我有一个部分解决方案:

a=input(print("\033[6n", end='')
Run Code Online (Sandbox Code Playgroud)

但这需要我在输入时按“回车”才能获取光标位置。

net*_*ego 5

问题是

  1. 默认情况下 stdin 被缓冲并且
  2. 将序列写入标准输出后,终端会将其响应发送到标准输入,而不是标准输出。所以终端的行为就像按下实际的键而不返回。

技巧是使用tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW)和 之前通过 in 变量存储终端属性termios.getattr来恢复默认行为。使用cbreakset,os.read(sys.stdin.fileno(), 1)您可以立即从 stdin 读取。这也会抑制来自终端的 ansi 控制代码响应。

def getpos():

    buf = ""
    stdin = sys.stdin.fileno()
    tattr = termios.tcgetattr(stdin)

    try:
        tty.setcbreak(stdin, termios.TCSANOW)
        sys.stdout.write("\x1b[6n")
        sys.stdout.flush()

        while True:
            buf += sys.stdin.read(1)
            if buf[-1] == "R":
                break

    finally:
        termios.tcsetattr(stdin, termios.TCSANOW, tattr)

    # reading the actual values, but what if a keystroke appears while reading
    # from stdin? As dirty work around, getpos() returns if this fails: None
    try:
        matches = re.match(r"^\x1b\[(\d*);(\d*)R", buf)
        groups = matches.groups()
    except AttributeError:
        return None

    return (int(groups[0]), int(groups[1]))
Run Code Online (Sandbox Code Playgroud)