aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_docmd.c27
-rw-r--r--src/nvim/generators/gen_ex_cmds.lua73
-rw-r--r--src/nvim/getchar.c87
-rw-r--r--src/nvim/keymap.c21
-rw-r--r--src/nvim/keymap.h5
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 */