mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
Merge pull request #32768 from zeertzjq/vim-9.1.1179
perf(keycodes): use hashy for string lookup
This commit is contained in:
86
src/gen/gen_keycodes.lua
Normal file
86
src/gen/gen_keycodes.lua
Normal file
@@ -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()
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
208
src/nvim/keycodes.lua
Normal file
208
src/nvim/keycodes.lua
Normal file
@@ -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.
|
||||
},
|
||||
}
|
84
test/benchmark/keycodes_spec.lua
Normal file
84
test/benchmark/keycodes_spec.lua
Normal file
@@ -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)
|
Reference in New Issue
Block a user