diff options
-rw-r--r-- | src/gen/gen_keycodes.lua | 86 | ||||
-rw-r--r-- | src/gen/hashy.lua | 20 | ||||
-rw-r--r-- | src/nvim/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/nvim/keycodes.c | 250 | ||||
-rw-r--r-- | src/nvim/keycodes.lua | 208 | ||||
-rw-r--r-- | test/benchmark/keycodes_spec.lua | 84 |
6 files changed, 414 insertions, 242 deletions
diff --git a/src/gen/gen_keycodes.lua b/src/gen/gen_keycodes.lua new file mode 100644 index 0000000000..53f0c24e58 --- /dev/null +++ b/src/gen/gen_keycodes.lua @@ -0,0 +1,86 @@ +local names_file = arg[1] + +local hashy = require('gen.hashy') +local keycodes = require('nvim.keycodes') + +local keycode_names = keycodes.names + +--- @type table<string,integer> +--- Maps lower-case key names to their original indexes. +local name_orig_idx = {} + +--- @type table<string,integer> +--- Maps keys to the original indexes of their preferred names. +local key_orig_idx = {} + +--- @type [string, string][] +--- When multiple keys have the same name (e.g. TAB and K_TAB), only the first one +--- is added to the two tables above, and the other keys are added here. +local extra_keys = {} + +for i, keycode in ipairs(keycode_names) do + local key = keycode[1] + local name = keycode[2] + local name_lower = name:lower() + if name_orig_idx[name_lower] == nil then + name_orig_idx[name_lower] = i + if key_orig_idx[key] == nil then + key_orig_idx[key] = i + end + else + table.insert(extra_keys, keycode) + end +end + +local hashorder = vim.tbl_keys(name_orig_idx) +table.sort(hashorder) +local hashfun +hashorder, hashfun = hashy.hashy_hash('get_special_key_code', hashorder, function(idx) + return 'key_names_table[' .. idx .. '].name.data' +end, true) + +--- @type table<string,integer> +--- Maps keys to the (after hash) indexes of the entries with preferred names. +local key_hash_idx = {} + +for i, lower_name in ipairs(hashorder) do + local orig_idx = name_orig_idx[lower_name] + local key = keycode_names[orig_idx][1] + if key_orig_idx[key] == orig_idx then + key_hash_idx[key] = i + end +end + +local names_tgt = assert(io.open(names_file, 'w')) +names_tgt:write([[ +static const struct key_name_entry { + int key; ///< Special key code or ascii value + String name; ///< Name of key + const String *pref_name; ///< Pointer to preferred key name + ///< (may be NULL or point to the name in another entry) +} key_names_table[] = {]]) + +for i, lower_name in ipairs(hashorder) do + local keycode = keycode_names[name_orig_idx[lower_name]] + local key = keycode[1] + local name = keycode[2] + local pref_idx = key_hash_idx[key] + names_tgt:write( + ('\n {%s, {"%s", %u}, %s},'):format( + key, + name, + #name, + pref_idx == i and 'NULL' or ('&key_names_table[%u].name'):format(pref_idx - 1) + ) + ) +end + +for _, keycode in ipairs(extra_keys) do + local key = keycode[1] + local name = keycode[2] + names_tgt:write(('\n {%s, {"%s", %u}, NULL},'):format(key, name, #name)) +end + +names_tgt:write('\n};\n\n') +names_tgt:write('static ' .. hashfun) +names_tgt:close() diff --git a/src/gen/hashy.lua b/src/gen/hashy.lua index 74b7655324..48292bfc0e 100644 --- a/src/gen/hashy.lua +++ b/src/gen/hashy.lua @@ -54,7 +54,7 @@ function M.build_pos_hash(strings) return len_pos_buckets, maxlen, worst_buck_size end -function M.switcher(put, tab, maxlen, worst_buck_size) +function M.switcher(put, tab, maxlen, worst_buck_size, lower) local neworder = {} --- @type string[] put ' switch (len) {\n' local bucky = worst_buck_size > 1 @@ -66,7 +66,7 @@ function M.switcher(put, tab, maxlen, worst_buck_size) local keys = vim.tbl_keys(posbuck) if #keys > 1 then table.sort(keys) - put('switch (str[' .. (pos - 1) .. ']) {\n') + put(('switch (%s(str[%s])) {\n'):format(lower and 'TOLOWER_ASC' or '', pos - 1)) for _, c in ipairs(keys) do local buck = posbuck[c] local startidx = #neworder @@ -102,7 +102,7 @@ function M.switcher(put, tab, maxlen, worst_buck_size) return neworder end -function M.hashy_hash(name, strings, access) +function M.hashy_hash(name, strings, access, lower) local stats = {} local put = function(str) table.insert(stats, str) @@ -116,27 +116,27 @@ function M.hashy_hash(name, strings, access) else put(' int low = -1;\n') end - local neworder = M.switcher(put, len_pos_buckets, maxlen, worst_buck_size) + local neworder = M.switcher(put, len_pos_buckets, maxlen, worst_buck_size, lower) if maxlen == 1 then put([[ return -1; ]]) elseif worst_buck_size > 1 then - put([[ + put(([[ for (int i = low; i < high; i++) { - if (!memcmp(str, ]] .. access('i') .. [[, len)) { + if (!%s(str, %s, len)) { return i; } } return -1; -]]) +]]):format(lower and 'mb_strnicmp' or 'memcmp', access('i'))) else - put([[ - if (low < 0 || memcmp(str, ]] .. access('low') .. [[, len)) { + put(([[ + if (low < 0 || %s(str, %s, len)) { return -1; } return low; -]]) +]]):format(lower and 'mb_strnicmp' or 'memcmp', access('low'))) end put '}\n\n' return neworder, table.concat(stats) diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 36bcd5fbce..39c78b3228 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -304,6 +304,7 @@ set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua) set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua) set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua) set(FUNCS_GENERATOR ${GENERATOR_DIR}/gen_eval.lua) +set(KEYCODES_GENERATOR ${GENERATOR_DIR}/gen_keycodes.lua) set(GENERATOR_C_GRAMMAR ${GENERATOR_DIR}/c_grammar.lua) set(GENERATOR_HASHY ${GENERATOR_DIR}/hashy.lua) set(GENERATOR_PRELOAD ${GENERATOR_DIR}/preload_nlua.lua) @@ -318,6 +319,7 @@ set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h) set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h) set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h) set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h) +set(GENERATED_KEYCODE_NAMES ${GENERATED_DIR}/keycode_names.generated.h) set(GENERATED_API_METADATA ${GENERATED_DIR}/api/private/api_metadata.generated.h) set(GENERATED_KEYSETS_DEFS ${GENERATED_DIR}/keysets_defs.generated.h) set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h) @@ -673,6 +675,7 @@ list(APPEND NVIM_GENERATED_FOR_SOURCES "${GENERATED_API_DISPATCH}" "${GENERATED_EX_CMDS_DEFS}" "${GENERATED_EVENTS_NAMES_MAP}" + "${GENERATED_KEYCODE_NAMES}" "${GENERATED_OPTIONS}" "${GENERATED_OPTIONS_MAP}" "${VIM_MODULE_FILE}" @@ -696,6 +699,11 @@ add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} DEPENDS ${LUA_GEN_DEPS} ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua ) +add_custom_command(OUTPUT ${GENERATED_KEYCODE_NAMES} + COMMAND ${LUA_GEN} ${KEYCODES_GENERATOR} ${GENERATED_KEYCODE_NAMES} + DEPENDS ${LUA_GEN_DEPS} ${KEYCODES_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/keycodes.lua +) + add_custom_command(OUTPUT ${GENERATED_OPTIONS} ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP} ${GENERATED_OPTION_VARS} COMMAND ${LUA_GEN} ${OPTIONS_GENERATOR} ${GENERATED_OPTIONS} ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP} ${GENERATED_OPTION_VARS} DEPENDS ${LUA_GEN_DEPS} ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index b6ba73f7c1..9cb2321eee 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -6,6 +6,7 @@ #include <string.h> #include <uv.h> +#include "nvim/api/private/defs.h" #include "nvim/ascii_defs.h" #include "nvim/charset.h" #include "nvim/errors.h" @@ -24,6 +25,7 @@ #include "nvim/strings.h" #ifdef INCLUDE_GENERATED_DECLARATIONS +# include "keycode_names.generated.h" # include "keycodes.c.generated.h" #endif @@ -142,214 +144,6 @@ static uint8_t modifier_keys_table[] = { NUL }; -static const struct key_name_entry { - int key; // Special key code or ascii value - const char *name; // Name of key -} key_names_table[] = { - { ' ', "Space" }, - { TAB, "Tab" }, - { K_TAB, "Tab" }, - { NL, "NL" }, - { NL, "NewLine" }, // Alternative name - { NL, "LineFeed" }, // Alternative name - { NL, "LF" }, // Alternative name - { CAR, "CR" }, - { CAR, "Return" }, // Alternative name - { CAR, "Enter" }, // Alternative name - { K_BS, "BS" }, - { K_BS, "BackSpace" }, // Alternative name - { ESC, "Esc" }, - { ESC, "Escape" }, // Alternative name - { CSI, "CSI" }, - { '|', "Bar" }, - { '\\', "Bslash" }, - { K_DEL, "Del" }, - { K_DEL, "Delete" }, // Alternative name - { K_KDEL, "kDel" }, - { K_KDEL, "KPPeriod" }, // libtermkey name - { K_UP, "Up" }, - { K_DOWN, "Down" }, - { K_LEFT, "Left" }, - { K_RIGHT, "Right" }, - { K_XUP, "xUp" }, - { K_XDOWN, "xDown" }, - { K_XLEFT, "xLeft" }, - { K_XRIGHT, "xRight" }, - { K_KUP, "kUp" }, - { K_KUP, "KP8" }, - { K_KDOWN, "kDown" }, - { K_KDOWN, "KP2" }, - { K_KLEFT, "kLeft" }, - { K_KLEFT, "KP4" }, - { K_KRIGHT, "kRight" }, - { K_KRIGHT, "KP6" }, - - { K_F1, "F1" }, - { K_F2, "F2" }, - { K_F3, "F3" }, - { K_F4, "F4" }, - { K_F5, "F5" }, - { K_F6, "F6" }, - { K_F7, "F7" }, - { K_F8, "F8" }, - { K_F9, "F9" }, - { K_F10, "F10" }, - - { K_F11, "F11" }, - { K_F12, "F12" }, - { K_F13, "F13" }, - { K_F14, "F14" }, - { K_F15, "F15" }, - { K_F16, "F16" }, - { K_F17, "F17" }, - { K_F18, "F18" }, - { K_F19, "F19" }, - { K_F20, "F20" }, - - { K_F21, "F21" }, - { K_F22, "F22" }, - { K_F23, "F23" }, - { K_F24, "F24" }, - { K_F25, "F25" }, - { K_F26, "F26" }, - { K_F27, "F27" }, - { K_F28, "F28" }, - { K_F29, "F29" }, - { K_F30, "F30" }, - - { K_F31, "F31" }, - { K_F32, "F32" }, - { K_F33, "F33" }, - { K_F34, "F34" }, - { K_F35, "F35" }, - { K_F36, "F36" }, - { K_F37, "F37" }, - { K_F38, "F38" }, - { K_F39, "F39" }, - { K_F40, "F40" }, - - { K_F41, "F41" }, - { K_F42, "F42" }, - { K_F43, "F43" }, - { K_F44, "F44" }, - { K_F45, "F45" }, - { K_F46, "F46" }, - { K_F47, "F47" }, - { K_F48, "F48" }, - { K_F49, "F49" }, - { K_F50, "F50" }, - - { K_F51, "F51" }, - { K_F52, "F52" }, - { K_F53, "F53" }, - { K_F54, "F54" }, - { K_F55, "F55" }, - { K_F56, "F56" }, - { K_F57, "F57" }, - { K_F58, "F58" }, - { K_F59, "F59" }, - { K_F60, "F60" }, - - { K_F61, "F61" }, - { K_F62, "F62" }, - { K_F63, "F63" }, - - { K_XF1, "xF1" }, - { K_XF2, "xF2" }, - { K_XF3, "xF3" }, - { K_XF4, "xF4" }, - - { K_HELP, "Help" }, - { K_UNDO, "Undo" }, - { K_FIND, "Find" }, // DEC key, often used as 'Home' - { K_KSELECT, "Select" }, // DEC key, often used as 'End' - { K_INS, "Insert" }, - { K_INS, "Ins" }, // Alternative name - { K_KINS, "kInsert" }, - { K_KINS, "KP0" }, - { K_HOME, "Home" }, - { K_KHOME, "kHome" }, - { K_KHOME, "KP7" }, - { K_XHOME, "xHome" }, - { K_ZHOME, "zHome" }, - { K_END, "End" }, - { K_KEND, "kEnd" }, - { K_KEND, "KP1" }, - { K_XEND, "xEnd" }, - { K_ZEND, "zEnd" }, - { K_PAGEUP, "PageUp" }, - { K_PAGEDOWN, "PageDown" }, - { K_KPAGEUP, "kPageUp" }, - { K_KPAGEUP, "KP9" }, - { K_KPAGEDOWN, "kPageDown" }, - { K_KPAGEDOWN, "KP3" }, - { K_KORIGIN, "kOrigin" }, - { K_KORIGIN, "KP5" }, - - { K_KPLUS, "kPlus" }, - { K_KPLUS, "KPPlus" }, - { K_KMINUS, "kMinus" }, - { K_KMINUS, "KPMinus" }, - { K_KDIVIDE, "kDivide" }, - { K_KDIVIDE, "KPDiv" }, - { K_KMULTIPLY, "kMultiply" }, - { K_KMULTIPLY, "KPMult" }, - { K_KENTER, "kEnter" }, - { K_KENTER, "KPEnter" }, - { K_KPOINT, "kPoint" }, - { K_KCOMMA, "kComma" }, - { K_KCOMMA, "KPComma" }, - { K_KEQUAL, "kEqual" }, - { K_KEQUAL, "KPEquals" }, - - { K_K0, "k0" }, - { K_K1, "k1" }, - { K_K2, "k2" }, - { K_K3, "k3" }, - { K_K4, "k4" }, - { K_K5, "k5" }, - { K_K6, "k6" }, - { K_K7, "k7" }, - { K_K8, "k8" }, - { K_K9, "k9" }, - - { '<', "lt" }, - - { K_MOUSE, "Mouse" }, - { K_LEFTMOUSE, "LeftMouse" }, - { K_LEFTMOUSE_NM, "LeftMouseNM" }, - { K_LEFTDRAG, "LeftDrag" }, - { K_LEFTRELEASE, "LeftRelease" }, - { K_LEFTRELEASE_NM, "LeftReleaseNM" }, - { K_MOUSEMOVE, "MouseMove" }, - { K_MIDDLEMOUSE, "MiddleMouse" }, - { K_MIDDLEDRAG, "MiddleDrag" }, - { K_MIDDLERELEASE, "MiddleRelease" }, - { K_RIGHTMOUSE, "RightMouse" }, - { K_RIGHTDRAG, "RightDrag" }, - { K_RIGHTRELEASE, "RightRelease" }, - { K_MOUSEDOWN, "ScrollWheelUp" }, - { K_MOUSEUP, "ScrollWheelDown" }, - { K_MOUSELEFT, "ScrollWheelRight" }, - { K_MOUSERIGHT, "ScrollWheelLeft" }, - { K_MOUSEDOWN, "MouseDown" }, // OBSOLETE: Use - { K_MOUSEUP, "MouseUp" }, // ScrollWheelXXX instead - { K_X1MOUSE, "X1Mouse" }, - { K_X1DRAG, "X1Drag" }, - { K_X1RELEASE, "X1Release" }, - { K_X2MOUSE, "X2Mouse" }, - { K_X2DRAG, "X2Drag" }, - { K_X2RELEASE, "X2Release" }, - { K_DROP, "Drop" }, - { K_ZERO, "Nul" }, - { K_SNR, "SNR" }, - { K_PLUG, "Plug" }, - { K_IGNORE, "Ignore" }, - { K_COMMAND, "Cmd" }, - { 0, NULL } - // NOTE: When adding a long name update MAX_KEY_NAME_LEN. -}; - static struct mousetable { int pseudo_code; // Code for pseudo mouse event int button; // Which mouse button is it? @@ -544,15 +338,18 @@ char *get_special_key_name(int c, int modifiers) } } } else { // use name of special key - size_t len = strlen(key_names_table[table_idx].name); + const String *s = key_names_table[table_idx].pref_name != NULL + ? key_names_table[table_idx].pref_name + : &key_names_table[table_idx].name; - if ((int)len + idx + 2 <= MAX_KEY_NAME_LEN) { - STRCPY(string + idx, key_names_table[table_idx].name); - idx += (int)len; + if ((int)s->size + idx + 2 <= MAX_KEY_NAME_LEN) { + STRCPY(string + idx, s->data); + idx += (int)s->size; } } string[idx++] = '>'; string[idx] = NUL; + return string; } @@ -795,17 +592,13 @@ static int extract_modifiers(int key, int *modp, const bool simplify, bool *cons /// @return the index when found, -1 when not found. int find_special_key_in_table(int c) { - int i; - - for (i = 0; key_names_table[i].name != NULL; i++) { + for (int i = 0; i < (int)ARRAY_SIZE(key_names_table); i++) { if (c == key_names_table[i].key) { - break; + return i; } } - if (key_names_table[i].name == NULL) { - i = -1; - } - return i; + + return -1; } /// Find the special key with the given name @@ -823,20 +616,13 @@ int get_special_key_code(const char *name) return TERMCAP2KEY((uint8_t)name[2], (uint8_t)name[3]); } - for (int i = 0; key_names_table[i].name != NULL; i++) { - const char *const table_name = key_names_table[i].name; - int j; - for (j = 0; ascii_isident((uint8_t)name[j]) && table_name[j] != NUL; j++) { - if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC((uint8_t)name[j])) { - break; - } - } - if (!ascii_isident((uint8_t)name[j]) && table_name[j] == NUL) { - return key_names_table[i].key; - } + const char *name_end = name; + while (ascii_isident(*name_end)) { + name_end++; } - return 0; + int idx = get_special_key_code_hash(name, (size_t)(name_end - name)); + return idx >= 0 ? key_names_table[idx].key : 0; } /// Look up the given mouse code to return the relevant information in the other arguments. diff --git a/src/nvim/keycodes.lua b/src/nvim/keycodes.lua new file mode 100644 index 0000000000..04f09eb005 --- /dev/null +++ b/src/nvim/keycodes.lua @@ -0,0 +1,208 @@ +return { + --- @type [string, string][] List of [key, name] tuples. + --- For keys with multiple names, put the preferred name first. + --- For multiple keys with the same name, put the preferred key first. + names = { + { [[' ']], 'Space' }, + { [[TAB]], 'Tab' }, + { [[K_TAB]], 'Tab' }, + { [[NL]], 'NL' }, + { [[NL]], 'NewLine' }, -- Alternative name + { [[NL]], 'LineFeed' }, -- Alternative name + { [[NL]], 'LF' }, -- Alternative name + { [[CAR]], 'CR' }, + { [[CAR]], 'Return' }, -- Alternative name + { [[CAR]], 'Enter' }, -- Alternative name + { [[K_BS]], 'BS' }, + { [[K_BS]], 'BackSpace' }, -- Alternative name + { [[ESC]], 'Esc' }, + { [[ESC]], 'Escape' }, -- Alternative name + { [[CSI]], 'CSI' }, + { [['|']], 'Bar' }, + { [['\\']], 'Bslash' }, + { [[K_DEL]], 'Del' }, + { [[K_DEL]], 'Delete' }, -- Alternative name + { [[K_KDEL]], 'kDel' }, + { [[K_KDEL]], 'KPPeriod' }, -- libtermkey name + { [[K_UP]], 'Up' }, + { [[K_DOWN]], 'Down' }, + { [[K_LEFT]], 'Left' }, + { [[K_RIGHT]], 'Right' }, + { [[K_XUP]], 'xUp' }, + { [[K_XDOWN]], 'xDown' }, + { [[K_XLEFT]], 'xLeft' }, + { [[K_XRIGHT]], 'xRight' }, + { [[K_KUP]], 'kUp' }, + { [[K_KUP]], 'KP8' }, + { [[K_KDOWN]], 'kDown' }, + { [[K_KDOWN]], 'KP2' }, + { [[K_KLEFT]], 'kLeft' }, + { [[K_KLEFT]], 'KP4' }, + { [[K_KRIGHT]], 'kRight' }, + { [[K_KRIGHT]], 'KP6' }, + + { [[K_F1]], 'F1' }, + { [[K_F2]], 'F2' }, + { [[K_F3]], 'F3' }, + { [[K_F4]], 'F4' }, + { [[K_F5]], 'F5' }, + { [[K_F6]], 'F6' }, + { [[K_F7]], 'F7' }, + { [[K_F8]], 'F8' }, + { [[K_F9]], 'F9' }, + { [[K_F10]], 'F10' }, + + { [[K_F11]], 'F11' }, + { [[K_F12]], 'F12' }, + { [[K_F13]], 'F13' }, + { [[K_F14]], 'F14' }, + { [[K_F15]], 'F15' }, + { [[K_F16]], 'F16' }, + { [[K_F17]], 'F17' }, + { [[K_F18]], 'F18' }, + { [[K_F19]], 'F19' }, + { [[K_F20]], 'F20' }, + + { [[K_F21]], 'F21' }, + { [[K_F22]], 'F22' }, + { [[K_F23]], 'F23' }, + { [[K_F24]], 'F24' }, + { [[K_F25]], 'F25' }, + { [[K_F26]], 'F26' }, + { [[K_F27]], 'F27' }, + { [[K_F28]], 'F28' }, + { [[K_F29]], 'F29' }, + { [[K_F30]], 'F30' }, + + { [[K_F31]], 'F31' }, + { [[K_F32]], 'F32' }, + { [[K_F33]], 'F33' }, + { [[K_F34]], 'F34' }, + { [[K_F35]], 'F35' }, + { [[K_F36]], 'F36' }, + { [[K_F37]], 'F37' }, + { [[K_F38]], 'F38' }, + { [[K_F39]], 'F39' }, + { [[K_F40]], 'F40' }, + + { [[K_F41]], 'F41' }, + { [[K_F42]], 'F42' }, + { [[K_F43]], 'F43' }, + { [[K_F44]], 'F44' }, + { [[K_F45]], 'F45' }, + { [[K_F46]], 'F46' }, + { [[K_F47]], 'F47' }, + { [[K_F48]], 'F48' }, + { [[K_F49]], 'F49' }, + { [[K_F50]], 'F50' }, + + { [[K_F51]], 'F51' }, + { [[K_F52]], 'F52' }, + { [[K_F53]], 'F53' }, + { [[K_F54]], 'F54' }, + { [[K_F55]], 'F55' }, + { [[K_F56]], 'F56' }, + { [[K_F57]], 'F57' }, + { [[K_F58]], 'F58' }, + { [[K_F59]], 'F59' }, + { [[K_F60]], 'F60' }, + + { [[K_F61]], 'F61' }, + { [[K_F62]], 'F62' }, + { [[K_F63]], 'F63' }, + + { [[K_XF1]], 'xF1' }, + { [[K_XF2]], 'xF2' }, + { [[K_XF3]], 'xF3' }, + { [[K_XF4]], 'xF4' }, + + { [[K_HELP]], 'Help' }, + { [[K_UNDO]], 'Undo' }, + { [[K_FIND]], 'Find' }, -- DEC key, often used as 'Home' + { [[K_KSELECT]], 'Select' }, -- DEC key, often used as 'End' + { [[K_INS]], 'Insert' }, + { [[K_INS]], 'Ins' }, -- Alternative name + { [[K_KINS]], 'kInsert' }, + { [[K_KINS]], 'KP0' }, + { [[K_HOME]], 'Home' }, + { [[K_KHOME]], 'kHome' }, + { [[K_KHOME]], 'KP7' }, + { [[K_XHOME]], 'xHome' }, + { [[K_ZHOME]], 'zHome' }, + { [[K_END]], 'End' }, + { [[K_KEND]], 'kEnd' }, + { [[K_KEND]], 'KP1' }, + { [[K_XEND]], 'xEnd' }, + { [[K_ZEND]], 'zEnd' }, + { [[K_PAGEUP]], 'PageUp' }, + { [[K_PAGEDOWN]], 'PageDown' }, + { [[K_KPAGEUP]], 'kPageUp' }, + { [[K_KPAGEUP]], 'KP9' }, + { [[K_KPAGEDOWN]], 'kPageDown' }, + { [[K_KPAGEDOWN]], 'KP3' }, + { [[K_KORIGIN]], 'kOrigin' }, + { [[K_KORIGIN]], 'KP5' }, + + { [[K_KPLUS]], 'kPlus' }, + { [[K_KPLUS]], 'KPPlus' }, + { [[K_KMINUS]], 'kMinus' }, + { [[K_KMINUS]], 'KPMinus' }, + { [[K_KDIVIDE]], 'kDivide' }, + { [[K_KDIVIDE]], 'KPDiv' }, + { [[K_KMULTIPLY]], 'kMultiply' }, + { [[K_KMULTIPLY]], 'KPMult' }, + { [[K_KENTER]], 'kEnter' }, + { [[K_KENTER]], 'KPEnter' }, + { [[K_KPOINT]], 'kPoint' }, + { [[K_KCOMMA]], 'kComma' }, + { [[K_KCOMMA]], 'KPComma' }, + { [[K_KEQUAL]], 'kEqual' }, + { [[K_KEQUAL]], 'KPEquals' }, + + { [[K_K0]], 'k0' }, + { [[K_K1]], 'k1' }, + { [[K_K2]], 'k2' }, + { [[K_K3]], 'k3' }, + { [[K_K4]], 'k4' }, + { [[K_K5]], 'k5' }, + { [[K_K6]], 'k6' }, + { [[K_K7]], 'k7' }, + { [[K_K8]], 'k8' }, + { [[K_K9]], 'k9' }, + + { [['<']], 'lt' }, + + { [[K_MOUSE]], 'Mouse' }, + { [[K_LEFTMOUSE]], 'LeftMouse' }, + { [[K_LEFTMOUSE_NM]], 'LeftMouseNM' }, + { [[K_LEFTDRAG]], 'LeftDrag' }, + { [[K_LEFTRELEASE]], 'LeftRelease' }, + { [[K_LEFTRELEASE_NM]], 'LeftReleaseNM' }, + { [[K_MOUSEMOVE]], 'MouseMove' }, + { [[K_MIDDLEMOUSE]], 'MiddleMouse' }, + { [[K_MIDDLEDRAG]], 'MiddleDrag' }, + { [[K_MIDDLERELEASE]], 'MiddleRelease' }, + { [[K_RIGHTMOUSE]], 'RightMouse' }, + { [[K_RIGHTDRAG]], 'RightDrag' }, + { [[K_RIGHTRELEASE]], 'RightRelease' }, + { [[K_MOUSEDOWN]], 'ScrollWheelUp' }, + { [[K_MOUSEUP]], 'ScrollWheelDown' }, + { [[K_MOUSELEFT]], 'ScrollWheelRight' }, + { [[K_MOUSERIGHT]], 'ScrollWheelLeft' }, + { [[K_MOUSEDOWN]], 'MouseDown' }, -- OBSOLETE: Use ScrollWheelUp instead + { [[K_MOUSEUP]], 'MouseUp' }, -- OBSOLETE: Use ScrollWheelDown instead + { [[K_X1MOUSE]], 'X1Mouse' }, + { [[K_X1DRAG]], 'X1Drag' }, + { [[K_X1RELEASE]], 'X1Release' }, + { [[K_X2MOUSE]], 'X2Mouse' }, + { [[K_X2DRAG]], 'X2Drag' }, + { [[K_X2RELEASE]], 'X2Release' }, + { [[K_DROP]], 'Drop' }, + { [[K_ZERO]], 'Nul' }, + { [[K_SNR]], 'SNR' }, + { [[K_PLUG]], 'Plug' }, + { [[K_IGNORE]], 'Ignore' }, + { [[K_COMMAND]], 'Cmd' }, + -- NOTE: When adding a long name update MAX_KEY_NAME_LEN. + }, +} diff --git a/test/benchmark/keycodes_spec.lua b/test/benchmark/keycodes_spec.lua new file mode 100644 index 0000000000..443df2a6fb --- /dev/null +++ b/test/benchmark/keycodes_spec.lua @@ -0,0 +1,84 @@ +local n = require('test.functional.testnvim')() +local clear = n.clear +local api = n.api +local fn = n.fn + +local keycodes = require('src.nvim.keycodes') + +describe('nvim_replace_termcodes performance', function() + it('200 calls with a key repeated 5000 times', function() + clear() + local stats = {} + local sum = 0 + local ms = 1 / 1000000 + + for _, keycode in ipairs(keycodes.names) do + local notation = ('<%s>'):format(keycode[2]) + local str = notation:rep(5000) + + local start = vim.uv.hrtime() + for _ = 1, 200 do + api.nvim_replace_termcodes(str, false, true, true) + end + local elapsed = vim.uv.hrtime() - start + + table.insert(stats, elapsed) + sum = sum + elapsed + io.stdout:write(('\n%-20s%14.6f ms'):format(notation, elapsed * ms)) + io.stdout:flush() + end + io.stdout:write('\n') + + table.sort(stats) + print(('%18s'):rep(6):format('avg', 'min', '25%', 'median', '75%', 'max')) + print( + (' %14.6f ms'):rep(6):format( + sum / #stats * ms, + stats[1] * ms, + stats[1 + math.floor(#stats * 0.25)] * ms, + stats[1 + math.floor(#stats * 0.5)] * ms, + stats[1 + math.floor(#stats * 0.75)] * ms, + stats[#stats] * ms + ) + ) + end) +end) + +describe('keytrans() performance', function() + it('200 calls with a key repeated 5000 times', function() + clear() + local stats = {} + local sum = 0 + local ms = 1 / 1000000 + + for _, keycode in ipairs(keycodes.names) do + local notation = ('<%s>'):format(keycode[2]) + local str = api.nvim_replace_termcodes(notation, false, true, true):rep(5000) + + local start = vim.uv.hrtime() + for _ = 1, 200 do + fn.keytrans(str) + end + local elapsed = vim.uv.hrtime() - start + + table.insert(stats, elapsed) + sum = sum + elapsed + io.stdout:write(('\n%-20s%14.6f ms'):format(notation, elapsed * ms)) + io.stdout:flush() + end + io.stdout:write('\n') + + table.sort(stats) + print((' %17s'):rep(6):format('avg', 'min', '25%', 'median', '75%', 'max')) + print( + (' %14.6f ms'):rep(6):format( + sum / #stats * ms, + stats[1] * ms, + stats[1 + math.floor(#stats * 0.25)] * ms, + stats[1 + math.floor(#stats * 0.5)] * ms, + stats[1 + math.floor(#stats * 0.75)] * ms, + stats[#stats] * ms + ) + ) + end) +end) |