Search code examples
pythonbashttyxterm

An xterm-compatible TTY color query command?


Here is some shell code extracted from https://github.com/rocky/bash-term-background to get terminal background colors. I'd like to mimic this behavior in Python so it can retrieve the values too:

stty -echo
# Issue command to get both foreground and
# background color
#            fg       bg
echo -ne '\e]10;?\a\e]11;?\a'
IFS=: read -t 0.1 -d $'\a' x fg
IFS=: read -t 0.1 -d $'\a' x bg
stty echo
# RGB values are in $fg and $bg

I can translate most of this, but the part I'm having problem with is echo -ne '\e]10;?\a\e]11;?\a'.

I would think that:

output = subprocess.check_output("echo -ne '\033]10;?\07\033]11;?\07'", shell=True)

would be a reasonable translation in Python 2.7, but I am not getting any output. Run in bash in an Xterm-compatible terminal gives:

rgb:e5e5e5/e5e5e6
rgb:000000/000000

But in python I am not seeing anything.

Update: As Mark Setchell suggests perhaps part of the problem is running in a subprocess. So when I change the python code to:

 print(check_output(["echo", "-ne" "'\033]10;?\07\033]11;?07'"]))

I now see the RGB values output, but only after the program terminates. So this suggests the problem is hooking up to see that output which I guess xterm is sending asynchronously.

2nd Update: based on meuh's code I've placed a fuller version of this in https://github.com/rocky/python-term-background


Solution

  • You need to just write the escape sequence to stdout and read the response on stdin after setting it to raw mode:

    #!/usr/bin/python3
    import os, select, sys, time, termios, tty
    
    fp = sys.stdin
    fd = fp.fileno()
    
    if os.isatty(fd):
        old_settings = termios.tcgetattr(fd)
        tty.setraw(fd)
        print('\033]10;?\07\033]11;?\07')
        time.sleep(0.01)
        r, w, e = select.select([ fp ], [], [], 0)
        if fp in r:
            data = fp.read(48)
        else:
            data = None
            print("no input available")
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        if data:
            print("got "+repr(data)+"\n")
    else:
        print("Not a tty")