From d1787e576d6e8ebdb286ef03f846f396ae8f88ee Mon Sep 17 00:00:00 2001 From: Thomas Hurst Date: Mon, 11 Aug 2008 15:30:51 +0100 Subject: [PATCH] Introduce a class for handling keybindings. Not yet hooked up to anything, but initial tests suggest it works. --- terminatorlib/keybindings.py | 92 ++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 terminatorlib/keybindings.py diff --git a/terminatorlib/keybindings.py b/terminatorlib/keybindings.py new file mode 100644 index 00000000..7d7491f0 --- /dev/null +++ b/terminatorlib/keybindings.py @@ -0,0 +1,92 @@ + +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', + 'close_window': 'Q', + 'resize_up': 'Up', + 'resize_down': 'Down', + 'resize_left': 'Left', + 'resize_right': 'Right', + 'move_tab_right': 'Page_Up', + 'move_tab_left': 'Page_Down', + 'toggle_zoom': 'X', + '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._parse() + + def _parse(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][key] = 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 + keyval = gtk.gdk.keyval_name(event.keyval) + return self._lookup.get(mask, self.empty).get(keyval, None) +