mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
Merge pull request #19180 from zeertzjq/tui-kitty-keypad
feat(tui): recognize keypad keys when using kitty keyboard protocol
This commit is contained in:
commit
4cded8cec1
@ -111,11 +111,17 @@ width of the terminal.
|
||||
*tui-input*
|
||||
Nvim uses libtermkey to convert terminal escape sequences to key codes.
|
||||
|terminfo| is used first, and CSI sequences not in |terminfo| (including
|
||||
extended keys a.k.a. modifyOtherKeys or `CSI u`) can also be parsed.
|
||||
extended keys a.k.a. modifyOtherKeys or "CSI u") can also be parsed.
|
||||
For example, when running Nvim in tmux, this makes Nvim leave Insert mode and
|
||||
go to the window below: >
|
||||
tmux send-keys 'Escape' [ 2 7 u 'C-W' j
|
||||
Where `'Escape' [ 2 7 u` is an unambiguous `CSI u` sequence for the <Esc> key.
|
||||
tmux send-keys 'Escape' [ 2 7 u 'C-W' j
|
||||
Where `'Escape' [ 2 7 u` is an unambiguous "CSI u" sequence for the <Esc> key.
|
||||
|
||||
The kitty keyboard protocol https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
||||
is partially supported, including keypad keys in Unicode Private Use Area.
|
||||
For example, this sequence is recognized by Nvim as <C-kEnter>: >
|
||||
CSI 57414 ; 5 u
|
||||
and can be used differently from <C-CR> in mappings.
|
||||
|
||||
*tui-modifyOtherKeys* *tui-csiu*
|
||||
Historically, terminal emulators could not distinguish between certain control
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
118
src/nvim/tui/input_defs.h
Normal file
118
src/nvim/tui/input_defs.h
Normal file
@ -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
|
@ -20,6 +20,7 @@ local nvim_prog = helpers.nvim_prog
|
||||
local nvim_set = helpers.nvim_set
|
||||
local ok = helpers.ok
|
||||
local read_file = helpers.read_file
|
||||
local funcs = helpers.funcs
|
||||
|
||||
if helpers.pending_win32(pending) then return end
|
||||
|
||||
@ -297,6 +298,179 @@ describe('TUI', function()
|
||||
]], attrs)
|
||||
end)
|
||||
|
||||
it('accepts keypad keys from kitty keyboard protocol #19180', function()
|
||||
feed_data('i')
|
||||
feed_data(funcs.nr2char(57399)) -- KP_0
|
||||
feed_data(funcs.nr2char(57400)) -- KP_1
|
||||
feed_data(funcs.nr2char(57401)) -- KP_2
|
||||
feed_data(funcs.nr2char(57402)) -- KP_3
|
||||
feed_data(funcs.nr2char(57403)) -- KP_4
|
||||
feed_data(funcs.nr2char(57404)) -- KP_5
|
||||
feed_data(funcs.nr2char(57405)) -- KP_6
|
||||
feed_data(funcs.nr2char(57406)) -- KP_7
|
||||
feed_data(funcs.nr2char(57407)) -- KP_8
|
||||
feed_data(funcs.nr2char(57408)) -- KP_9
|
||||
feed_data(funcs.nr2char(57409)) -- KP_DECIMAL
|
||||
feed_data(funcs.nr2char(57410)) -- KP_DIVIDE
|
||||
feed_data(funcs.nr2char(57411)) -- KP_MULTIPLY
|
||||
feed_data(funcs.nr2char(57412)) -- KP_SUBTRACT
|
||||
feed_data(funcs.nr2char(57413)) -- KP_ADD
|
||||
feed_data(funcs.nr2char(57414)) -- KP_ENTER
|
||||
feed_data(funcs.nr2char(57415)) -- KP_EQUAL
|
||||
screen:expect([[
|
||||
0123456789./*-+ |
|
||||
={1: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
{3:-- INSERT --} |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57417)) -- KP_LEFT
|
||||
screen:expect([[
|
||||
0123456789./*-+ |
|
||||
{1:=} |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
{3:-- INSERT --} |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57418)) -- KP_RIGHT
|
||||
screen:expect([[
|
||||
0123456789./*-+ |
|
||||
={1: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
{3:-- INSERT --} |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57419)) -- KP_UP
|
||||
screen:expect([[
|
||||
0{1:1}23456789./*-+ |
|
||||
= |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
{3:-- INSERT --} |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57420)) -- KP_DOWN
|
||||
screen:expect([[
|
||||
0123456789./*-+ |
|
||||
={1: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
{3:-- INSERT --} |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57425)) -- KP_INSERT
|
||||
screen:expect([[
|
||||
0123456789./*-+ |
|
||||
={1: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
{3:-- REPLACE --} |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data('\027[27u') -- ESC
|
||||
screen:expect([[
|
||||
0123456789./*-+ |
|
||||
{1:=} |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data('\027[57417;5u') -- CTRL + KP_LEFT
|
||||
screen:expect([[
|
||||
{1:0}123456789./*-+ |
|
||||
= |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data('\027[57418;2u') -- SHIFT + KP_RIGHT
|
||||
screen:expect([[
|
||||
0123456789{1:.}/*-+ |
|
||||
= |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57426)) -- KP_DELETE
|
||||
screen:expect([[
|
||||
0123456789{1:/}*-+ |
|
||||
= |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57423)) -- KP_HOME
|
||||
screen:expect([[
|
||||
{1:0}123456789/*-+ |
|
||||
= |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(funcs.nr2char(57424)) -- KP_END
|
||||
screen:expect([[
|
||||
0123456789/*-{1:+} |
|
||||
= |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data(':tab split\r:tabnew\r')
|
||||
feed_data(':highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline\r')
|
||||
local attrs = screen:get_default_attr_ids()
|
||||
attrs[11] = {underline = true}
|
||||
screen:expect([[
|
||||
{11: + [No Name] + [No Name] }{3: [No Name] }{1: }{11:X}|
|
||||
{1: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]], attrs)
|
||||
feed_data('\027[57421;5u') -- CTRL + KP_PAGE_UP
|
||||
screen:expect([[
|
||||
{11: + [No Name] }{3: + [No Name] }{11: [No Name] }{1: }{11:X}|
|
||||
0123456789/*-{1:+} |
|
||||
= |
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]], attrs)
|
||||
feed_data('\027[57422;5u') -- CTRL + KP_PAGE_DOWN
|
||||
screen:expect([[
|
||||
{11: + [No Name] + [No Name] }{3: [No Name] }{1: }{11:X}|
|
||||
{1: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |
|
||||
]], attrs)
|
||||
end)
|
||||
|
||||
it('paste: Insert mode', function()
|
||||
-- "bracketed paste"
|
||||
feed_data('i""\027i\027[200~')
|
||||
|
Loading…
Reference in New Issue
Block a user