From 42333ea98dfcd2994ee128a3467dfe68205154cd Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 28 Jul 2023 14:48:41 +0100 Subject: feat(docs): generate builtin.txt (#24493) - eval.lua is now the source of truth. - Formatting is much more consistent. - Fixed Lua type generation for polymorphic functions (get(), etc). - Removed "Overview" section from builtin.txt - Can generate this if we really want it. - Moved functions from sign.txt and testing.txt into builtin.txt. - Removed the *timer* *timers* tags since libuv timers via vim.uv should be preferred. - Removed the temp-file-name tag from tempname() - Moved lueval() from lua.txt to builtin.txt. * Fix indent * fixup! * fixup! fixup! * fixup! better tag formatting * fixup: revert changes no longer needed * fixup! CI --------- Co-authored-by: zeertzjq --- scripts/gen_eval_files.lua | 274 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100755 scripts/gen_eval_files.lua (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua new file mode 100755 index 0000000000..7193346758 --- /dev/null +++ b/scripts/gen_eval_files.lua @@ -0,0 +1,274 @@ +#!/usr/bin/env -S nvim -l +-- Generator for src/nvim/eval.lua + +local funcs = require('src/nvim/eval').funcs + +local LUA_KEYWORDS = { + ['and'] = true, + ['end'] = true, + ['function'] = true, + ['or'] = true, + ['if'] = true, + ['while'] = true, + ['repeat'] = true, +} + +--- @param f string +--- @param params {[1]:string,[2]:string}[]|true +local function render_fun_sig(f, params) + local param_str --- @type string + if params == true then + param_str = '...' + else + param_str = table.concat( + vim.tbl_map( + --- @param v {[1]:string,[2]:string} + function(v) + return v[1] + end, + params + ), + ', ' + ) + end + + if LUA_KEYWORDS[f] then + return string.format("vim.fn['%s'] = function(%s) end", f, param_str) + else + return string.format('function vim.fn.%s(%s) end', f, param_str) + end +end + +--- Uniquify names +--- Fix any names that are lua keywords +--- @param params {[1]:string,[2]:string}[] +--- @return {[1]:string,[2]:string}[] +local function process_params(params) + local seen = {} --- @type table + local sfx = 1 + + for _, p in ipairs(params) do + if LUA_KEYWORDS[p[1]] then + p[1] = p[1] .. '_' + end + if seen[p[1]] then + p[1] = p[1] .. sfx + sfx = sfx + 1 + else + seen[p[1]] = true + end + end + + return params +end + +--- @param f string +--- @param fun vim.EvalFn +--- @param write fun(line: string) +local function render_vimfn(f, fun, write) + if fun.lua == false then + return + end + + local funname = fun.name or f + + local params = process_params(fun.params) + + if fun.signature then + write('') + if fun.deprecated then + write('--- @deprecated') + end + + local desc = fun.desc + + if desc then + desc = desc:gsub('\n%s*\n%s*$', '\n') + for _, l in ipairs(vim.split(desc, '\n', { plain = true })) do + l = l:gsub('^ ', ''):gsub('\t', ' '):gsub('@', '\\@') + write('--- ' .. l) + end + end + + local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0 + + for i, param in ipairs(params) do + local pname, ptype = param[1], param[2] + local optional = (pname ~= '...' and i > req_args) and '?' or '' + write(string.format('--- @param %s%s %s', pname, optional, ptype)) + end + + if fun.returns ~= false then + write('--- @return ' .. (fun.returns or 'any')) + end + + write(render_fun_sig(funname, params)) + + return + end + + print('no doc for', funname) +end + +--- @type table +local rendered_tags = {} + +--- @param f string +--- @param fun vim.EvalFn +--- @param write fun(line: string) +local function render_eval_doc(f, fun, write) + if fun.deprecated then + return + end + + if not fun.signature then + return + end + + local desc = fun.desc + + if not desc then + write(fun.signature) + return + end + + local name = fun.name or f + local tags = { '*' .. name .. '()*' } + if fun.tags then + for _, t in ipairs(fun.tags) do + tags[#tags + 1] = '*' .. t .. '*' + end + end + local tag = table.concat(tags, ' ') + + local siglen = #fun.signature + if rendered_tags[name] then + write(fun.signature) + else + if siglen + #tag > 80 then + write(string.rep('\t', 6) .. tag) + write(fun.signature) + else + local tt = math.max(1, (76 - siglen - #tag) / 8) + write(string.format('%s%s%s', fun.signature, string.rep('\t', tt), tag)) + end + end + rendered_tags[name] = true + + desc = vim.trim(desc) + local desc_l = vim.split(desc, '\n', { plain = true }) + for _, l in ipairs(desc_l) do + l = l:gsub('^ ', '') + if vim.startswith(l, '<') and not l:match('^<[A-Z][A-Z]') then + write('<\t\t' .. l:sub(2)) + else + write('\t\t' .. l) + end + end + + if #desc_l > 0 and not desc_l[#desc_l]:match('^', + '\t:let a = "aaaa\\nxxxx"', + '\t:echo matchstr(a, "..\\n..")', + '\taa', + '\txx', + '\t:echo matchstr(a, "a.x")', + '\ta', + '\tx', + '', + 'Don\'t forget that "^" will only match at the first character of the String and', + '"$" at the last character of the string. They don\'t match after or before a', + '"\\n".', + '', + ' vim:tw=78:ts=8:noet:ft=help:norl:', + }, + }, +} + +--- @param elem nvim.gen_eval_files.elem +local function render(elem) + local o = assert(io.open(elem.path, 'w')) + + --- @param l string + local function write(l) + local l1 = l:gsub('%s+$', '') + o:write(l1) + o:write('\n') + end + + for _, l in ipairs(elem.header or {}) do + write(l) + end + + --- @type string[] + local fnames = vim.tbl_keys(funcs) + table.sort(fnames) + + for _, f in ipairs(fnames) do + elem.render(f, funcs[f], write) + end + + for _, l in ipairs(elem.footer or {}) do + write(l) + end + + o:close() +end + +local function main() + for _, c in ipairs(CONFIG) do + render(c) + end +end + +main() -- cgit From 9b5f58185e1ff0597c7e95b7205d9ec11be1848c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 1 Aug 2023 09:57:52 +0100 Subject: docs(builtin): fix and annotate language blocks (#24506) --- scripts/gen_eval_files.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index 7193346758..ee8bbe48a3 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -217,14 +217,14 @@ local CONFIG = { 'same way. The difference is that a String is handled like it is one line.', 'When it contains a "\\n" character, this is not seen as a line break for the', 'pattern. It can be matched with a "\\n" in the pattern, or with ".". Example:', - '>', - '\t:let a = "aaaa\\nxxxx"', - '\t:echo matchstr(a, "..\\n..")', - '\taa', - '\txx', - '\t:echo matchstr(a, "a.x")', - '\ta', - '\tx', + '>vim', + '\tlet a = "aaaa\\nxxxx"', + '\techo matchstr(a, "..\\n..")', + '\t" aa', + '\t" xx', + '\techo matchstr(a, "a.x")', + '\t" a', + '\t" x', '', 'Don\'t forget that "^" will only match at the first character of the String and', '"$" at the last character of the string. They don\'t match after or before a', -- cgit From 20bfdbe83253cf5ec0a42bd75bd4ed7df945ab37 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 1 Aug 2023 11:12:00 +0100 Subject: docs(builtin): right align tags (#24522) --- scripts/gen_eval_files.lua | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index ee8bbe48a3..0b845fb246 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -113,6 +113,31 @@ end --- @type table local rendered_tags = {} +--- @param name string +--- @param fun vim.EvalFn +--- @param write fun(line: string) +local function render_sig_and_tag(name, fun, write) + local tags = { '*' .. name .. '()*' } + + if fun.tags then + for _, t in ipairs(fun.tags) do + tags[#tags + 1] = '*' .. t .. '*' + end + end + + local tag = table.concat(tags, ' ') + local siglen = #fun.signature + local conceal_offset = 2*(#tags - 1) + local tag_pad_len = math.max(1, 80 - #tag + conceal_offset) + + if siglen + #tag > 80 then + write(string.rep(' ', tag_pad_len) .. tag) + write(fun.signature) + else + write(string.format('%s%s%s', fun.signature, string.rep(' ', tag_pad_len - siglen), tag)) + end +end + --- @param f string --- @param fun vim.EvalFn --- @param write fun(line: string) @@ -133,27 +158,13 @@ local function render_eval_doc(f, fun, write) end local name = fun.name or f - local tags = { '*' .. name .. '()*' } - if fun.tags then - for _, t in ipairs(fun.tags) do - tags[#tags + 1] = '*' .. t .. '*' - end - end - local tag = table.concat(tags, ' ') - local siglen = #fun.signature if rendered_tags[name] then write(fun.signature) else - if siglen + #tag > 80 then - write(string.rep('\t', 6) .. tag) - write(fun.signature) - else - local tt = math.max(1, (76 - siglen - #tag) / 8) - write(string.format('%s%s%s', fun.signature, string.rep('\t', tt), tag)) - end + render_sig_and_tag(name, fun, write) + rendered_tags[name] = true end - rendered_tags[name] = true desc = vim.trim(desc) local desc_l = vim.split(desc, '\n', { plain = true }) -- cgit From 48d533272e57e91e4d14c93b26d4922957f40cd7 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 1 Aug 2023 14:20:44 +0100 Subject: feat(lua-types): types for vim.api.* (#24523) --- scripts/gen_eval_files.lua | 263 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 255 insertions(+), 8 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index 0b845fb246..7e470a3105 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -1,7 +1,35 @@ #!/usr/bin/env -S nvim -l -- Generator for src/nvim/eval.lua -local funcs = require('src/nvim/eval').funcs +--- @class vim.api.metadata +--- @field name string +--- @field parameters {[1]:string,[2]:string}[] +--- @field return_type string +--- @field deprecated_since integer +--- @field eval boolean +--- @field fast boolean +--- @field handler_id integer +--- @field impl_name string +--- @field lua boolean +--- @field method boolean +--- @field remote boolean +--- @field since integer + +local LUA_META_HEADER = { + '--- @meta', + '-- THIS FILE IS GENERATED', + '-- DO NOT EDIT', + "error('Cannot require a meta file')", +} + +local LUA_API_META_HEADER = { + '--- @meta', + '-- THIS FILE IS GENERATED', + '-- DO NOT EDIT', + "error('Cannot require a meta file')", + '', + 'vim.api = {}', +} local LUA_KEYWORDS = { ['and'] = true, @@ -13,6 +41,47 @@ local LUA_KEYWORDS = { ['repeat'] = true, } +local API_TYPES = { + Window = 'integer', + Tabpage = 'integer', + Buffer = 'integer', + Boolean = 'boolean', + Object = 'any', + Integer = 'integer', + String = 'string', + Array = 'any[]', + LuaRef = 'function', + Dictionary = 'table', + Float = 'number', + void = '', +} + +--- Convert an API type to Lua +--- @param t string +--- @return string +local function api_type(t) + if t:match('^ArrayOf%(([z-aA-Z]+), %d+%') then + print(t:match('^ArrayOf%(([z-aA-Z]+), %d+%')) + end + local as0 = t:match('^ArrayOf%((.*)%)') + if as0 then + local as = vim.split(as0, ', ', { plain = true }) + return api_type(as[1]) .. '[]' + end + + local d = t:match('^Dict%((.*)%)') + if d then + return 'vim.api.keyset.' .. d + end + + local d0 = t:match('^DictionaryOf%((.*)%)') + if d0 then + return 'table' + end + + return API_TYPES[t] or t +end + --- @param f string --- @param params {[1]:string,[2]:string}[]|true local function render_fun_sig(f, params) @@ -41,8 +110,8 @@ end --- Uniquify names --- Fix any names that are lua keywords ---- @param params {[1]:string,[2]:string}[] ---- @return {[1]:string,[2]:string}[] +--- @param params {[1]:string,[2]:string,[3]:string}[] +--- @return {[1]:string,[2]:string,[3]:string}[] local function process_params(params) local seen = {} --- @type table local sfx = 1 @@ -62,6 +131,170 @@ local function process_params(params) return params end +--- @class vim.gen_vim_doc_fun +--- @field signature string +--- @field doc string[] +--- @field parameters_doc table +--- @field return string[] +--- @field seealso string[] +--- @field annotations string[] + +--- @return table +local function get_api_funcs() + local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb')) + local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]] + local ret = {} --- @type table + + local doc_mpack_f = assert(io.open('runtime/doc/api.mpack', 'rb')) + local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table]] + + for _, fun in ipairs(metadata) do + local fdoc = doc_metadata[fun.name] + + local params = {} --- @type {[1]:string,[2]:string}[] + for _, p in ipairs(fun.parameters) do + local ptype, pname = p[1], p[2] + params[#params + 1] = { + pname, + api_type(ptype), + fdoc and fdoc.parameters_doc[pname] or nil, + } + end + + local r = { + signature = 'NA', + name = fun.name, + params = params, + returns = api_type(fun.return_type), + deprecated = fun.deprecated_since ~= nil, + } + + if fdoc then + if #fdoc.doc > 0 then + r.desc = table.concat(fdoc.doc, '\n') + end + r.return_desc = (fdoc['return'] or {})[1] + end + + ret[fun.name] = r + end + return ret +end + +--- Convert vimdoc references to markdown literals +--- Convert vimdoc codeblocks to markdown codeblocks +--- @param x string +--- @return string +local function norm_text(x) + return ( + x:gsub('|([^ ]+)|', '`%1`') + :gsub('>lua', '\n```lua') + :gsub('>vim', '\n```vim') + :gsub('\n<$', '\n```') + :gsub('\n<\n', '\n```\n') + ) +end + +--- @param _f string +--- @param fun vim.EvalFn +--- @param write fun(line: string) +local function render_api_fun(_f, fun, write) + if not vim.startswith(fun.name, 'nvim_') then + return + end + + write('') + + if vim.startswith(fun.name, 'nvim__') then + write('--- @private') + end + + if fun.deprecated then + write('--- @deprecated') + end + + local desc = fun.desc + if desc then + for _, l in ipairs(vim.split(norm_text(desc), '\n', { plain = true })) do + write('--- ' .. l) + end + write('---') + end + + local param_names = {} --- @type string[] + local params = process_params(fun.params) + for _, p in ipairs(params) do + param_names[#param_names + 1] = p[1] + local pdesc = p[3] + if pdesc then + local pdesc_a = vim.split(norm_text(pdesc), '\n', { plain = true }) + write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1]) + for i = 2, #pdesc_a do + if not pdesc_a[i] then + break + end + write('--- ' .. pdesc_a[i]) + end + else + write('--- @param ' .. p[1] .. ' ' .. p[2]) + end + end + if fun.returns ~= '' then + if fun.returns_desc then + write('--- @return ' .. fun.returns .. ' : ' .. fun.returns_desc) + else + write('--- @return ' .. fun.returns) + end + end + local param_str = table.concat(param_names, ', ') + + write(string.format('function vim.api.%s(%s) end', fun.name, param_str)) +end + +--- @return table +local function get_api_keysets() + local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb')) + + --- @diagnostic disable-next-line:no-unknown + local metadata = assert(vim.mpack.decode(mpack_f:read('*all'))) + + local ret = {} --- @type table + + --- @type {[1]: string, [2]: {[1]: string, [2]: string}[] }[] + local keysets = metadata.keysets + + for _, keyset in ipairs(keysets) do + local kname = keyset[1] + local kdef = keyset[2] + for _, field in ipairs(kdef) do + field[2] = api_type(field[2]) + end + ret[kname] = { + signature = 'NA', + name = kname, + params = kdef, + } + end + + return ret +end + +--- @param _f string +--- @param fun vim.EvalFn +--- @param write fun(line: string) +local function render_api_keyset(_f, fun, write) + write('') + write('--- @class vim.api.keyset.' .. fun.name) + for _, p in ipairs(fun.params) do + write('--- @field ' .. p[1] .. ' ' .. p[2]) + end +end + +--- @return table +local function get_eval_funcs() + return require('src/nvim/eval').funcs +end + --- @param f string --- @param fun vim.EvalFn --- @param write fun(line: string) @@ -83,6 +316,7 @@ local function render_vimfn(f, fun, write) local desc = fun.desc if desc then + --- @type string desc = desc:gsub('\n%s*\n%s*$', '\n') for _, l in ipairs(vim.split(desc, '\n', { plain = true })) do l = l:gsub('^ ', ''):gsub('\t', ' '):gsub('@', '\\@') @@ -184,6 +418,7 @@ end --- @class nvim.gen_eval_files.elem --- @field path string +--- @field funcs fun(): table --- @field render fun(f:string,fun:vim.EvalFn,write:fun(line:string)) --- @field header? string[] --- @field footer? string[] @@ -192,15 +427,25 @@ end local CONFIG = { { path = 'runtime/lua/vim/_meta/vimfn.lua', + header = LUA_META_HEADER, + funcs = get_eval_funcs, render = render_vimfn, - header = { - '--- @meta', - '-- THIS FILE IS GENERATED', - '-- DO NOT EDIT', - }, + }, + { + path = 'runtime/lua/vim/_meta/api.lua', + header = LUA_API_META_HEADER, + funcs = get_api_funcs, + render = render_api_fun, + }, + { + path = 'runtime/lua/vim/_meta/api_keysets.lua', + header = LUA_META_HEADER, + funcs = get_api_keysets, + render = render_api_keyset, }, { path = 'runtime/doc/builtin.txt', + funcs = get_eval_funcs, render = render_eval_doc, header = { '*builtin.txt* Nvim', @@ -261,6 +506,8 @@ local function render(elem) write(l) end + local funcs = elem.funcs() + --- @type string[] local fnames = vim.tbl_keys(funcs) table.sort(fnames) -- cgit From d086bc1e8590a92a70c414bd60e1e988bbdd3c0a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 1 Aug 2023 16:17:26 -0700 Subject: docs: drop "Can also be used as a method" #24508 Now that we "own" builtin.txt, we cant remove the repetitive mention of Vimscript's UFCS syntax. It's noisy to mention this for each function, and it's also not a Vimscript feature that should be encouraged. Also change the builtin.txt heading to "NVIM REFERENCE MANUAL", which indicates when a help file is Nvim-owned. --- scripts/gen_eval_files.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index 7e470a3105..c3123fd47c 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -451,7 +451,7 @@ local CONFIG = { '*builtin.txt* Nvim', '', '', - '\t\t VIM REFERENCE MANUAL\t by Bram Moolenaar', + '\t\t NVIM REFERENCE MANUAL', '', '', 'Builtin functions\t\t*vimscript-functions* *builtin-functions*', -- cgit From 6fa17da39b270bf230764859a9537124b18d3ed5 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 4 Aug 2023 21:26:53 +0100 Subject: docs(options): take ownership of options.txt (#24528) * docs(options): take ownership of options.txt - `src/nvim/options.lua` is now the source of truth - generate runtime/lua/vim/_meta/options.lua * fixup! zeer comments * fixup! zeer comments (2) * fixup! re-enable luacheck * fixup! regen --- scripts/gen_eval_files.lua | 300 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 276 insertions(+), 24 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index c3123fd47c..640d2afb4f 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -31,6 +31,21 @@ local LUA_API_META_HEADER = { 'vim.api = {}', } +local LUA_OPTION_META_HEADER = { + '--- @meta', + '-- THIS FILE IS GENERATED', + '-- DO NOT EDIT', + "error('Cannot require a meta file')", + '', + '---@class vim.bo', + '---@field [integer] vim.bo', + 'vim.bo = vim.bo', + '', + '---@class vim.wo', + '---@field [integer] vim.wo', + 'vim.wo = vim.wo', +} + local LUA_KEYWORDS = { ['and'] = true, ['end'] = true, @@ -41,6 +56,12 @@ local LUA_KEYWORDS = { ['repeat'] = true, } +local OPTION_TYPES = { + bool = 'boolean', + number = 'integer', + string = 'string', +} + local API_TYPES = { Window = 'integer', Tabpage = 'integer', @@ -56,16 +77,20 @@ local API_TYPES = { void = '', } +--- @param x string +--- @param sep? string +--- @return string[] +local function split(x, sep) + return vim.split(x, sep or '\n', { plain = true }) +end + --- Convert an API type to Lua --- @param t string --- @return string local function api_type(t) - if t:match('^ArrayOf%(([z-aA-Z]+), %d+%') then - print(t:match('^ArrayOf%(([z-aA-Z]+), %d+%')) - end local as0 = t:match('^ArrayOf%((.*)%)') if as0 then - local as = vim.split(as0, ', ', { plain = true }) + local as = split(as0, ', ') return api_type(as[1]) .. '[]' end @@ -84,6 +109,7 @@ end --- @param f string --- @param params {[1]:string,[2]:string}[]|true +--- @return string local function render_fun_sig(f, params) local param_str --- @type string if params == true then @@ -92,6 +118,7 @@ local function render_fun_sig(f, params) param_str = table.concat( vim.tbl_map( --- @param v {[1]:string,[2]:string} + --- @return string function(v) return v[1] end, @@ -140,7 +167,7 @@ end --- @field annotations string[] --- @return table -local function get_api_funcs() +local function get_api_meta() local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb')) local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]] local ret = {} --- @type table @@ -192,13 +219,15 @@ local function norm_text(x) :gsub('>vim', '\n```vim') :gsub('\n<$', '\n```') :gsub('\n<\n', '\n```\n') + :gsub('%s+>\n', '\n```\n') + :gsub('\n<%s+\n?', '\n```\n') ) end --- @param _f string --- @param fun vim.EvalFn --- @param write fun(line: string) -local function render_api_fun(_f, fun, write) +local function render_api_meta(_f, fun, write) if not vim.startswith(fun.name, 'nvim_') then return end @@ -215,7 +244,7 @@ local function render_api_fun(_f, fun, write) local desc = fun.desc if desc then - for _, l in ipairs(vim.split(norm_text(desc), '\n', { plain = true })) do + for _, l in ipairs(split(norm_text(desc))) do write('--- ' .. l) end write('---') @@ -227,7 +256,7 @@ local function render_api_fun(_f, fun, write) param_names[#param_names + 1] = p[1] local pdesc = p[3] if pdesc then - local pdesc_a = vim.split(norm_text(pdesc), '\n', { plain = true }) + local pdesc_a = split(norm_text(pdesc)) write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1]) for i = 2, #pdesc_a do if not pdesc_a[i] then @@ -252,7 +281,7 @@ local function render_api_fun(_f, fun, write) end --- @return table -local function get_api_keysets() +local function get_api_keysets_meta() local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb')) --- @diagnostic disable-next-line:no-unknown @@ -282,7 +311,7 @@ end --- @param _f string --- @param fun vim.EvalFn --- @param write fun(line: string) -local function render_api_keyset(_f, fun, write) +local function render_api_keyset_meta(_f, fun, write) write('') write('--- @class vim.api.keyset.' .. fun.name) for _, p in ipairs(fun.params) do @@ -291,14 +320,14 @@ local function render_api_keyset(_f, fun, write) end --- @return table -local function get_eval_funcs() +local function get_eval_meta() return require('src/nvim/eval').funcs end --- @param f string --- @param fun vim.EvalFn --- @param write fun(line: string) -local function render_vimfn(f, fun, write) +local function render_eval_meta(f, fun, write) if fun.lua == false then return end @@ -318,7 +347,7 @@ local function render_vimfn(f, fun, write) if desc then --- @type string desc = desc:gsub('\n%s*\n%s*$', '\n') - for _, l in ipairs(vim.split(desc, '\n', { plain = true })) do + for _, l in ipairs(split(desc)) do l = l:gsub('^ ', ''):gsub('\t', ' '):gsub('@', '\\@') write('--- ' .. l) end @@ -401,10 +430,10 @@ local function render_eval_doc(f, fun, write) end desc = vim.trim(desc) - local desc_l = vim.split(desc, '\n', { plain = true }) + local desc_l = split(desc) for _, l in ipairs(desc_l) do l = l:gsub('^ ', '') - if vim.startswith(l, '<') and not l:match('^<[A-Z][A-Z]') then + if vim.startswith(l, '<') and not l:match('^<[^ \t]+>') then write('<\t\t' .. l:sub(2)) else write('\t\t' .. l) @@ -416,10 +445,201 @@ local function render_eval_doc(f, fun, write) end end +--- @param d vim.option_defaults +--- @param vimdoc? boolean +--- @return string +local function render_option_default(d, vimdoc) + local dt --- @type integer|boolean|string|fun(): string + if d.if_false ~= nil then + dt = d.if_false + else + dt = d.if_true + end + + if vimdoc then + if d.doc then + return d.doc + end + if type(dt) == 'boolean' then + return dt and 'on' or 'off' + end + end + + if dt == "" or dt == nil or type(dt) == 'function' then + dt = d.meta + end + + local v --- @type string + if not vimdoc then + v = vim.inspect(dt) --[[@as string]] + else + v = type(dt) == 'string' and '"'..dt..'"' or tostring(dt) + end + + --- @type table + local envvars = { + TMPDIR = false, + VIMRUNTIME = false, + XDG_CONFIG_HOME = vim.env.HOME..'/.local/config', + XDG_DATA_HOME = vim.env.HOME..'/.local/share', + XDG_STATE_HOME = vim.env.HOME..'/.local/state', + } + + for name, default in pairs(envvars) do + local value = vim.env[name] or default + if value then + v = v:gsub(vim.pesc(value), '$'..name) + end + end + + return v +end + +--- @param _f string +--- @param opt vim.option_meta +--- @param write fun(line: string) +local function render_option_meta(_f, opt, write) + write('') + for _, l in ipairs(split(norm_text(opt.desc))) do + write('--- '..l) + end + + write('--- @type '..OPTION_TYPES[opt.type]) + write('vim.o.'..opt.full_name..' = '..render_option_default(opt.defaults)) + if opt.abbreviation then + write('vim.o.'..opt.abbreviation..' = vim.o.'..opt.full_name) + end + + for _, s in pairs { + {'wo', 'window'}, + {'bo', 'buffer'}, + {'go', 'global'}, + } do + local id, scope = s[1], s[2] + if vim.list_contains(opt.scope, scope) or (id == 'go' and #opt.scope > 1) then + local pfx = 'vim.'..id..'.' + write(pfx..opt.full_name..' = vim.o.'..opt.full_name) + if opt.abbreviation then + write(pfx..opt.abbreviation..' = '..pfx..opt.full_name) + end + end + end +end + +--- @param s string[] +--- @return string +local function scope_to_doc(s) + local m = { + global = 'global', + buffer = 'local to buffer', + window = 'local to window', + tab = 'local to tab page' + } + + if #s == 1 then + return m[s[1]] + end + assert(s[1] == 'global') + return 'global or '..m[s[2]]..' |global-local|' +end + +--- @return table +local function get_option_meta() + local opts = require('src/nvim/options').options + local optinfo = vim.api.nvim_get_all_options_info() + local ret = {} --- @type table + for _, o in ipairs(opts) do + if o.desc then + if o.full_name == 'cmdheight' then + table.insert(o.scope, 'tab') + end + local r = vim.deepcopy(o) --[[@as vim.option_meta]] + r.desc = o.desc:gsub('^ ', ''):gsub('\n ', '\n') + r.defaults = r.defaults or {} + if r.defaults.meta == nil then + r.defaults.meta = optinfo[o.full_name].default + end + ret[o.full_name] = r + end + end + return ret +end + +--- @param opt vim.option_meta +--- @return string[] +local function build_option_tags(opt) + --- @type string[] + local tags = { opt.full_name } + + tags[#tags+1] = opt.abbreviation + if opt.type == 'bool' then + for i = 1, #tags do + tags[#tags+1] = 'no'..tags[i] + end + end + + for i, t in ipairs(tags) do + tags[i] = "'"..t.."'" + end + + for _, t in ipairs(opt.tags or {}) do + tags[#tags+1] = t + end + + for i, t in ipairs(tags) do + tags[i] = "*"..t.."*" + end + + return tags +end + +--- @param _f string +--- @param opt vim.option_meta +--- @param write fun(line: string) +local function render_option_doc(_f, opt, write) + local tags = build_option_tags(opt) + local tag_str = table.concat(tags, ' ') + local conceal_offset = 2*(#tags - 1) + local tag_pad = string.rep('\t', math.ceil((64 - #tag_str + conceal_offset) / 8)) + -- local pad = string.rep(' ', 80 - #tag_str + conceal_offset) + write(tag_pad..tag_str) + + local name_str --- @type string + if opt.abbreviation then + name_str = string.format("'%s' '%s'", opt.full_name, opt.abbreviation) + else + name_str = string.format("'%s'", opt.full_name) + end + + local otype = opt.type == 'bool' and 'boolean' or opt.type + if opt.defaults.doc or opt.defaults.if_true ~= nil or opt.defaults.meta ~= nil then + local v = render_option_default(opt.defaults, true) + local pad = string.rep('\t', math.max(1, math.ceil((24 - #name_str) / 8))) + if opt.defaults.doc then + local deflen = #string.format('%s%s%s (', name_str, pad, otype) + --- @type string + v = v:gsub('\n', '\n'..string.rep(' ', deflen - 2)) + end + write(string.format('%s%s%s\t(default %s)', name_str, pad, otype, v)) + else + write(string.format('%s\t%s', name_str, otype)) + end + + write('\t\t\t'..scope_to_doc(opt.scope)) + for _, l in ipairs(split(opt.desc)) do + if l == '<' or l:match('^<%s') then + write(l) + else + write('\t'..l:gsub('\\<', '<')) + end + end +end + --- @class nvim.gen_eval_files.elem --- @field path string ---- @field funcs fun(): table ---- @field render fun(f:string,fun:vim.EvalFn,write:fun(line:string)) +--- @field from? string Skip lines in path until this pattern is reached. +--- @field funcs fun(): table +--- @field render fun(f:string,obj:table,write:fun(line:string)) --- @field header? string[] --- @field footer? string[] @@ -428,24 +648,24 @@ local CONFIG = { { path = 'runtime/lua/vim/_meta/vimfn.lua', header = LUA_META_HEADER, - funcs = get_eval_funcs, - render = render_vimfn, + funcs = get_eval_meta, + render = render_eval_meta, }, { path = 'runtime/lua/vim/_meta/api.lua', header = LUA_API_META_HEADER, - funcs = get_api_funcs, - render = render_api_fun, + funcs = get_api_meta, + render = render_api_meta, }, { path = 'runtime/lua/vim/_meta/api_keysets.lua', header = LUA_META_HEADER, - funcs = get_api_keysets, - render = render_api_keyset, + funcs = get_api_keysets_meta, + render = render_api_keyset_meta, }, { path = 'runtime/doc/builtin.txt', - funcs = get_eval_funcs, + funcs = get_eval_meta, render = render_eval_doc, header = { '*builtin.txt* Nvim', @@ -489,10 +709,38 @@ local CONFIG = { ' vim:tw=78:ts=8:noet:ft=help:norl:', }, }, + { + path = 'runtime/lua/vim/_meta/options.lua', + header = LUA_OPTION_META_HEADER, + funcs = get_option_meta, + render = render_option_meta, + }, + { + path = 'runtime/doc/options.txt', + header = { '' }, + from = 'A jump table for the options with a short description can be found at |Q_op|.', + footer = { + ' vim:tw=78:ts=8:noet:ft=help:norl:' + }, + funcs = get_option_meta, + render = render_option_doc, + } } --- @param elem nvim.gen_eval_files.elem local function render(elem) + print('Rendering '..elem.path) + local from_lines = {} --- @type string[] + local from = elem.from + if from then + for line in io.lines(elem.path) do + from_lines[#from_lines+1] = line + if line:match(from) then + break + end + end + end + local o = assert(io.open(elem.path, 'w')) --- @param l string @@ -502,6 +750,10 @@ local function render(elem) o:write('\n') end + for _, l in ipairs(from_lines) do + write(l) + end + for _, l in ipairs(elem.header or {}) do write(l) end -- cgit From 7bc93e0e2f246dd78026a3472d929a0fe450f70d Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 1 Aug 2023 14:01:19 +0200 Subject: refactor(api): use typed keysets Initially this is just for geting rid of boilerplate, but eventually the types could get exposed as metadata --- scripts/gen_eval_files.lua | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index c3123fd47c..eea76958ae 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -260,19 +260,18 @@ local function get_api_keysets() local ret = {} --- @type table - --- @type {[1]: string, [2]: {[1]: string, [2]: string}[] }[] + --- @type {name: string, keys: string[], types: table}[] local keysets = metadata.keysets - for _, keyset in ipairs(keysets) do - local kname = keyset[1] - local kdef = keyset[2] - for _, field in ipairs(kdef) do - field[2] = api_type(field[2]) + for _, k in ipairs(keysets) do + local params = {} + for _, key in ipairs(k.keys) do + table.insert(params, {key, api_type(k.types[key] or 'any')}) end - ret[kname] = { + ret[k.name] = { signature = 'NA', - name = kname, - params = kdef, + name = k.name, + params = params, } end -- cgit From 628763fbd82d0fab292b7e92b553c6b1ed53e556 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 8 Aug 2023 10:40:43 +0200 Subject: docs(lua): the keyset nilocalypse This is needed to give recent LuaLS the right idea about optional fields. --- scripts/gen_eval_files.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index d29691dfe8..9bc9e99c46 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -295,7 +295,7 @@ local function get_api_keysets_meta() for _, k in ipairs(keysets) do local params = {} for _, key in ipairs(k.keys) do - table.insert(params, {key, api_type(k.types[key] or 'any')}) + table.insert(params, {key..'?', api_type(k.types[key] or 'any')}) end ret[k.name] = { signature = 'NA', -- cgit From 0ba27bb51d3297aec43e78050cc3adcf6879db22 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 23 Aug 2023 16:32:15 +0800 Subject: vim-patch:9.0.1710: scrolloff options work slightly different Problem: sidescrolloff and scrolloff options work slightly different than other global-local options Solution: Make it behave consistent for all global-local options It was noticed, that sidescrolloff and scrolloff options behave differently in comparison to other global-local window options like 'listchars' So make those two behave like other global-local options. Also add some extra documentation for a few special local-window options. Add a few tests to make sure all global-local window options behave similar closes: vim/vim#12956 closes: vim/vim#12643 https://github.com/vim/vim/commit/4a8eb6e7a9df10f79bf95301ced012f0d6a13088 Co-authored-by: Christian Brabandt --- scripts/gen_eval_files.lua | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index 9bc9e99c46..2990eef069 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -542,6 +542,36 @@ local function scope_to_doc(s) return 'global or '..m[s[2]]..' |global-local|' end +-- @param o vim.option_meta +-- @return string +local function scope_more_doc(o) + if + vim.list_contains({ + 'previewwindow', + 'scroll', + 'winfixheight', + 'winfixwidth', + }, o.full_name) + then + return ' |special-local-window-option|' + end + + if + vim.list_contains({ + 'bufhidden', + 'buftype', + 'filetype', + 'modified', + 'readonly', + 'syntax', + }, o.full_name) + then + return ' |special-local-buffer-option|' + end + + return '' +end + --- @return table local function get_option_meta() local opts = require('src/nvim/options').options @@ -624,7 +654,7 @@ local function render_option_doc(_f, opt, write) write(string.format('%s\t%s', name_str, otype)) end - write('\t\t\t'..scope_to_doc(opt.scope)) + write('\t\t\t'..scope_to_doc(opt.scope)..scope_more_doc(opt)) for _, l in ipairs(split(opt.desc)) do if l == '<' or l:match('^<%s') then write(l) -- cgit From 2234b84a1b85832667ad4a23fd5dee0bd1c92b72 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 17 Aug 2023 11:14:58 +0100 Subject: docs(generators): bake into cmake --- scripts/gen_eval_files.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index 2990eef069..e41054ed65 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -1,5 +1,8 @@ #!/usr/bin/env -S nvim -l --- Generator for src/nvim/eval.lua +-- Generator for various vimdoc and Lua type files + +local DEP_API_METADATA = 'build/api_metadata.mpack' +local DEP_API_DOC = 'runtime/doc/api.mpack' --- @class vim.api.metadata --- @field name string @@ -168,11 +171,11 @@ end --- @return table local function get_api_meta() - local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb')) + local mpack_f = assert(io.open(DEP_API_METADATA, 'rb')) local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]] local ret = {} --- @type table - local doc_mpack_f = assert(io.open('runtime/doc/api.mpack', 'rb')) + local doc_mpack_f = assert(io.open(DEP_API_DOC, 'rb')) local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table]] for _, fun in ipairs(metadata) do @@ -282,7 +285,7 @@ end --- @return table local function get_api_keysets_meta() - local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb')) + local mpack_f = assert(io.open(DEP_API_METADATA, 'rb')) --- @diagnostic disable-next-line:no-unknown local metadata = assert(vim.mpack.decode(mpack_f:read('*all'))) -- cgit From daf7abbc4238dc269e22dd431bc4b1627ef9b6a1 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Thu, 24 Aug 2023 13:29:40 +0100 Subject: docs(builtin): small fixes (#24861) Also make gen_eval_files.lua render vimdoc helpExamples properly if the line begins with the `>` marker. --- scripts/gen_eval_files.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index e41054ed65..f8d69ce313 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -437,6 +437,8 @@ local function render_eval_doc(f, fun, write) l = l:gsub('^ ', '') if vim.startswith(l, '<') and not l:match('^<[^ \t]+>') then write('<\t\t' .. l:sub(2)) + elseif l:match('^>[a-z0-9]*$') then + write(l) else write('\t\t' .. l) end -- cgit From 4b6023be7c2b132e7e6994adc73a7b79fbf40946 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 12 Sep 2023 07:37:05 +0800 Subject: vim-patch:596ad66d1ddb (#25102) runtime(doc): documentation updates This is a collection of various improvements to the help pages closes vim/vim#12790 https://github.com/vim/vim/commit/596ad66d1ddb742ef349e98eb06b8e4052f68f51 Co-authored-by: Christian Brabandt Co-authored-by: Houl Co-authored-by: Doug Kearns Co-authored-by: Adri Verhoef --- scripts/gen_eval_files.lua | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'scripts/gen_eval_files.lua') diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index f8d69ce313..5d726315bd 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -550,28 +550,21 @@ end -- @param o vim.option_meta -- @return string local function scope_more_doc(o) - if - vim.list_contains({ - 'previewwindow', - 'scroll', - 'winfixheight', - 'winfixwidth', - }, o.full_name) - then - return ' |special-local-window-option|' - end - if vim.list_contains({ 'bufhidden', 'buftype', 'filetype', 'modified', + 'previewwindow', 'readonly', + 'scroll', 'syntax', + 'winfixheight', + 'winfixwidth', }, o.full_name) then - return ' |special-local-buffer-option|' + return ' |local-noglobal|' end return '' -- cgit From 2e92065686f62851318150a315591c30b8306a4b Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:23:01 -0500 Subject: docs: replace
 with ``` (#25136)

---
 scripts/gen_eval_files.lua | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

(limited to 'scripts/gen_eval_files.lua')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 5d726315bd..1afe3d5f46 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -213,17 +213,20 @@ end
 
 --- Convert vimdoc references to markdown literals
 --- Convert vimdoc codeblocks to markdown codeblocks
+---
+--- Ensure code blocks have one empty line before the start fence and after the closing fence.
+---
 --- @param x string
 --- @return string
 local function norm_text(x)
   return (
     x:gsub('|([^ ]+)|', '`%1`')
-      :gsub('>lua', '\n```lua')
-      :gsub('>vim', '\n```vim')
-      :gsub('\n<$', '\n```')
-      :gsub('\n<\n', '\n```\n')
-      :gsub('%s+>\n', '\n```\n')
-      :gsub('\n<%s+\n?', '\n```\n')
+      :gsub('\n*>lua', '\n\n```lua')
+      :gsub('\n*>vim', '\n\n```vim')
+      :gsub('\n+<$', '\n```')
+      :gsub('\n+<\n+', '\n```\n\n')
+      :gsub('%s+>\n+', '\n```\n')
+      :gsub('\n+<%s+\n?', '\n```\n')
   )
 end
 
