aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/tui/input.c')
-rw-r--r--src/nvim/tui/input.c163
1 files changed, 144 insertions, 19 deletions
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;
+ }
}
}