From 030228571c5c9904b7bee29034e4429fbe8eda71 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 21 Nov 2016 13:49:01 +0530 Subject: [PATCH] Implement keyboard shortcuts for paste --- kitty/boss.py | 38 ++++++++++++++++++++++++++++++-------- kitty/config.py | 13 ++++++++----- kitty/keys.py | 4 ++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/kitty/boss.py b/kitty/boss.py index 5fb8ac41f..4abbcb2c2 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -19,7 +19,7 @@ import glfw_constants from .constants import appname from .char_grid import CharGrid -from .keys import interpret_text_event, interpret_key_event +from .keys import interpret_text_event, interpret_key_event, get_shortcut from .utils import sanitize_title from .fast_data_types import ( BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, read_bytes_dump, read_bytes @@ -110,16 +110,18 @@ class Boss(Thread): def on_mouse_button(self, window, button, action, mods): if action == glfw_constants.GLFW_RELEASE: if button == glfw_constants.GLFW_MOUSE_BUTTON_MIDDLE: - # glfw has no way to get the primary selection - # text = glfw.glfwGetClipboardString(window) - text = subprocess.check_output(['xsel']) - if text: - if self.screen.in_bracketed_paste_mode(): - text = BRACKETED_PASTE_START.encode('ascii') + text + BRACKETED_PASTE_END.encode('ascii') - self.write_to_child(text) + self.paste_from_selection() + return def on_key(self, window, key, scancode, action, mods): if action == glfw_constants.GLFW_PRESS or action == glfw_constants.GLFW_REPEAT: + func = get_shortcut(self.opts.keymap, mods, key) + if func is not None: + func = getattr(self, func, None) + if func is not None: + passthrough = func() + if not passthrough: + return data = interpret_key_event(key, scancode, mods) if data: self.write_to_child(data) @@ -260,3 +262,23 @@ class Boss(Thread): self.char_grid.change_colors(self.pending_color_changes) self.pending_color_changes = {} glfw.glfwPostEmptyEvent() + + # actions {{{ + + def paste(self, text): + if text: + if self.screen.in_bracketed_paste_mode(): + text = BRACKETED_PASTE_START.encode('ascii') + text + BRACKETED_PASTE_END.encode('ascii') + self.write_to_child(text) + + def paste_from_clipboard(self): + text = glfw.glfwGetClipboardString(self.window) + self.paste(text) + + def paste_from_selection(self): + # glfw has no way to get the primary selection + # https://github.com/glfw/glfw/issues/894 + text = subprocess.check_output(['xsel']) + self.paste(text) + + # }}} diff --git a/kitty/config.py b/kitty/config.py index 9c7842043..384c7b5ad 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -230,11 +230,14 @@ def parse_key(val, keymap): def map_mod(m): return {'CTRL': 'CONTROL', 'CMD': 'CONTROL'}.get(m, m) - try: - mods = frozenset(getattr(glfw, 'GLFW_MOD_' + map_mod(m.upper())) for m in parts[:-1]) - except AttributeError: - print('Shortcut: {} has an unknown modifier, ignoring'.format(val), file=sys.stderr) - return + mods = 0 + for m in parts[:-1]: + try: + mods |= getattr(glfw, 'GLFW_MOD_' + map_mod(m.upper())) + except AttributeError: + print('Shortcut: {} has an unknown modifier, ignoring'.format(val), file=sys.stderr) + return + key = getattr(glfw, 'GLFW_KEY_' + parts[-1].upper(), None) if key is None: print('Shortcut: {} has an unknown key, ignoring'.format(val), file=sys.stderr) diff --git a/kitty/keys.py b/kitty/keys.py index 96ba0c0a4..739560aa9 100644 --- a/kitty/keys.py +++ b/kitty/keys.py @@ -61,3 +61,7 @@ def interpret_text_event(codepoint, mods): return b'' # Handled by interpret_key_event above data = chr(codepoint).encode('utf-8') return data + + +def get_shortcut(keymap, mods, key): + return keymap.get((mods & 0b1111, key))