gen_api_metadata.lua (2608B)
1 local mpack = vim.mpack 2 3 assert(#arg == 7) 4 local funcs_metadata_inputf = arg[1] -- exported functions metadata 5 local ui_metadata_inputf = arg[2] -- ui events metadata 6 local ui_options_inputf = arg[3] -- for ui options 7 local git_version_inputf = arg[4] -- git version header 8 local nvim_version_inputf = arg[5] -- nvim version 9 local dump_bin_array_inputf = arg[6] 10 local api_metadata_outputf = arg[7] 11 12 local version = loadfile(nvim_version_inputf)() 13 local git_version = io.open(git_version_inputf):read '*a' 14 local version_build = git_version:match('#define NVIM_VERSION_BUILD "([^"]+)"') or vim.NIL 15 16 local text = io.open(ui_options_inputf):read '*a' 17 local ui_options_text = text:match('ui_ext_names%[][^{]+{([^}]+)}') 18 local ui_options = { 'rgb' } 19 for x in ui_options_text:gmatch('"([a-z][a-z_]+)"') do 20 table.insert(ui_options, x) 21 end 22 23 local pieces = {} --- @type string[] 24 25 -- Naively using mpack.encode({foo=x, bar=y}) will make the build 26 -- "non-reproducible". Emit maps directly as FIXDICT(2) "foo" x "bar" y instead 27 local function fixdict(num) 28 if num > 15 then 29 error 'implement more dict codes' 30 end 31 pieces[#pieces + 1] = string.char(128 + num) 32 end 33 34 local function put(item, item2) 35 table.insert(pieces, mpack.encode(item)) 36 if item2 ~= nil then 37 table.insert(pieces, mpack.encode(item2)) 38 end 39 end 40 41 fixdict(6) 42 43 put('version') 44 fixdict(1 + #version) 45 for _, item in ipairs(version) do 46 -- NB: all items are mandatory. But any error will be less confusing 47 -- with placeholder vim.NIL (than invalid mpack data) 48 local val = item[2] == nil and vim.NIL or item[2] 49 put(item[1], val) 50 end 51 put('build', version_build) 52 53 put('functions') 54 table.insert(pieces, io.open(funcs_metadata_inputf, 'rb'):read('*all')) 55 put('ui_events') 56 table.insert(pieces, io.open(ui_metadata_inputf, 'rb'):read('*all')) 57 put('ui_options', ui_options) 58 59 put('error_types') 60 fixdict(2) 61 put('Exception', { id = 0 }) 62 put('Validation', { id = 1 }) 63 64 put('types') 65 local types = 66 { { 'Buffer', 'nvim_buf_' }, { 'Window', 'nvim_win_' }, { 'Tabpage', 'nvim_tabpage_' } } 67 fixdict(#types) 68 for i, item in ipairs(types) do 69 put(item[1]) 70 fixdict(2) 71 put('id', i - 1) 72 put('prefix', item[2]) 73 end 74 75 local packed = table.concat(pieces) 76 --- @type fun(api_metadata: file*, name: string, packed: string) 77 local dump_bin_array = loadfile(dump_bin_array_inputf)() 78 79 -- serialize the API metadata using msgpack and embed into the resulting 80 -- binary for easy querying by clients 81 local api_metadata_output = assert(io.open(api_metadata_outputf, 'wb')) 82 dump_bin_array(api_metadata_output, 'packed_api_metadata', packed) 83 api_metadata_output:close()