Verifique caracteres extras no buffer do terminal Linux

Tento implementargetch() no Python, que também deve retornar uma lista de caracteres para chaves especiais como F1-F12 e teclas de seta. Essas chaves especiais geram vários caracteres em uma sequência. Portantogetch() lê um caractere no modo de bloqueio e deve verificar se há caracteres extras no buffer de entrada para buscá-los també

Estou usandoioctl ligue junto com termios.FIONREAD para obter o número de bytes no buffer de entrada. Ele captura pressionamentos de teclas não especiais empilhados no buffer, mas perde símbolos extras de teclas especiais. Parece que existem dois buffers diferentes e seria bom se alguém pudesse explicar iss

Aqui está o exemplo interativo:

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))

Notasleep(1) no meio. Se você pressionar uma tecla antes que esse segundo expire, a saída será:

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

Para 5 chaves comuns (por exemplo, 'asdfg') inseridas em um segundo, a saída é:

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

mas para uma única tecla de seta, a saída:

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

Há duas perguntas aqui:

Por que 4 símbolos na fila com pressionamentos de tecla comuns são descartados? É por causa da mudança para o modo de terminal "bruto"? Como é possível preservar os caracteres para as subseqüentesgetch() roda sem sair do terminal no modo "bruto"?

Porque oioctl buffer para uma única tecla especial pressionada está vazio? De onde vêm esses caracteres para @ subsequentgetch() corre? Como verificá-los?

questionAnswers(1)

yourAnswerToTheQuestion