import re, gtk class KeymapError(Exception): def __init__(self, value): self.value = value self.action = 'unknown' def __str__(self): return "Keybinding '%s' invalid: %s" % (self.action, self.value) class TerminatorKeybindings: Modifier = re.compile('<([^<]+)>') keys = { 'zoom_in': 'plus', 'zoom_out': 'minus', 'zoom_normal': '0', 'new_root_tab': 'T', 'new_tab': 'T', 'go_next': 'N', 'go_prev': 'P', 'split_horiz': 'O', 'split_vert': 'E', 'close_term': 'W', 'copy': 'C', 'paste': 'V', 'toggle_scrollbar': 'S', 'search': 'F', 'close_window': 'Q', 'resize_up': 'Up', 'resize_down': 'Down', 'resize_left': 'Left', 'resize_right': 'Right', 'move_tab_right': 'Page_Down', 'move_tab_left': 'Page_Up', 'toggle_zoom': 'X', 'scaled_zoom': 'Z', 'next_tab': 'Page_Down', 'prev_tab': 'Page_Up', 'go_prev': 'Tab', 'go_next': 'Tab', 'full_screen': 'F11', } modifiers = { 'ctrl': gtk.gdk.CONTROL_MASK, 'shift': gtk.gdk.SHIFT_MASK, 'alt': gtk.gdk.MOD1_MASK } empty = {} def __init__(self): self.reload() def reload(self): self._lookup = {} self._masks = 0 for action, binding in self.keys.items(): try: mask, key = self._parsebinding(binding) keyval = gtk.gdk.keyval_from_name(key) if keyval == 0: raise KeymapError("Key '%s' is unrecognised" % key) except KeymapError, e: e.action = action raise e else: self._lookup.setdefault(mask, {}) self._lookup[mask][keyval] = action if key == 'Tab': self._lookup[mask][gtk.keysyms.ISO_Left_Tab] = action self._masks |= mask def _parsebinding(self, binding): mask = 0 modifiers = re.findall(self.Modifier, binding) if modifiers: for modifier in modifiers: mask |= self._lookup_modifier(modifier) key = re.sub(self.Modifier, '', binding) if key == '': raise KeymapError('No key found') return (mask, re.sub(self.Modifier, '', binding)) def _lookup_modifier(self, modifier): try: return self.modifiers[modifier.lower()] except KeyError: raise KeymapError("Unhandled modifier '<%s>'" % modifier) def lookup(self, event): mask = event.state & self._masks return self._lookup.get(mask, self.empty).get(event.keyval, None)