153 lines
4.5 KiB
Python
153 lines
4.5 KiB
Python
import curses, sys, termios
|
|
|
|
# this is a huge map of ASCII keycode sequences it should include all
|
|
# the "standard" ones for a US 104 key keyboard. this module may need
|
|
# to support some kind of subclassing in order to be localizable.
|
|
#
|
|
# of course, i'd be crazy to try to localize a curses app
|
|
MAP = { 0: "C-@",
|
|
1: "C-a",
|
|
2: "C-b",
|
|
3: "C-c",
|
|
4: "C-d",
|
|
5: "C-e",
|
|
6: "C-f",
|
|
7: "C-g",
|
|
#8: "C-h",
|
|
8: "BACKSPACE",
|
|
#9: "C-i",
|
|
9: "TAB",
|
|
#10: "C-j",
|
|
10: "RETURN",
|
|
11: "C-k",
|
|
12: "C-l",
|
|
#13: "C-m",
|
|
13: "RETURN",
|
|
14: "C-n",
|
|
15: "C-o",
|
|
16: "C-p",
|
|
17: "C-q",
|
|
18: "C-r",
|
|
19: "C-s",
|
|
20: "C-t",
|
|
21: "C-u",
|
|
22: "C-v",
|
|
23: "C-w",
|
|
24: "C-x",
|
|
25: "C-y",
|
|
26: "C-z",
|
|
27: { 79: { 80: "F1",
|
|
81: "F2",
|
|
82: "F3",
|
|
83: "F4" },
|
|
91: { 49: { 49: { 126: "F1" },
|
|
50: { 126: "F2" },
|
|
51: { 126: "F3" },
|
|
52: { 126: "F4" },
|
|
53: { 126: "F5" },
|
|
55: { 126: "F6" },
|
|
56: { 126: "F7" },
|
|
57: { 126: "F8" },
|
|
126: "HOME" },
|
|
50: { 48: { 126: "F9" },
|
|
49: { 126: "F10" },
|
|
51: { 126: "F11" },
|
|
52: { 126: "F12" },
|
|
126: "INSERT" },
|
|
51: { 126: "DELETE" },
|
|
52: { 126: "END" },
|
|
53: { 126: "PG_UP" },
|
|
54: { 126: "PG_DN" },
|
|
65: "U_ARROW",
|
|
66: "D_ARROW",
|
|
67: "R_ARROW",
|
|
68: "L_ARROW",
|
|
90: "LEFT_TAB",
|
|
91: { 65: "F1",
|
|
66: "F2",
|
|
67: "F3",
|
|
68: "F4",
|
|
69: "F5" } } },
|
|
28: "C-\\",
|
|
29: "C-]",
|
|
30: "C-30",
|
|
31: "C-/",
|
|
32: "SPACE",
|
|
127: "DELETE" }
|
|
|
|
# add the meta/control-char combinations
|
|
for key in MAP.iterkeys():
|
|
if key == 27:
|
|
# we don't want to define ESC-ESC
|
|
continue
|
|
MAP[27][key] = "M-%s" % (MAP[key])
|
|
|
|
# add meta character stuff
|
|
for i in range(33, 126):
|
|
if i == 79 or i == 91:
|
|
# these keys are used in other sequences
|
|
continue
|
|
# 7bit meta sequences
|
|
MAP[27][i] = "M-%s" % (chr(i))
|
|
# 8bit meta characters
|
|
MAP[128+i] = "M-%s" % (chr(i))
|
|
|
|
def disable_control_chars():
|
|
#terminal settings are for chumps
|
|
attr = termios.tcgetattr(sys.stdin)
|
|
|
|
global OLD_ATTR
|
|
OLD_ATTR = attr
|
|
|
|
# don't listen to allow input START/STOP (C-s,C-q)
|
|
attr[0] = attr[0] & ~(termios.IXON | termios.IXOFF)
|
|
|
|
# remove as many signal handlers as we can; we want to
|
|
# leave C-d and C-z probably
|
|
for pos in range(0,len(attr[6])):
|
|
if pos == termios.VEOF or pos == termios.VSUSP:
|
|
continue
|
|
attr[6][pos] = '\x00'
|
|
|
|
# write the attributes back
|
|
termios.tcsetattr(sys.stdin, termios.TCSANOW, attr)
|
|
|
|
|
|
class Handler(object):
|
|
def __init__(self):
|
|
self.tokens = []
|
|
self.unset_meta()
|
|
def unset_meta(self):
|
|
self.meta = MAP
|
|
def set_meta(self, d):
|
|
self.meta = d
|
|
|
|
def parse(self, i):
|
|
if i == -1:
|
|
# this means that no key was actually pressed
|
|
return
|
|
|
|
if i in self.meta:
|
|
# we have a special "named" token (a control character or
|
|
# a meta sequence)
|
|
if type(self.meta[i]) == type({}):
|
|
# ok, we need to keep traversing down to finish the
|
|
# meta sequence
|
|
self.set_meta(self.meta[i])
|
|
else:
|
|
# ok, we either got a control character or finished a
|
|
# meta sequence
|
|
self.tokens.append(self.meta[i])
|
|
self.unset_meta()
|
|
else:
|
|
# we got a regular character
|
|
# we may have interrupted a meta sequence... so unset it
|
|
self.unset_meta()
|
|
|
|
if(32 < i and i < 127):
|
|
# we got a "regular" keycode, so use it
|
|
self.tokens.append(chr(i))
|
|
else:
|
|
# this shouldn't really happen
|
|
raise Exception, "strange keycode recieved: %d" % (i)
|