Usando un buon modulo leggero, curtsies potresti fare qualcosa del genere (preso dalla loro directory examples/):
from curtsies import Input
def main():
with Input(keynames='curses') as input_generator:
for e in input_generator:
print(repr(e))
if __name__ == '__main__':
main()
Quindi premendo i tasti sulla tastiera ottieni qualcosa del genere:
'a'
's'
'KEY_F(1)'
'KEY_F(2)'
'KEY_F(3)'
'KEY_F(4)'
'KEY_F(5)'
'KEY_LEFT'
'KEY_DOWN'
'KEY_UP'
'KEY_RIGHT'
'KEY_NPAGE'
'\n'
curtsies è usato da bpython come un'astrazione di basso livello di cose relative al terminale.
Il problema di base della decodifica dell'input è che in diversi terminali e programmi di emulazione di terminale come xterm
o gnome-terminals
fisicamente le stesse chiavi producono diverse sequenze di codici chiave. Ecco perché è necessario sapere quali impostazioni del terminale devono essere utilizzate per decodificare l'input. Tale modulo aiuta ad astrarre da quei dettagli cruenti.
Questo è un semplice ciclo che metterà stdin in modalità raw (disabilitando il buffering in modo da non dover premere invio) per ottenere singoli caratteri. Dovresti fare qualcosa di più intelligente (come un with
statement per disabilitarlo) ma qui ti viene l'idea:
import tty
import sys
import termios
orig_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin)
x = 0
while x != chr(27): # ESC
x=sys.stdin.read(1)[0]
print("You pressed", x)
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)
Penso che dovresti eseguire il loop per rilevare i rilasci chiave in Python.
ETA qualche altra spiegazione:
Su Linux, l'input al tuo programma sarà line buffered . Ciò significa che il sistema operativo eseguirà il buffering dell'input fino a quando non avrà un'intera riga, quindi il tuo programma non vedrà nemmeno nulla dell'utente digitato fino a quando l'utente non preme anche "invio". In altre parole, se il tuo programma si aspetta che l'utente digiti "w" e l'utente lo fa, "w" rimarrà nel buffer del sistema operativo fino a quando l'utente non preme "invio". A questo punto l'intera riga viene consegnata al tuo programma in modo da ottenere la stringa "w\n" come input dell'utente.
Puoi disabilitarlo mettendo il tty in modalità raw . Puoi farlo con la funzione Python tty.setcbreak
che chiamerà il driver tty in Linux per dirgli di interrompere il buffering. Gli ho passato il sys.stdin
argomento per dirgli per quale flusso volevo disattivare il buffering. Quindi dopo il tty.setcbreak
call, il ciclo sopra ti darà un output per ogni tasto premuto dall'utente.
Una complicazione, tuttavia, è che una volta terminato il programma, il tty è ancora in modalità raw. In genere lo troverai insoddisfacente poiché non ottieni la potenza offerta dalle moderne impostazioni del terminale (come quando usi le sequenze di controllo o di fuga). Ad esempio, nota che potresti avere problemi a uscire dal programma con ctrl-C
. Di conseguenza dovresti riportare il terminale in modalità cucinata una volta che hai finito di leggere i caratteri di input. Il termios.tcsetattr
call dice semplicemente "rimetti il terminale come l'ho trovato". Sa come farlo chiamando prima termios.tcgetattr
all'inizio del programma che dice "dimmi tutte le impostazioni correnti per il terminale".
Una volta compreso tutto ciò, dovresti essere facilmente in grado di incapsulare la funzionalità in una funzione adatta al tuo programma.
stdin
è il flusso che l'input ti arriva dall'utente. Wikipedia può dirti di più sui flussi standard.