Použitím dobrého lehkého modulu curtsies byste mohli udělat něco takového (převzato z jejich adresáře příkladů/):
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()
Takže stisknutím kláves na klávesnici získáte něco takového:
'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 používá bpython jako nízkoúrovňovou abstrakci věcí souvisejících s terminálem.
Základní problém dekódování vstupu spočívá v tom, že v různých terminálech a programech emulátoru terminálu, jako je xterm
nebo gnome-terminals
fyzicky stejné klíče vytvářejí různé sekvence kódů klíčů. To je důvod, proč je třeba vědět, která nastavení terminálu by měla být použita k dekódování vstupu. Takový modul pomáhá abstrahovat od těchto krvavých detailů.
Toto je jednoduchá smyčka, která přepne stdin do režimu raw (vypnutí ukládání do vyrovnávací paměti, abyste nemuseli stisknout enter), abyste získali jednotlivé znaky. Měli byste udělat něco chytřejšího (například with
příkaz k jeho zakázání), ale nápad získáte zde:
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)
Domnívám se, že pro detekci uvolnění klíčů v Pythonu byste museli smyčkovat.
ETA další vysvětlení:
V systému Linux bude vstup do vašeho programu řádkově uložen . To znamená, že operační systém bude ukládat vstup do vyrovnávací paměti, dokud nebude mít celý řádek, takže váš program ani neuvidí nic, co uživatel zadal, dokud uživatel také nestiskne 'enter'. Jinými slovy, pokud váš program očekává, že uživatel napíše „w“ a uživatel to udělá, „w“ bude sedět ve vyrovnávací paměti operačního systému, dokud uživatel nestiskne „enter“. V tomto okamžiku je do vašeho programu doručen celý řádek, takže jako vstup uživatele dostanete řetězec "w\n".
Toto můžete zakázat tak, že tty přepnete do raw režimu . To provedete pomocí funkce Python tty.setcbreak
což provede volání ovladače tty v linuxu, aby mu řekl, aby zastavil ukládání do vyrovnávací paměti. Předal jsem to sys.stdin
argument, abych mu řekl, pro který stream jsem chtěl vypnout ukládání do vyrovnávací paměti. Takže po tty.setcbreak
smyčka výše vám poskytne výstup pro každou klávesu, kterou uživatel stiskne.
Komplikací však je, že jakmile váš program skončí, tty je stále v surovém režimu. Obecně vám to přijde neuspokojivé, protože nezískáte žádný výkon, který nabízí moderní nastavení terminálu (jako když používáte ovládací nebo únikové sekvence). Všimněte si například, že můžete mít potíže s ukončením programu s ctrl-C
. V důsledku toho byste měli terminál vrátit zpět do režimu vaření jakmile dokončíte čtení vstupních znaků. termios.tcsetattr
volání jednoduše říká "vraťte terminál tak, jak jsem ho našel". Ví, jak to udělat, nejprve zavoláním termios.tcgetattr
na začátku programu, který říká "řekni mi všechna aktuální nastavení terminálu".
Jakmile tomu všemu porozumíte, měli byste být snadno schopni zapouzdřit funkčnost do funkce, která vyhovuje vašemu programu.
stdin
je stream, který k vám přichází od uživatele. Wikipedia vám může říct více o standardních streamech.