-- 
cgit 


From c80a3976cb34c2b3c7f6f01e9ad2db41a4f67796 Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Mon, 9 Oct 2023 15:34:48 -0700
Subject: docs: miscellaneous doc and type fixes (#25554)

---
 scripts/gen_eval_files.lua | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'scripts/gen_eval_files.lua')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 1afe3d5f46..bf243e96fd 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -19,14 +19,14 @@ local DEP_API_DOC  = 'runtime/doc/api.mpack'
 --- @field since integer
 
 local LUA_META_HEADER = {
-  '--- @meta',
+  '--- @meta _',
   '-- THIS FILE IS GENERATED',
   '-- DO NOT EDIT',
   "error('Cannot require a meta file')",
 }
 
 local LUA_API_META_HEADER = {
-  '--- @meta',
+  '--- @meta _',
   '-- THIS FILE IS GENERATED',
   '-- DO NOT EDIT',
   "error('Cannot require a meta file')",
@@ -35,7 +35,7 @@ local LUA_API_META_HEADER = {
 }
 
 local LUA_OPTION_META_HEADER = {
-  '--- @meta',
+  '--- @meta _',
   '-- THIS FILE IS GENERATED',
   '-- DO NOT EDIT',
   "error('Cannot require a meta file')",
-- 
cgit 


From e0d97d264f83d45472e6cdd1051893db1083eefb Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 2 Nov 2023 11:12:38 -0700
Subject: build: use built nvim artifact to generate eval files (#25875)

In cases where the generated files depend on changes to Nvim itself,
generating the files with an older version of Nvim will fail because
those changes are not present in the older version.

For example, if a new option is added then the generator script should
be run with the version of Nvim that contains the new option, or else
the generation will fail.

Co-authored-by: dundargoc 
---
 scripts/gen_eval_files.lua | 1 -
 1 file changed, 1 deletion(-)

(limited to 'scripts/gen_eval_files.lua')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index bf243e96fd..714358e488 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -1,4 +1,3 @@
-#!/usr/bin/env -S nvim -l
 -- Generator for various vimdoc and Lua type files
 
 local DEP_API_METADATA = 'build/api_metadata.mpack'
-- 
cgit 


From 570367ac83cdceeee7d43dadcff7652bd5cc93c5 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Tue, 28 Nov 2023 13:52:17 +0800
Subject: docs(lua): don't include remote-only API functions (#26266)

---
 scripts/gen_eval_files.lua | 50 ++++++++++++++++++++++++----------------------
 1 file changed, 26 insertions(+), 24 deletions(-)

(limited to 'scripts/gen_eval_files.lua')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 714358e488..e331dd996e 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -178,34 +178,36 @@ local function get_api_meta()
   local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table]]
 
   for _, fun in ipairs(metadata) do
-    local fdoc = doc_metadata[fun.name]
-
-    local params = {} --- @type {[1]:string,[2]:string}[]
-    for _, p in ipairs(fun.parameters) do
-      local ptype, pname = p[1], p[2]
-      params[#params + 1] = {
-        pname,
-        api_type(ptype),
-        fdoc and fdoc.parameters_doc[pname] or nil,
-      }
-    end
+    if fun.lua then
+      local fdoc = doc_metadata[fun.name]
+
+      local params = {} --- @type {[1]:string,[2]:string}[]
+      for _, p in ipairs(fun.parameters) do
+        local ptype, pname = p[1], p[2]
+        params[#params + 1] = {
+          pname,
+          api_type(ptype),
+          fdoc and fdoc.parameters_doc[pname] or nil,
+        }
+      end
 
-    local r = {
-      signature = 'NA',
-      name = fun.name,
-      params = params,
-      returns = api_type(fun.return_type),
-      deprecated = fun.deprecated_since ~= nil,
-    }
+      local r = {
+        signature = 'NA',
+        name = fun.name,
+        params = params,
+        returns = api_type(fun.return_type),
+        deprecated = fun.deprecated_since ~= nil,
+      }
 
-    if fdoc then
-      if #fdoc.doc > 0 then
-        r.desc = table.concat(fdoc.doc, '\n')
+      if fdoc then
+        if #fdoc.doc > 0 then
+          r.desc = table.concat(fdoc.doc, '\n')
+        end
+        r.return_desc = (fdoc['return'] or {})[1]
       end
-      r.return_desc = (fdoc['return'] or {})[1]
-    end
 
-    ret[fun.name] = r
+      ret[fun.name] = r
+    end
   end
   return ret
 end
-- 
cgit