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)