diff --git a/README.asciidoc b/README.asciidoc index a37b193e6..76501b031 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -21,7 +21,7 @@ :sc_next_window: pass:quotes[`ctrl+shift+]`] :sc_ninth_window: pass:quotes[`ctrl+shift+9`] :sc_paste_from_clipboard: pass:quotes[`ctrl+shift+v`] -:sc_paste_from_selection: pass:quotes[`ctrl+shift+s`] +:sc_paste_from_selection: pass:quotes[`ctrl+shift+s` or `shift+insert`] :sc_previous_tab: pass:quotes[`ctrl+shift+left`] :sc_previous_window: pass:quotes[`ctrl+shift+[`] :sc_scroll_end: pass:quotes[`ctrl+shift+end`] diff --git a/key_encoding.asciidoc b/key_encoding.asciidoc new file mode 100644 index 000000000..12dd635c7 --- /dev/null +++ b/key_encoding.asciidoc @@ -0,0 +1,126 @@ += Key encoding for extended keyboard protocol + +|=== +| Name | Number | + +| 0 | 48 | +| 1 | 49 | +| 2 | 50 | +| 3 | 51 | +| 4 | 52 | +| 5 | 53 | +| 6 | 54 | +| 7 | 55 | +| 8 | 56 | +| 9 | 57 | +| A | 65 | +| APOSTROPHE | 39 | +| B | 66 | +| BACKSLASH | 92 | +| BACKSPACE | 259 | +| C | 67 | +| CAPS_LOCK | 280 | +| COMMA | 44 | +| D | 68 | +| DELETE | 261 | +| DOWN | 264 | +| E | 69 | +| END | 269 | +| ENTER | 257 | +| EQUAL | 61 | +| ESCAPE | 256 | +| F | 70 | +| F1 | 290 | +| F10 | 299 | +| F11 | 300 | +| F12 | 301 | +| F13 | 302 | +| F14 | 303 | +| F15 | 304 | +| F16 | 305 | +| F17 | 306 | +| F18 | 307 | +| F19 | 308 | +| F2 | 291 | +| F20 | 309 | +| F21 | 310 | +| F22 | 311 | +| F23 | 312 | +| F24 | 313 | +| F25 | 314 | +| F3 | 292 | +| F4 | 293 | +| F5 | 294 | +| F6 | 295 | +| F7 | 296 | +| F8 | 297 | +| F9 | 298 | +| G | 71 | +| GRAVE_ACCENT | 96 | +| H | 72 | +| HOME | 268 | +| I | 73 | +| INSERT | 260 | +| J | 74 | +| K | 75 | +| KP_0 | 320 | +| KP_1 | 321 | +| KP_2 | 322 | +| KP_3 | 323 | +| KP_4 | 324 | +| KP_5 | 325 | +| KP_6 | 326 | +| KP_7 | 327 | +| KP_8 | 328 | +| KP_9 | 329 | +| KP_ADD | 334 | +| KP_DECIMAL | 330 | +| KP_DIVIDE | 331 | +| KP_ENTER | 335 | +| KP_EQUAL | 336 | +| KP_MULTIPLY | 332 | +| KP_SUBTRACT | 333 | +| L | 76 | +| LEFT | 263 | +| LEFT_ALT | 342 | +| LEFT_BRACKET | 91 | +| LEFT_CONTROL | 341 | +| LEFT_SHIFT | 340 | +| LEFT_SUPER | 343 | +| M | 77 | +| MINUS | 45 | +| N | 78 | +| NUM_LOCK | 282 | +| O | 79 | +| P | 80 | +| PAGE_DOWN | 267 | +| PAGE_UP | 266 | +| PAUSE | 284 | +| PERIOD | 46 | +| PRINT_SCREEN | 283 | +| Q | 81 | +| R | 82 | +| RIGHT | 262 | +| RIGHT_ALT | 346 | +| RIGHT_BRACKET | 93 | +| RIGHT_CONTROL | 345 | +| RIGHT_SHIFT | 344 | +| RIGHT_SUPER | 347 | +| S | 83 | +| SCROLL_LOCK | 281 | +| SEMICOLON | 59 | +| SLASH | 47 | +| SPACE | 32 | +| T | 84 | +| TAB | 258 | +| U | 85 | +| UP | 265 | +| V | 86 | +| W | 87 | +| WORLD_1 | 161 | +| WORLD_2 | 162 | +| X | 88 | +| Y | 89 | +| Z | 90 | + +|=== diff --git a/kitty/keys.py b/kitty/keys.py index fcf055f45..c999a8cfd 100644 --- a/kitty/keys.py +++ b/kitty/keys.py @@ -109,3 +109,13 @@ def interpret_text_event(codepoint, mods): def get_shortcut(keymap, mods, key, scancode): key = get_localized_key(key, scancode) return keymap.get((mods & 0b1111, key)) + + +def key_integer_map(): + ans = {} + for k in dir(defines): + if k.startswith('GLFW_KEY_'): + val = getattr(defines, k) + if val < defines.GLFW_KEY_LAST and val != defines.GLFW_KEY_UNKNOWN: + ans[k[9:]] = val + return ans diff --git a/preprocess-readme.py b/preprocess-readme.py index 720b57b8e..5325f487b 100755 --- a/preprocess-readme.py +++ b/preprocess-readme.py @@ -2,14 +2,15 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2016, Kovid Goyal +import json import os import re +import subprocess from collections import defaultdict base = os.path.dirname(os.path.abspath(__file__)) os.chdir(base) - defns = defaultdict(list) for line in open('kitty/kitty.conf'): @@ -17,13 +18,32 @@ for line in open('kitty/kitty.conf'): _, sc, name = line.split(maxsplit=3) defns[name].append('`' + sc + '`') -defns = [':sc_{}: pass:quotes[{}]'.format(name, ' or '.join(defns[name])) for name in sorted(defns)] +defns = [ + ':sc_{}: pass:quotes[{}]'.format(name, ' or '.join(defns[name])) + for name in sorted(defns) +] defns = '\n'.join(defns) raw = open('README.asciidoc').read() -pat = re.compile(r'^// START_SHORTCUT_BLOCK$.+?^// END_SHORTCUT_BLOCK$', re.M | re.DOTALL) -nraw = pat.sub('// START_SHORTCUT_BLOCK\n' + - defns + '\n// END_SHORTCUT_BLOCK', raw) +pat = re.compile( + r'^// START_SHORTCUT_BLOCK$.+?^// END_SHORTCUT_BLOCK$', re.M | re.DOTALL +) +nraw = pat.sub( + '// START_SHORTCUT_BLOCK\n' + defns + '\n// END_SHORTCUT_BLOCK', raw +) if raw != nraw: print('Updating shortcuts block') open('README.asciidoc', 'w').write(nraw) + +raw = subprocess.check_output([ + 'kitty', '-c', + 'from kitty.keys import *; import json; print(json.dumps(key_integer_map()))' +]).decode('utf-8') +key_map = json.loads(raw) +lines = ['|===', '| Name | Number |', ''] +for k in sorted(key_map): + lines.append('| {:15s} | {:4d} |'.format(k, key_map[k])) +lines += ['', '|==='] +with open('key_encoding.asciidoc', 'w') as f: + print('= Key encoding for extended keyboard protocol\n', file=f) + print('\n'.join(lines), file=f) diff --git a/protocol-extensions.asciidoc b/protocol-extensions.asciidoc index abf42c8a6..5ad6f7e5b 100644 --- a/protocol-extensions.asciidoc +++ b/protocol-extensions.asciidoc @@ -301,3 +301,78 @@ the file repeatedly with no overhead. | y | _y-offset_ -- the row in the pixel data to start from (0-based) |=== + + +== Keyboard handling + +There are various problems with the current state of keyboard handling. They +include: + + * No way to use modifiers other than `Ctrl` and `Alt` + * No reliable way to distinguish single `Esc` keypresses from the + start of a escape sequence. Currently, client programs use + fragile timing related hacks for this, leading to bugs, for example: + link:https://github.com/neovim/neovim/issues/2035[neovim #2035] + +There are already two distinct keyboard handling modes, _normal mode_ and +_application mode_. These modes generate different escape sequences for the +various special keys (arrow keys, function keys, home/end etc.) Most terminals +start out in normal mode, however, most shell programs like `bash` switch them to +application mode. We propose adding a third mode, named _full mode_ that addresses +the shortcomings listed above. + +Switching to the new _full mode_ is accomplished using the standard private +mode DECSET escape sequence + +``` +[?2017h +``` + +and to leave _full mode_, use DECRST + +``` +[?2017l +``` + +The number `2017` above is not used for any existing modes, as far as I know. +Client programs can query if the terminal emulator is in _full mode_ by using +the standard link:http://vt100.net/docs/vt510-rm/DECRQM[DECRQM] escape sequence. + +The new mode works as follows: + + * All printable key presses without modifier keys are sent just as in the + _normal mode_. This means all printable ASCII characters and in addition, + `Enter`, `Space` and `Backspace`. Also any unicode characters generated by + platform specific extended input modes, such as using the `AltGr` key. This + is done so that client programs that are not aware of this mode can still + handle basic text entry, so if a _full mode_ using program crashes and does + not reset, the user can still issue a `reset` command in the shell to restore + normal key handling. Note that this includes pressing the `Shift` modifier + and printable keys. + + * For non printable keys and key combinations including one or more modifiers, + an escape sequence encoding the key event is sent. For details on the + escape sequence, see below. + +The escape sequence encodes the following properties: + + * Type of event: `press,repeat,release` + * Modifiers pressed at the time of the event + * The actual key being pressed + +``` +_K:\ +``` + +Where `` is one of `p` -- press, `r` -- release and `t` -- repeat. +Modifiers is zero or more of `c` -- Control, `a` -- Alt, `s` -- Shift and `m` -- Meta. +`` is a number corresponding to the key pressed. The key name to number mapping +is defined in link:key_encoding.asciidoc[this table]. + +For example: + +``` +_Kpca:88\ +``` + +Is the key press event `++x`.