Проверьте наличие дополнительных символов в буфере терминала Linux

Я пытаюсь реализоватьgetch() функция в Python, которая также должна возвращать список символов для специальных клавиш, таких как F1-F12 и клавиши со стрелками. Эти специальные ключи генерируют несколько символов в последовательности. Следовательноgetch() читает один символ в режиме блокировки, а затем должен проверить, есть ли дополнительные символы во входном буфере, чтобы получить их тоже.

Я используюioctl позвонить вместе сtermios.FIONREAD чтобы получить количество байтов во входном буфере. Он отлавливает нажатия специальных клавиш, помещенных в буфер, но пропускает дополнительные символы из специальных клавиш. Кажется, что есть два разных буфера, и было бы неплохо, если бы кто-нибудь смог это объяснить.

Вот интерактивный пример:

from time import sleep

def getch():
    import sys, tty, termios
    fd = sys.stdin.fileno()
    # save old terminal settings, because we are changing them
    old_settings = termios.tcgetattr(fd)
    try:
        # set terminal to "raw" mode, in which driver returns
        # one char at a time instead of one line at a time
        #
        # tty.setraw() is just a helper for tcsetattr() call, see
        # http://hg.python.org/cpython/file/c6880edaf6f3/Lib/tty.py
        tty.setraw(fd)
        ch = sys.stdin.read(1)

        # --- check if there are more characters in buffer
        from fcntl import ioctl
        from array import array

        sleep(1)
        buf = array('i', [0])
        ioctl(fd, termios.FIONREAD, buf)
        print "buf queue: %s," % buf[0],
        # ---

    finally:
        # restore terminal settings. Do this when all output is
        # finished - TCSADRAIN flag
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

char = ''
while char != 'q':
  char = getch()
  print 'sym: %s, ord(%s)' % (char, ord(char))

Записьsleep(1) в центре. Если вы нажмете одну клавишу до истечения этой секунды, результат будет:

buf queue: 0, sym: l, ord(108)

Для 5 обычных ключей (например, asdfg), введенных за одну секунду, вывод будет:

buf queue: 4, sym: a, ord(97)

но для одной клавиши со стрелкой вывод:

buf queue: 0, sym: , ord(27)
buf queue: 0, sym: [, ord(91)
buf queue: 0, sym: D, ord(68)

Здесь есть два вопроса:

Почему 4 символа в очереди с обычными нажатиями клавиш отбрасываются? Это из-за переключения в «сырой» режим терминала? Как можно сохранить символы для последующегоgetch() работает не выходя из терминала в "сыром" режиме?

Почемуioctl буфер для одной специальной клавиши нажатия пуст? Откуда берутся эти персонажи для последующегоgetch() работает? Как проверить их?

Ответы на вопрос(1)

Ваш ответ на вопрос