Чтение многосимвольных нажатий на клавиатуре

У меня есть скрипт для чтения и обработки нажатий клавиатуры в python. Это отлично работает для меня со стандартными ключами, которые отправляют один байт в stdin. Я не могу найти разумный способ читать нажатия клавиш, которые создают многобайтовый escape-код ansi. Что мне нужно сделать, чтобы иметь возможность читать все доступные данные из стандартного ввода?

Система: OS X, Python 3.4

Вот мой минимальный пример кода:

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)


Ожидаемое/желаемое поведение

Когда я запускаю скрипт и нажимаю кнопку со стрелкой вправо, я ожидаю, что результат будет таким:

b'\x1b'
b'['
b'C'

Что я на самом деле получаю:

b'\x1b'

Если я затем нажму любую другую клавишу, все остальное будет прочитано. Например, если я сейчас нажму «x», я получу:

b'['
b'C'
b'x'

Как я могу получить все три байта с начальным нажатием клавиши?


person amicitas    schedule 20.07.2016    source источник
comment
sys.stdin - неправильная абстракция для этого. Это просто файл, содержащий байты; любая информация о том, какие нажатия клавиш сгенерировали эти байты, теряется. Вам нужно напрямую взаимодействовать с клавиатурой, что я не думаю, что возможно, используя только стандартную библиотеку.   -  person chepner    schedule 20.07.2016
comment
Я думаю, может быть, здесь более конкретный вопрос: почему select.select неправильно сообщает, что sys.stdin доступен для чтения?   -  person amicitas    schedule 20.07.2016


Ответы (1)


Когда вы столкнетесь с \x1b, дождитесь остальной части управляющей последовательности. Затем оставьте тайм-аут, на случай, если пользователь нажал клавишу esc в одиночку. Vim делает это, поскольку это единственный способ сделать это.

person Min4Builder    schedule 23.01.2017