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

4

我正在编写一个名为"libansi"的库。

我想要捕获ansi序列\x1b[6n的返回码。

我尝试过一些解决方法,但是都没用。

例如:

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

rep返回"\033[6n"是什么意思?有人知道吗?感谢您的帮助。

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

a=input(print("\033[6n", end='')

但是我需要按下输入键才能获取光标位置。

所有像这样的解决方案都无法工作,因为在sh/bash命令中的ANSI序列被回显到子shell中。 - Daudré-Vignier Charles
1个回答

5
问题在于,默认情况下stdin是带有缓冲区的,当将序列写入stdout之后,终端会将其响应发送到stdin,而不是stdout。因此,终端就像按下实际键盘上的按键一样,但没有回车。
诀窍在于使用tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW),并在此之前通过termios.getattr将终端属性存储在变量中以恢复默认行为。通过设置cbreak,您可以立即从stdin读取os.read(sys.stdin.fileno(), 1),这也会抑制终端的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]))

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