neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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()