aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerw7 <erw7.github@gmail.com>2021-11-24 02:05:35 +0900
committerzeertzjq <zeertzjq@outlook.com>2022-07-04 21:09:33 +0800
commit33ed85a2f62d2b8dbac131cb61d03ac601808342 (patch)
treee8926b05923c8245ab0a1c3f832723c61adce91a
parentab5929e1b0f13b8750c8a97d41396ac9a0769e18 (diff)
downloadrneovim-33ed85a2f62d2b8dbac131cb61d03ac601808342.tar.gz
rneovim-33ed85a2f62d2b8dbac131cb61d03ac601808342.tar.bz2
rneovim-33ed85a2f62d2b8dbac131cb61d03ac601808342.zip
feat(tui): recognize keypad keys when using kitty keyboard protocol
-rw-r--r--src/nvim/getchar.c4
-rw-r--r--src/nvim/map.c5
-rw-r--r--src/nvim/map.h4
-rw-r--r--src/nvim/tui/input.c163
-rw-r--r--src/nvim/tui/input.h1
-rw-r--r--src/nvim/tui/input_defs.h118
6 files changed, 276 insertions, 19 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index c3dbb02dce..0f6eddef9d 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1545,12 +1545,16 @@ int vgetc(void)
}
break;
+ case K_KUP:
case K_XUP:
c = K_UP; break;
+ case K_KDOWN:
case K_XDOWN:
c = K_DOWN; break;
+ case K_KLEFT:
case K_XLEFT:
c = K_LEFT; break;
+ case K_KRIGHT:
case K_XRIGHT:
c = K_RIGHT; break;
}
diff --git a/src/nvim/map.c b/src/nvim/map.c
index d27e40b4ee..d3058a5d52 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -30,6 +30,8 @@
#define int_eq kh_int_hash_equal
#define handle_T_hash kh_int_hash_func
#define handle_T_eq kh_int_hash_equal
+#define KittyKey_hash kh_int_hash_func
+#define KittyKey_eq kh_int_hash_equal
#if defined(ARCH_64)
# define ptr_t_hash(key) uint64_t_hash((uint64_t)(key))
@@ -162,6 +164,7 @@ static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2)
}
MAP_IMPL(int, int, DEFAULT_INITIALIZER)
+MAP_IMPL(int, cstr_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, int, DEFAULT_INITIALIZER)
MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
@@ -177,6 +180,8 @@ MAP_IMPL(int, String, DEFAULT_INITIALIZER)
MAP_IMPL(ColorKey, ColorItem, COLOR_ITEM_INITIALIZER)
+MAP_IMPL(KittyKey, cstr_t, DEFAULT_INITIALIZER)
+
/// Deletes a key:value pair from a string:pointer map, and frees the
/// storage of both key and value.
///
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 4f4aaa3552..845daac3f7 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -7,6 +7,7 @@
#include "nvim/extmark_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/map_defs.h"
+#include "nvim/tui/input_defs.h"
#include "nvim/ui_client.h"
#if defined(__NetBSD__)
@@ -34,6 +35,7 @@
// NOTE: Keys AND values must be allocated! khash.h does not make a copy.
//
MAP_DECLS(int, int)
+MAP_DECLS(int, cstr_t)
MAP_DECLS(cstr_t, ptr_t)
MAP_DECLS(cstr_t, int)
MAP_DECLS(ptr_t, ptr_t)
@@ -50,6 +52,8 @@ MAP_DECLS(int, String)
MAP_DECLS(ColorKey, ColorItem)
+MAP_DECLS(KittyKey, cstr_t)
+
#define MAP_INIT { { 0, 0, 0, 0, NULL, NULL, NULL } }
#define map_init(k, v, map) do { *(map) = (Map(k, v)) MAP_INIT; } while (false)
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 3e24e892b8..61a59bcf06 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -23,6 +23,91 @@
#define KEY_BUFFER_SIZE 0xfff
+static const struct kitty_key_map_entry {
+ KittyKey key;
+ const char *name;
+} kitty_key_map_entry[] = {
+ { KITTY_KEY_ESCAPE, "Esc" },
+ { KITTY_KEY_ENTER, "CR" },
+ { KITTY_KEY_TAB, "Tab" },
+ { KITTY_KEY_BACKSPACE, "BS" },
+ { KITTY_KEY_INSERT, "Insert" },
+ { KITTY_KEY_DELETE, "Del" },
+ { KITTY_KEY_LEFT, "Left" },
+ { KITTY_KEY_RIGHT, "Right" },
+ { KITTY_KEY_UP, "Up" },
+ { KITTY_KEY_DOWN, "Down" },
+ { KITTY_KEY_PAGE_UP, "PageUp" },
+ { KITTY_KEY_PAGE_DOWN, "PageDown" },
+ { KITTY_KEY_HOME, "Home" },
+ { KITTY_KEY_END, "End" },
+ { KITTY_KEY_F1, "F1" },
+ { KITTY_KEY_F2, "F2" },
+ { KITTY_KEY_F3, "F3" },
+ { KITTY_KEY_F4, "F4" },
+ { KITTY_KEY_F5, "F5" },
+ { KITTY_KEY_F6, "F6" },
+ { KITTY_KEY_F7, "F7" },
+ { KITTY_KEY_F8, "F8" },
+ { KITTY_KEY_F9, "F9" },
+ { KITTY_KEY_F10, "F10" },
+ { KITTY_KEY_F11, "F11" },
+ { KITTY_KEY_F12, "F12" },
+ { KITTY_KEY_F13, "F13" },
+ { KITTY_KEY_F14, "F14" },
+ { KITTY_KEY_F15, "F15" },
+ { KITTY_KEY_F16, "F16" },
+ { KITTY_KEY_F17, "F17" },
+ { KITTY_KEY_F18, "F18" },
+ { KITTY_KEY_F19, "F19" },
+ { KITTY_KEY_F20, "F20" },
+ { KITTY_KEY_F21, "F21" },
+ { KITTY_KEY_F22, "F22" },
+ { KITTY_KEY_F23, "F23" },
+ { KITTY_KEY_F24, "F24" },
+ { KITTY_KEY_F25, "F25" },
+ { KITTY_KEY_F26, "F26" },
+ { KITTY_KEY_F27, "F27" },
+ { KITTY_KEY_F28, "F28" },
+ { KITTY_KEY_F29, "F29" },
+ { KITTY_KEY_F30, "F30" },
+ { KITTY_KEY_F31, "F31" },
+ { KITTY_KEY_F32, "F32" },
+ { KITTY_KEY_F33, "F33" },
+ { KITTY_KEY_F34, "F34" },
+ { KITTY_KEY_F35, "F35" },
+ { KITTY_KEY_KP_0, "k0" },
+ { KITTY_KEY_KP_1, "k1" },
+ { KITTY_KEY_KP_2, "k2" },
+ { KITTY_KEY_KP_3, "k3" },
+ { KITTY_KEY_KP_4, "k4" },
+ { KITTY_KEY_KP_5, "k5" },
+ { KITTY_KEY_KP_6, "k6" },
+ { KITTY_KEY_KP_7, "k7" },
+ { KITTY_KEY_KP_8, "k8" },
+ { KITTY_KEY_KP_9, "k9" },
+ { KITTY_KEY_KP_DECIMAL, "kPoint" },
+ { KITTY_KEY_KP_DIVIDE, "kDivide" },
+ { KITTY_KEY_KP_MULTIPLY, "kMultiply" },
+ { KITTY_KEY_KP_SUBTRACT, "kMinus" },
+ { KITTY_KEY_KP_ADD, "kPlus" },
+ { KITTY_KEY_KP_ENTER, "kEnter" },
+ { KITTY_KEY_KP_EQUAL, "kEqual" },
+ { KITTY_KEY_KP_LEFT, "kLeft" },
+ { KITTY_KEY_KP_RIGHT, "kRight" },
+ { KITTY_KEY_KP_UP, "kUp" },
+ { KITTY_KEY_KP_DOWN, "kDown" },
+ { KITTY_KEY_KP_PAGE_UP, "kPageUp" },
+ { KITTY_KEY_KP_PAGE_DOWN, "kPageDown" },
+ { KITTY_KEY_KP_HOME, "kHome" },
+ { KITTY_KEY_KP_END, "kEnd" },
+ { KITTY_KEY_KP_INSERT, "kInsert" },
+ { KITTY_KEY_KP_DELETE, "kDel" },
+ { KITTY_KEY_KP_BEGIN, "kOrigin" },
+};
+
+static Map(KittyKey, cstr_t) kitty_key_map = MAP_INIT;
+
#ifndef UNIT_TESTING
typedef enum {
kIncomplete = -1,
@@ -50,6 +135,11 @@ void tinput_init(TermInput *input, Loop *loop)
uv_mutex_init(&input->key_buffer_mutex);
uv_cond_init(&input->key_buffer_cond);
+ for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) {
+ map_put(KittyKey, cstr_t)(&kitty_key_map, kitty_key_map_entry[i].key,
+ kitty_key_map_entry[i].name);
+ }
+
// If stdin is not a pty, switch to stderr. For cases like:
// echo q | nvim -es
// ls *.md | xargs nvim
@@ -89,6 +179,7 @@ void tinput_init(TermInput *input, Loop *loop)
void tinput_destroy(TermInput *input)
{
+ map_destroy(KittyKey, cstr_t)(&kitty_key_map);
rbuffer_free(input->key_buffer);
uv_mutex_destroy(&input->key_buffer_mutex);
uv_cond_destroy(&input->key_buffer_cond);
@@ -206,19 +297,46 @@ static void tinput_enqueue(TermInput *input, char *buf, size_t size)
rbuffer_write(input->key_buffer, buf, size);
}
+static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key)
+{
+ const char *name = map_get(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint);
+ if (name) {
+ char buf[64];
+ size_t len = 0;
+ buf[len++] = '<';
+ if (key->modifiers & TERMKEY_KEYMOD_SHIFT) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "S-");
+ }
+ if (key->modifiers & TERMKEY_KEYMOD_ALT) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "A-");
+ }
+ if (key->modifiers & TERMKEY_KEYMOD_CTRL) {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "C-");
+ }
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "%s>", name);
+ tinput_enqueue(input, buf, len);
+ }
+}
+
static void forward_simple_utf8(TermInput *input, TermKeyKey *key)
{
size_t len = 0;
char buf[64];
char *ptr = key->utf8;
- while (*ptr) {
- if (*ptr == '<') {
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "<lt>");
- } else {
- buf[len++] = *ptr;
+ if (key->code.codepoint >= 0xE000 && key->code.codepoint <= 0xF8FF
+ && map_has(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint)) {
+ handle_kitty_key_protocol(input, key);
+ return;
+ } else {
+ while (*ptr) {
+ if (*ptr == '<') {
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, "<lt>");
+ } else {
+ buf[len++] = *ptr;
+ }
+ ptr++;
}
- ptr++;
}
tinput_enqueue(input, buf, len);
@@ -236,19 +354,26 @@ static void forward_modified_utf8(TermInput *input, TermKeyKey *key)
len = termkey_strfkey(input->tk, buf, sizeof(buf), key, TERMKEY_FORMAT_VIM);
} else {
assert(key->modifiers);
- // Termkey doesn't include the S- modifier for ASCII characters (e.g.,
- // ctrl-shift-l is <C-L> instead of <C-S-L>. Vim, on the other hand,
- // treats <C-L> and <C-l> the same, requiring the S- modifier.
- len = termkey_strfkey(input->tk, buf, sizeof(buf), key, TERMKEY_FORMAT_VIM);
- if ((key->modifiers & TERMKEY_KEYMOD_CTRL)
- && !(key->modifiers & TERMKEY_KEYMOD_SHIFT)
- && ASCII_ISUPPER(key->code.codepoint)) {
- assert(len <= 62);
- // Make room for the S-
- memmove(buf + 3, buf + 1, len - 1);
- buf[1] = 'S';
- buf[2] = '-';
- len += 2;
+ if (key->code.codepoint >= 0xE000 && key->code.codepoint <= 0xF8FF
+ && map_has(KittyKey, cstr_t)(&kitty_key_map,
+ (KittyKey)key->code.codepoint)) {
+ handle_kitty_key_protocol(input, key);
+ return;
+ } else {
+ // Termkey doesn't include the S- modifier for ASCII characters (e.g.,
+ // ctrl-shift-l is <C-L> instead of <C-S-L>. Vim, on the other hand,
+ // treats <C-L> and <C-l> the same, requiring the S- modifier.
+ len = termkey_strfkey(input->tk, buf, sizeof(buf), key, TERMKEY_FORMAT_VIM);
+ if ((key->modifiers & TERMKEY_KEYMOD_CTRL)
+ && !(key->modifiers & TERMKEY_KEYMOD_SHIFT)
+ && ASCII_ISUPPER(key->code.codepoint)) {
+ assert(len <= 62);
+ // Make room for the S-
+ memmove(buf + 3, buf + 1, len - 1);
+ buf[1] = 'S';
+ buf[2] = '-';
+ len += 2;
+ }
}
}
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 84daf40744..51df57938c 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -6,6 +6,7 @@
#include "nvim/event/stream.h"
#include "nvim/event/time.h"
+#include "nvim/tui/input_defs.h"
#include "nvim/tui/tui.h"
typedef enum {
diff --git a/src/nvim/tui/input_defs.h b/src/nvim/tui/input_defs.h
new file mode 100644
index 0000000000..846cf45350
--- /dev/null
+++ b/src/nvim/tui/input_defs.h
@@ -0,0 +1,118 @@
+#ifndef NVIM_TUI_INPUT_DEFS_H
+#define NVIM_TUI_INPUT_DEFS_H
+
+typedef enum {
+ KITTY_KEY_ESCAPE = 57344,
+ KITTY_KEY_ENTER = 57345,
+ KITTY_KEY_TAB = 57346,
+ KITTY_KEY_BACKSPACE = 57347,
+ KITTY_KEY_INSERT = 57348,
+ KITTY_KEY_DELETE = 57349,
+ KITTY_KEY_LEFT = 57350,
+ KITTY_KEY_RIGHT = 57351,
+ KITTY_KEY_UP = 57352,
+ KITTY_KEY_DOWN = 57353,
+ KITTY_KEY_PAGE_UP = 57354,
+ KITTY_KEY_PAGE_DOWN = 57355,
+ KITTY_KEY_HOME = 57356,
+ KITTY_KEY_END = 57357,
+ KITTY_KEY_CAPS_LOCK = 57358,
+ KITTY_KEY_SCROLL_LOCK = 57359,
+ KITTY_KEY_NUM_LOCK = 57360,
+ KITTY_KEY_PRINT_SCREEN = 57361,
+ KITTY_KEY_PAUSE = 57362,
+ KITTY_KEY_MENU = 57363,
+ KITTY_KEY_F1 = 57364,
+ KITTY_KEY_F2 = 57365,
+ KITTY_KEY_F3 = 57366,
+ KITTY_KEY_F4 = 57367,
+ KITTY_KEY_F5 = 57368,
+ KITTY_KEY_F6 = 57369,
+ KITTY_KEY_F7 = 57370,
+ KITTY_KEY_F8 = 57371,
+ KITTY_KEY_F9 = 57372,
+ KITTY_KEY_F10 = 57373,
+ KITTY_KEY_F11 = 57374,
+ KITTY_KEY_F12 = 57375,
+ KITTY_KEY_F13 = 57376,
+ KITTY_KEY_F14 = 57377,
+ KITTY_KEY_F15 = 57378,
+ KITTY_KEY_F16 = 57379,
+ KITTY_KEY_F17 = 57380,
+ KITTY_KEY_F18 = 57381,
+ KITTY_KEY_F19 = 57382,
+ KITTY_KEY_F20 = 57383,
+ KITTY_KEY_F21 = 57384,
+ KITTY_KEY_F22 = 57385,
+ KITTY_KEY_F23 = 57386,
+ KITTY_KEY_F24 = 57387,
+ KITTY_KEY_F25 = 57388,
+ KITTY_KEY_F26 = 57389,
+ KITTY_KEY_F27 = 57390,
+ KITTY_KEY_F28 = 57391,
+ KITTY_KEY_F29 = 57392,
+ KITTY_KEY_F30 = 57393,
+ KITTY_KEY_F31 = 57394,
+ KITTY_KEY_F32 = 57395,
+ KITTY_KEY_F33 = 57396,
+ KITTY_KEY_F34 = 57397,
+ KITTY_KEY_F35 = 57398,
+ KITTY_KEY_KP_0 = 57399,
+ KITTY_KEY_KP_1 = 57400,
+ KITTY_KEY_KP_2 = 57401,
+ KITTY_KEY_KP_3 = 57402,
+ KITTY_KEY_KP_4 = 57403,
+ KITTY_KEY_KP_5 = 57404,
+ KITTY_KEY_KP_6 = 57405,
+ KITTY_KEY_KP_7 = 57406,
+ KITTY_KEY_KP_8 = 57407,
+ KITTY_KEY_KP_9 = 57408,
+ KITTY_KEY_KP_DECIMAL = 57409,
+ KITTY_KEY_KP_DIVIDE = 57410,
+ KITTY_KEY_KP_MULTIPLY = 57411,
+ KITTY_KEY_KP_SUBTRACT = 57412,
+ KITTY_KEY_KP_ADD = 57413,
+ KITTY_KEY_KP_ENTER = 57414,
+ KITTY_KEY_KP_EQUAL = 57415,
+ KITTY_KEY_KP_SEPARATOR = 57416,
+ KITTY_KEY_KP_LEFT = 57417,
+ KITTY_KEY_KP_RIGHT = 57418,
+ KITTY_KEY_KP_UP = 57419,
+ KITTY_KEY_KP_DOWN = 57420,
+ KITTY_KEY_KP_PAGE_UP = 57421,
+ KITTY_KEY_KP_PAGE_DOWN = 57422,
+ KITTY_KEY_KP_HOME = 57423,
+ KITTY_KEY_KP_END = 57424,
+ KITTY_KEY_KP_INSERT = 57425,
+ KITTY_KEY_KP_DELETE = 57426,
+ KITTY_KEY_KP_BEGIN = 57427,
+ KITTY_KEY_MEDIA_PLAY = 57428,
+ KITTY_KEY_MEDIA_PAUSE = 57429,
+ KITTY_KEY_MEDIA_PLAY_PAUSE = 57430,
+ KITTY_KEY_MEDIA_REVERSE = 57431,
+ KITTY_KEY_MEDIA_STOP = 57432,
+ KITTY_KEY_MEDIA_FAST_FORWARD = 57433,
+ KITTY_KEY_MEDIA_REWIND = 57434,
+ KITTY_KEY_MEDIA_TRACK_NEXT = 57435,
+ KITTY_KEY_MEDIA_TRACK_PREVIOUS = 57436,
+ KITTY_KEY_MEDIA_RECORD = 57437,
+ KITTY_KEY_LOWER_VOLUME = 57438,
+ KITTY_KEY_RAISE_VOLUME = 57439,
+ KITTY_KEY_MUTE_VOLUME = 57440,
+ KITTY_KEY_LEFT_SHIFT = 57441,
+ KITTY_KEY_LEFT_CONTROL = 57442,
+ KITTY_KEY_LEFT_ALT = 57443,
+ KITTY_KEY_LEFT_SUPER = 57444,
+ KITTY_KEY_LEFT_HYPER = 57445,
+ KITTY_KEY_LEFT_META = 57446,
+ KITTY_KEY_RIGHT_SHIFT = 57447,
+ KITTY_KEY_RIGHT_CONTROL = 57448,
+ KITTY_KEY_RIGHT_ALT = 57449,
+ KITTY_KEY_RIGHT_SUPER = 57450,
+ KITTY_KEY_RIGHT_HYPER = 57451,
+ KITTY_KEY_RIGHT_META = 57452,
+ KITTY_KEY_ISO_LEVEL3_SHIFT = 57453,
+ KITTY_KEY_ISO_LEVEL5_SHIFT = 57454,
+} KittyKey;
+
+#endif // NVIM_TUI_INPUT_DEFS_H