gen_ex_cmds.lua: build the command table

Lua port of create_cmdidxs.vim from 8.0.0572

N/A:
vim-patch:8.0.0572: building the command table requires Perl

Problem:    Building the command table requires Perl.
Solution:   Use a Vim script solution. (Dominique Pelle, closes vim/vim#1641)
6de5e12601
This commit is contained in:
Jan Edmund Lazo 2019-03-10 17:41:18 -04:00
parent 07a5c9d4f0
commit 63025a1d65
2 changed files with 58 additions and 24 deletions

View File

@ -155,8 +155,6 @@ struct dbg_stuff {
# include "ex_cmds_defs.generated.h" # include "ex_cmds_defs.generated.h"
#endif #endif
static const int command_count = 539;
static char_u dollar_command[2] = {'$', 0}; static char_u dollar_command[2] = {'$', 0};
static void save_dbg_stuff(struct dbg_stuff *dsp) static void save_dbg_stuff(struct dbg_stuff *dsp)
@ -2265,8 +2263,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
need_rethrow = check_cstack = FALSE; need_rethrow = check_cstack = FALSE;
doend: 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.lnum = 1;
curwin->w_cursor.col = 0;
}
if (errormsg != NULL && *errormsg != NUL && !did_emsg) { if (errormsg != NULL && *errormsg != NUL && !did_emsg) {
if (flags & DOCMD_VERBOSE) { if (flags & DOCMD_VERBOSE) {
@ -2447,7 +2448,7 @@ static char_u *find_command(exarg_T *eap, int *full)
const int c2 = eap->cmd[1]; const int c2 = eap->cmd[1];
if (command_count != (int)CMD_SIZE) { if (command_count != (int)CMD_SIZE) {
iemsg((char_u *)_("E943: Command table needs to be updated, run 'make cmdidxs'")); iemsg((char *)_("E943: Command table needs to be updated, run 'make'"));
getout(1); getout(1);
} }

View File

@ -28,34 +28,41 @@ local lastchar = nil
local i local i
local cmd local cmd
local first = true local first = true
local prevfirstchar = nil
local byte_a = string.byte('a') local byte_a = string.byte('a')
local byte_z = string.byte('z') local byte_z = string.byte('z')
local a_to_z = byte_z - byte_a + 1
local cmdidxs = string.format([[ -- Table giving the index of the first command in cmdnames[] to lookup
static const cmdidx_T cmdidxs[%u] = { -- based on the first letter of a command.
]], byte_z - byte_a + 2) 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([[ enumfile:write([[
typedef enum CMD_index { typedef enum CMD_index {
]]) ]])
defsfile:write(string.format([[ defsfile:write(string.format([[
static const int command_count = %u;
]], #defs))
defsfile:write(string.format([[
static CommandDefinition cmdnames[%u] = { static CommandDefinition cmdnames[%u] = {
]], #defs)) ]], #defs))
local cmds, cmdidxs1, cmdidxs2 = {}, {}, {}
for i, cmd in ipairs(defs) do for i, cmd in ipairs(defs) do
local enumname = cmd.enum or ('CMD_' .. cmd.command) local enumname = cmd.enum or ('CMD_' .. cmd.command)
firstchar = string.byte(cmd.command) local byte_cmd = cmd.command:sub(1, 1):byte()
if firstchar ~= prevfirstchar then if byte_a <= byte_cmd and byte_cmd <= byte_z then
if (not prevfirstchar table.insert(cmds, cmd.command)
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
end end
if first then if first then
first = false first = false
@ -71,6 +78,35 @@ for i, cmd in ipairs(defs) do
.cmd_addr_type = %i .cmd_addr_type = %i
}]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type)) }]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type))
end 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([[ defsfile:write([[
}; };
@ -81,8 +117,5 @@ enumfile:write([[
CMD_USER_BUF = -2 CMD_USER_BUF = -2
} cmdidx_T; } cmdidx_T;
]]) ]])
cmdidxs = cmdidxs .. [[ defsfile:write(cmdidxs1_out .. '};\n')
defsfile:write(cmdidxs2_out .. '};\n')
};
]]
defsfile:write(cmdidxs)