diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_docmd.c | 27 | ||||
-rw-r--r-- | src/nvim/generators/gen_ex_cmds.lua | 73 | ||||
-rw-r--r-- | src/nvim/getchar.c | 87 | ||||
-rw-r--r-- | src/nvim/keymap.c | 21 | ||||
-rw-r--r-- | src/nvim/keymap.h | 5 |
5 files changed, 146 insertions, 67 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index fbe41f9914..037b5dec7f 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -2263,8 +2263,11 @@ static char_u * do_one_cmd(char_u **cmdlinep, need_rethrow = check_cstack = FALSE; doend: - if (curwin->w_cursor.lnum == 0) /* can happen with zero line number */ + // can happen with zero line number + if (curwin->w_cursor.lnum == 0) { curwin->w_cursor.lnum = 1; + curwin->w_cursor.col = 0; + } if (errormsg != NULL && *errormsg != NUL && !did_emsg) { if (flags & DOCMD_VERBOSE) { @@ -2440,10 +2443,24 @@ static char_u *find_command(exarg_T *eap, int *full) } } - if (ASCII_ISLOWER(*eap->cmd)) - eap->cmdidx = cmdidxs[CharOrdLow(*eap->cmd)]; - else - eap->cmdidx = cmdidxs[26]; + if (ASCII_ISLOWER(eap->cmd[0])) { + const int c1 = eap->cmd[0]; + const int c2 = eap->cmd[1]; + + if (command_count != (int)CMD_SIZE) { + iemsg((char *)_("E943: Command table needs to be updated, run 'make'")); + getout(1); + } + + // Use a precomputed index for fast look-up in cmdnames[] + // taking into account the first 2 letters of eap->cmd. + eap->cmdidx = cmdidxs1[CharOrdLow(c1)]; + if (ASCII_ISLOWER(c2)) { + eap->cmdidx += cmdidxs2[CharOrdLow(c1)][CharOrdLow(c2)]; + } + } else { + eap->cmdidx = CMD_bang; + } for (; (int)eap->cmdidx < (int)CMD_SIZE; eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1)) diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua index cb566d46ca..7859d7c71a 100644 --- a/src/nvim/generators/gen_ex_cmds.lua +++ b/src/nvim/generators/gen_ex_cmds.lua @@ -28,34 +28,41 @@ local lastchar = nil local i local cmd local first = true -local prevfirstchar = nil local byte_a = string.byte('a') local byte_z = string.byte('z') +local a_to_z = byte_z - byte_a + 1 -local cmdidxs = string.format([[ -static const cmdidx_T cmdidxs[%u] = { -]], byte_z - byte_a + 2) +-- Table giving the index of the first command in cmdnames[] to lookup +-- based on the first letter of a command. +local cmdidxs1_out = string.format([[ +static const uint16_t cmdidxs1[%u] = { +]], a_to_z) +-- Table giving the index of the first command in cmdnames[] to lookup +-- based on the first 2 letters of a command. +-- Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they +-- fit in a byte. +local cmdidxs2_out = string.format([[ +static const char_u cmdidxs2[%u][%u] = { +/* a b c d e f g h i j k l m n o p q r s t u v w x y z */ + +]], a_to_z, a_to_z) enumfile:write([[ typedef enum CMD_index { ]]) defsfile:write(string.format([[ +static const int command_count = %u; +]], #defs)) +defsfile:write(string.format([[ static CommandDefinition cmdnames[%u] = { ]], #defs)) +local cmds, cmdidxs1, cmdidxs2 = {}, {}, {} for i, cmd in ipairs(defs) do local enumname = cmd.enum or ('CMD_' .. cmd.command) - firstchar = string.byte(cmd.command) - if firstchar ~= prevfirstchar then - if (not prevfirstchar - or (byte_a <= firstchar and firstchar <= byte_z) - or (byte_a <= prevfirstchar and prevfirstchar <= byte_z)) then - if not first then - cmdidxs = cmdidxs .. ',\n' - end - cmdidxs = cmdidxs .. ' ' .. enumname - end - prevfirstchar = firstchar + local byte_cmd = cmd.command:sub(1, 1):byte() + if byte_a <= byte_cmd and byte_cmd <= byte_z then + table.insert(cmds, cmd.command) end if first then first = false @@ -71,6 +78,35 @@ for i, cmd in ipairs(defs) do .cmd_addr_type = %i }]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type)) end +for i = #cmds, 1, -1 do + local cmd = cmds[i] + -- First and second characters of the command + local c1 = cmd:sub(1, 1) + cmdidxs1[c1] = i - 1 + if cmd:len() >= 2 then + local c2 = cmd:sub(2, 2) + local byte_c2 = string.byte(c2) + if byte_a <= byte_c2 and byte_c2 <= byte_z then + if not cmdidxs2[c1] then + cmdidxs2[c1] = {} + end + cmdidxs2[c1][c2] = i - 1 + end + end +end +for i = byte_a, byte_z do + local c1 = string.char(i) + cmdidxs1_out = cmdidxs1_out .. ' /* ' .. c1 .. ' */ ' .. cmdidxs1[c1] .. ',\n' + cmdidxs2_out = cmdidxs2_out .. ' /* ' .. c1 .. ' */ {' + for j = byte_a, byte_z do + local c2 = string.char(j) + cmdidxs2_out = cmdidxs2_out .. + ((cmdidxs2[c1] and cmdidxs2[c1][c2]) + and string.format('%3d', cmdidxs2[c1][c2] - cmdidxs1[c1]) + or ' 0') .. ',' + end + cmdidxs2_out = cmdidxs2_out .. ' },\n' +end defsfile:write([[ }; @@ -81,8 +117,5 @@ enumfile:write([[ CMD_USER_BUF = -2 } cmdidx_T; ]]) -cmdidxs = cmdidxs .. [[ - -}; -]] -defsfile:write(cmdidxs) +defsfile:write(cmdidxs1_out .. '};\n') +defsfile:write(cmdidxs2_out .. '};\n') diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 139bf7b802..87a8d9b53e 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1425,49 +1425,52 @@ int vgetc(void) /* a keypad or special function key was not mapped, use it like * its ASCII equivalent */ switch (c) { - case K_KPLUS: c = '+'; break; - case K_KMINUS: c = '-'; break; - case K_KDIVIDE: c = '/'; break; - case K_KMULTIPLY: c = '*'; break; - case K_KENTER: c = CAR; break; - case K_KPOINT: - c = '.'; break; - case K_K0: c = '0'; break; - case K_K1: c = '1'; break; - case K_K2: c = '2'; break; - case K_K3: c = '3'; break; - case K_K4: c = '4'; break; - case K_K5: c = '5'; break; - case K_K6: c = '6'; break; - case K_K7: c = '7'; break; - case K_K8: c = '8'; break; - case K_K9: c = '9'; break; - - case K_XHOME: - case K_ZHOME: if (mod_mask == MOD_MASK_SHIFT) { - c = K_S_HOME; - mod_mask = 0; - } else if (mod_mask == MOD_MASK_CTRL) { - c = K_C_HOME; - mod_mask = 0; - } else - c = K_HOME; - break; - case K_XEND: - case K_ZEND: if (mod_mask == MOD_MASK_SHIFT) { - c = K_S_END; - mod_mask = 0; - } else if (mod_mask == MOD_MASK_CTRL) { - c = K_C_END; - mod_mask = 0; - } else - c = K_END; - break; + case K_KPLUS: c = '+'; break; + case K_KMINUS: c = '-'; break; + case K_KDIVIDE: c = '/'; break; + case K_KMULTIPLY: c = '*'; break; + case K_KENTER: c = CAR; break; + case K_KPOINT: c = '.'; break; + case K_K0: c = '0'; break; + case K_K1: c = '1'; break; + case K_K2: c = '2'; break; + case K_K3: c = '3'; break; + case K_K4: c = '4'; break; + case K_K5: c = '5'; break; + case K_K6: c = '6'; break; + case K_K7: c = '7'; break; + case K_K8: c = '8'; break; + case K_K9: c = '9'; break; + + case K_XHOME: + case K_ZHOME: + if (mod_mask == MOD_MASK_SHIFT) { + c = K_S_HOME; + mod_mask = 0; + } else if (mod_mask == MOD_MASK_CTRL) { + c = K_C_HOME; + mod_mask = 0; + } else { + c = K_HOME; + } + break; + case K_XEND: + case K_ZEND: + if (mod_mask == MOD_MASK_SHIFT) { + c = K_S_END; + mod_mask = 0; + } else if (mod_mask == MOD_MASK_CTRL) { + c = K_C_END; + mod_mask = 0; + } else { + c = K_END; + } + break; - case K_XUP: c = K_UP; break; - case K_XDOWN: c = K_DOWN; break; - case K_XLEFT: c = K_LEFT; break; - case K_XRIGHT: c = K_RIGHT; break; + case K_XUP: c = K_UP; break; + case K_XDOWN: c = K_DOWN; break; + case K_XLEFT: c = K_LEFT; break; + case K_XRIGHT: c = K_RIGHT; break; } /* For a multi-byte character get all the bytes and return the diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index ade5487ec8..ea04f1251e 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -163,6 +163,7 @@ static const struct key_name_entry { { 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" }, @@ -171,6 +172,14 @@ static const struct key_name_entry { { 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" }, @@ -223,24 +232,36 @@ static const struct key_name_entry { { 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_K0, "k0" }, diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index baf8963aa8..92d8777382 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -256,9 +256,13 @@ enum key_extra { #define K_ZERO TERMCAP2KEY(KS_ZERO, KE_FILLER) #define K_UP TERMCAP2KEY('k', 'u') +#define K_KUP TERMCAP2KEY('K', 'u') /* keypad up */ #define K_DOWN TERMCAP2KEY('k', 'd') +#define K_KDOWN TERMCAP2KEY('K', 'd') /* keypad down */ #define K_LEFT TERMCAP2KEY('k', 'l') +#define K_KLEFT TERMCAP2KEY('K', 'l') /* keypad left */ #define K_RIGHT TERMCAP2KEY('k', 'r') +#define K_KRIGHT TERMCAP2KEY('K', 'r') /* keypad right */ #define K_S_UP TERMCAP2KEY(KS_EXTRA, KE_S_UP) #define K_S_DOWN TERMCAP2KEY(KS_EXTRA, KE_S_DOWN) #define K_S_LEFT TERMCAP2KEY('#', '4') @@ -367,6 +371,7 @@ enum key_extra { #define K_PAGEDOWN TERMCAP2KEY('k', 'N') #define K_KPAGEUP TERMCAP2KEY('K', '3') /* keypad pageup (upper R.) */ #define K_KPAGEDOWN TERMCAP2KEY('K', '5') /* keypad pagedown (lower R.) */ +#define K_KORIGIN TERMCAP2KEY('K', '2') /* keypad center */ #define K_KPLUS TERMCAP2KEY('K', '6') /* keypad plus */ #define K_KMINUS TERMCAP2KEY('K', '7') /* keypad minus */ |