0

I want to write a Python program to get the current background color of an Xterm terminal. (This feature is available in termenv written in golang but I can't find any existing implementations in Python.)

This can be done by sending an OSC (Operating System Control) control sequence to stdout and reading the response from stdin. For example, to read the terminal background, the escape code is:

print('\033]11;?\033\\\033[6n')

The full response to this OSC query is '\x1b]11;rgb:2c2c/2c2c/2c2c\x1b\\\x1b[50;1R'

However, since not all terminals support this control sequence, we can't expect them to return anything in stdin. If nothing is supplied in stdin and we still call stdin.read(), read() will wait forever until the user input something. So we need a function to tell whether stdin contains anything for us to read.

I found that select can be used to check if stdin has inputs. However, when I tried using select, it only passed for the first character, and it returned an empty array after that even if inputs are present:

print('\033]11;?\033\\\033[6n')

print(select.select([0], [], [], 0.1)) # Prints ([0], [], [])
print(repr(sys.stdin.read(1)))         # Prints '\x1b'
print(select.select([0], [], [], 0.1)) # Prints ([], [], [])
print(repr(sys.stdin.read(1)))         # Prints ']'
print(select.select([0], [], [], 0.1)) # Prints ([], [], [])
print(repr(sys.stdin.read(1)))         # Prints '1'

Why would select return an empty array (indicating that fd#0 (stdin) is not available for input) when there are inputs waiting to be read in stdin? The go implementation using the native unix.Select doesn't seem to have this issue.

I also tried using stdin.readable(), but this always returns True whether or not there are actually inputs present.

Hykilpikonna
  • 1,749
  • 2
  • 15
  • 32

0 Answers0