I have a script to read and handle keyboard strokes within python. This works perfectly fine for me for standard keys which send one byte to stdin
. I cannot find a reasonable way to read keystrokes that produce a multi-byte ansi escape code. What do I need to do to be able to read all available data from stdin?
System: OSX, Python 3.4
Here is my minimal example code:
import sys
import termios
import select
# Save the terminal settings
fd = sys.stdin.fileno()
new_term = termios.tcgetattr(fd)
old_term = termios.tcgetattr(fd)
# New terminal setting unbuffered
new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)
termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)
while sys.stdin in select.select([sys.stdin], [], [], 10.0)[0]:
char = sys.stdin.buffer.read(1)
print('User input: {}'.format(char))
if char == b'q':
break
termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)
When I start the script and press the right arrow button I would expect the output to be:
b'\x1b'
b'['
b'C'
What I actually get is:
b'\x1b'
If I then press any other key, everything else gets read. For example if I now press 'x' I get:
b'['
b'C'
b'x'
How can I get all three bytes with the initial key press?
When you encounter an \x1b
, wait for the rest of the escape sequence. Then leave a timeout, just in case the user pressed esc alone. Vim does that, as it is the only way to do it.