Python で関数を実装しようとしましたがgetch()
、F1-F12 や矢印キーなどの特殊キーの文字のリストも返す必要があります。これらの特別なキーは、連続して複数の文字を生成します。したがってgetch()
、ブロッキング モードで 1 文字を読み取り、入力バッファに余分な文字があるかどうかを確認して、それらも取得する必要があります。
call をtermios.FIONREADioctl
と共に使用して、入力バッファー内のバイト数を取得しています。バッファにスタックされた非特殊キーの押下をキャッチしますが、特殊キーからの余分な記号は見逃します。2 つの異なるバッファーがあるようです。誰かがこれを説明してくれたらうれしいです。
インタラクティブな例を次に示します。
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)
途中注意。この秒が切れる前に 1 つのキーを押すと、出力は次のようになります。
buf queue: 0, sym: l, ord(108)
1 秒間に 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)
ここで 2 つの質問があります。
通常のキー押下でキュー内の 4 つのシンボルが破棄されるのはなぜですか? 「生」端末モードに切り替えたためですか?
getch()
端末を「生」モードのままにしなくても、後続の実行のために文字を保持するにはどうすればよいですか?ioctl
特別なキーを 1 回押すだけのバッファが空になるのはなぜですか? それらのキャラクターは、その後のgetch()
実行のためにどこから来ていますか? それらを確認する方法は?