Eh, elle kod yazdım. Gelecekte referans olması için bir açıklama bırakacağım.
Koşullar hattı tamponlama
sadece Stdin okuma hattı tamponlama olduğunda ortaya çıkan ilk sorun, devre dışı bırakma
import sys, tty, termios, codecs, unicodedata
from contextlib import contextmanager
. Tek bir karakterin programımıza gerekli yeni bir satır olmadan ulaşmasını istiyoruz ve bu, terminalin çalıştığı varsayılan yol değil.
with cbreak():
single_char_no_newline = sys.stdin.read(1)
Biz bitince temiz yukarı gerçekleştirmek önemlidir:
@contextmanager
def cbreak():
old_attrs = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin)
try:
yield
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attrs)
Bu yönetici aşağıdaki deyim sağlar: Bunun için
, ben tty
yapılandırmayı işleyen bir bağlam yöneticisi yazdı veya terminalin bir reset
'a ihtiyacı olabilir.
sadece Stdin kodlayan bir okuma ikinci bir sorun, kod çözme Stdin. Ascii unicode karakterleri bize tamamen istenmeyen olan byte by byte'a ulaşacak.
def uinput():
reader = codecs.getreader(sys.stdin.encoding)(sys.stdin)
with cbreak():
while True:
yield reader.read(1)
Bu boruların üzerinde başarısız olabilir: Düzgün stdin'nin deşifre etmek
, biz Unicode karakterleri için yineleme bir jeneratör yazdı. Emin değilim. Ancak benim kullanım durumum için, doğru kodlamayı seçer ve bir karakter akışı üretir.
Handling özel karakterler
Öncelikle, kontrol olanlardan ayrı yazdırılabilir karakterleri söylemek mümkün olmalıdır:
printables bir yana
def is_printable(c):
return not unicodedata.category(c).startswith('C')
, şimdilik, sadece işlemek istiyorum ← geri tuşu ve CtrlD sekansı
def is_backspace(c):
return c in ('\x08','\x7F')
def is_interrupt(c):
return c == '\x04'
Bir araya getirme: xinput()
Her şey şu anda hazır. İstediğim işlev için orijinal sözleşme okuma girişi, özel karakterleri ele al, geri arama çağrısı.
def xinput(callback):
text = ''
for c in uinput():
if is_printable(c): text += c
elif is_backspace(c): text = text[:-1]
elif is_interrupt(c): break
callback(text)
return text
← geri silme Hellx bunu Koşu ve yazarak
def test(text):
print 'Buffer now holds', text
xinput(test)
dışarı çalışılıyoro Dünya gösterir:
Buffer now holds H
Buffer now holds He
Buffer now holds Hel
Buffer now holds Hell
Buffer now holds Hellx
Buffer now holds Hell
Buffer now holds Hello
Buffer now holds Hello
Buffer now holds Hello w
Buffer now holds Hello wo
Buffer now holds Hello wor
Buffer now holds Hello worl
Buffer now holds Hello world
uygulama sadece yansıtır