gen_ex_cmds.lua (5035B)
1 -- Will generate files ex_cmds_enum.generated.h with cmdidx_T enum 2 -- and ex_cmds_defs.generated.h with main Ex commands definitions. 3 4 local enumfname = arg[1] -- '/ex_cmds_enum.generated.h' 5 local defsfname = arg[2] -- '/ex_cmds_defs.generated.h' 6 local ex_cmds_name = arg[3] -- 'ex_cmds.lua' 7 8 local enumfile = io.open(enumfname, 'w') 9 local defsfile = io.open(defsfname, 'w') 10 11 local bit = require 'bit' 12 local ex_cmds = loadfile(ex_cmds_name)() 13 local defs = ex_cmds.cmds 14 local flags = ex_cmds.flags 15 16 local byte_a = string.byte('a') 17 local byte_z = string.byte('z') 18 local a_to_z = byte_z - byte_a + 1 19 20 -- Table giving the index of the first command in cmdnames[] to lookup 21 -- based on the first letter of a command. 22 local cmdidxs1_out = string.format( 23 [[ 24 static const uint16_t cmdidxs1[%u] = { 25 ]], 26 a_to_z 27 ) 28 -- Table giving the index of the first command in cmdnames[] to lookup 29 -- based on the first 2 letters of a command. 30 -- Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they 31 -- fit in a byte. 32 local cmdidxs2_out = string.format( 33 [[ 34 static const uint8_t cmdidxs2[%u][%u] = { 35 /* 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 */ 36 ]], 37 a_to_z, 38 a_to_z 39 ) 40 41 enumfile:write([[ 42 // IWYU pragma: private, include "nvim/ex_cmds_defs.h" 43 44 typedef enum CMD_index { 45 ]]) 46 defsfile:write(string.format( 47 [[ 48 #include "nvim/arglist.h" 49 #include "nvim/autocmd.h" 50 #include "nvim/buffer.h" 51 #include "nvim/cmdhist.h" 52 #include "nvim/debugger.h" 53 #include "nvim/diff.h" 54 #include "nvim/digraph.h" 55 #include "nvim/eval.h" 56 #include "nvim/eval/userfunc.h" 57 #include "nvim/eval/vars.h" 58 #include "nvim/ex_cmds.h" 59 #include "nvim/ex_cmds2.h" 60 #include "nvim/ex_docmd.h" 61 #include "nvim/ex_eval.h" 62 #include "nvim/ex_session.h" 63 #include "nvim/help.h" 64 #include "nvim/indent.h" 65 #include "nvim/lua/executor.h" 66 #include "nvim/lua/secure.h" 67 #include "nvim/mapping.h" 68 #include "nvim/mark.h" 69 #include "nvim/match.h" 70 #include "nvim/menu.h" 71 #include "nvim/message.h" 72 #include "nvim/ops.h" 73 #include "nvim/option.h" 74 #include "nvim/os/lang.h" 75 #include "nvim/profile.h" 76 #include "nvim/quickfix.h" 77 #include "nvim/register.h" 78 #include "nvim/runtime.h" 79 #include "nvim/sign.h" 80 #include "nvim/spell.h" 81 #include "nvim/spellfile.h" 82 #include "nvim/syntax.h" 83 #include "nvim/undo.h" 84 #include "nvim/usercmd.h" 85 #include "nvim/version.h" 86 87 static const int command_count = %u; 88 static CommandDefinition cmdnames[%u] = { 89 ]], 90 #defs, 91 #defs 92 )) 93 local cmds, cmdidxs1, cmdidxs2 = {}, {}, {} 94 for _, cmd in ipairs(defs) do 95 if bit.band(cmd.flags, flags.RANGE) == flags.RANGE then 96 assert( 97 cmd.addr_type ~= 'ADDR_NONE', 98 string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command) 99 ) 100 else 101 assert( 102 cmd.addr_type == 'ADDR_NONE', 103 string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command) 104 ) 105 end 106 if bit.band(cmd.flags, flags.DFLALL) == flags.DFLALL then 107 assert( 108 cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE', 109 string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command) 110 ) 111 end 112 if bit.band(cmd.flags, flags.PREVIEW) == flags.PREVIEW then 113 assert( 114 cmd.preview_func ~= nil, 115 string.format('ex_cmds.lua:%s: Missing preview_func\n', cmd.command) 116 ) 117 end 118 local enumname = cmd.enum or ('CMD_' .. cmd.command) 119 local byte_cmd = cmd.command:sub(1, 1):byte() 120 if byte_a <= byte_cmd and byte_cmd <= byte_z then 121 table.insert(cmds, cmd.command) 122 end 123 local preview_func 124 if cmd.preview_func then 125 preview_func = string.format('&%s', cmd.preview_func) 126 else 127 preview_func = 'NULL' 128 end 129 enumfile:write(' ' .. enumname .. ',\n') 130 defsfile:write(string.format( 131 [[ 132 [%s] = { 133 .cmd_name = "%s", 134 .cmd_func = (ex_func_T)&%s, 135 .cmd_preview_func = %s, 136 .cmd_argt = %uL, 137 .cmd_addr_type = %s 138 }, 139 ]], 140 enumname, 141 cmd.command, 142 cmd.func, 143 preview_func, 144 cmd.flags, 145 cmd.addr_type 146 )) 147 end 148 for i = #cmds, 1, -1 do 149 local cmd = cmds[i] 150 -- First and second characters of the command 151 local c1 = cmd:sub(1, 1) 152 cmdidxs1[c1] = i - 1 153 if cmd:len() >= 2 then 154 local c2 = cmd:sub(2, 2) 155 local byte_c2 = string.byte(c2) 156 if byte_a <= byte_c2 and byte_c2 <= byte_z then 157 if not cmdidxs2[c1] then 158 cmdidxs2[c1] = {} 159 end 160 cmdidxs2[c1][c2] = i - 1 161 end 162 end 163 end 164 for i = byte_a, byte_z do 165 local c1 = string.char(i) 166 cmdidxs1_out = cmdidxs1_out .. ' /* ' .. c1 .. ' */ ' .. cmdidxs1[c1] .. ',\n' 167 cmdidxs2_out = cmdidxs2_out .. ' /* ' .. c1 .. ' */ {' 168 for j = byte_a, byte_z do 169 local c2 = string.char(j) 170 cmdidxs2_out = cmdidxs2_out 171 .. ((cmdidxs2[c1] and cmdidxs2[c1][c2]) and string.format( 172 '%3d', 173 cmdidxs2[c1][c2] - cmdidxs1[c1] 174 ) or ' 0') 175 .. ',' 176 end 177 cmdidxs2_out = cmdidxs2_out .. ' },\n' 178 end 179 enumfile:write([[ 180 CMD_SIZE, 181 CMD_USER = -1, 182 CMD_USER_BUF = -2 183 } cmdidx_T; 184 ]]) 185 defsfile:write(string.format( 186 [[ 187 }; 188 %s}; 189 %s}; 190 ]], 191 cmdidxs1_out, 192 cmdidxs2_out 193 ))