pmacs3/keyinput.py

156 lines
4.6 KiB
Python

import sys
import 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
# ome 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" }
def setup():
# add the meta/control-char combinations
for key in MAP:
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))
MAP[255] = "M-DELETE"
setup()
def disable_control_chars():
# terminal settings are for chumps
attr = termios.tcgetattr(sys.stdin)
old = termios.tcgetattr(sys.stdin)
# don't listen to allow input START/STOP (C-s,C-q)
attr[0] = attr[0] & ~(termios.IXON | termios.IXOFF)
#FIX3
# 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] = b'\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))