diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/bump_deps.lua | 476 | ||||
-rwxr-xr-x | scripts/gen_eval_files.lua | 101 | ||||
-rw-r--r-- | scripts/gen_help_html.lua | 7 | ||||
-rwxr-xr-x | scripts/gen_vimdoc.lua | 34 | ||||
-rwxr-xr-x | scripts/genappimage.sh | 33 | ||||
-rw-r--r-- | scripts/luacats_grammar.lua | 4 | ||||
-rw-r--r-- | scripts/luacats_parser.lua | 25 | ||||
-rwxr-xr-x | scripts/vimpatch.lua | 2 |
8 files changed, 254 insertions, 428 deletions
diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua index ad71da5150..a44e4a2d5e 100755 --- a/scripts/bump_deps.lua +++ b/scripts/bump_deps.lua @@ -3,44 +3,50 @@ -- Usage: -- ./scripts/bump_deps.lua -h -local M = {} +assert(vim.fn.executable('gh') == 1) +assert(vim.fn.executable('sed') == 1) -local _trace = false local required_branch_prefix = 'bump-' local commit_prefix = 'build(deps): ' --- Print message -local function p(s) - vim.cmd('set verbose=1') - vim.api.nvim_echo({ { s, '' } }, false, {}) - vim.cmd('set verbose=0') -end - -local function die() - p('') +local repos = { + 'luajit/luajit', + 'libuv/libuv', + 'luvit/luv', + 'neovim/unibilium', + 'juliastrings/utf8proc', + 'tree-sitter/tree-sitter', + 'tree-sitter/tree-sitter-c', + 'tree-sitter-grammars/tree-sitter-lua', + 'tree-sitter-grammars/tree-sitter-vim', + 'neovim/tree-sitter-vimdoc', + 'tree-sitter-grammars/tree-sitter-query', + 'tree-sitter-grammars/tree-sitter-markdown', + 'bytecodealliance/wasmtime', + 'uncrustify/uncrustify', +} + +local dependency_table = {} --- @type table<string, string> +for _, repo in pairs(repos) do + dependency_table[vim.fs.basename(repo)] = repo +end + +local function die(msg) + print(msg) vim.cmd('cquit 1') end -- Executes and returns the output of `cmd`, or nil on failure. -- if die_on_fail is true, process dies with die_msg on failure --- --- Prints `cmd` if `trace` is enabled. local function _run(cmd, die_on_fail, die_msg) - if _trace then - p('run: ' .. vim.inspect(cmd)) - end - local rv = vim.trim(vim.fn.system(cmd)) or '' - if vim.v.shell_error ~= 0 then + local rv = vim.system(cmd):wait() + if rv.code ~= 0 then if die_on_fail then - if _trace then - p(rv) - end - p(die_msg) - die() + die(die_msg) end return nil end - return rv + return vim.trim(rv.stdout) end -- Run a command, return nil on failure @@ -53,108 +59,20 @@ local function run_die(cmd, err_msg) return _run(cmd, true, err_msg) end -local function require_executable(cmd) - local cmd_path = run_die({ 'sh', '-c', 'command -v ' .. cmd }, cmd .. ' not found!') - run_die({ 'test', '-x', cmd_path }, cmd .. ' is not executable') -end - -local function rm_file_if_present(path_to_file) - run({ 'rm', '-f', path_to_file }) -end - -local nvim_src_dir = vim.fn.getcwd() +local nvim_src_dir = run({ 'git', 'rev-parse', '--show-toplevel' }) local deps_file = nvim_src_dir .. '/' .. 'cmake.deps/deps.txt' -local temp_dir = nvim_src_dir .. '/tmp' -run({ 'mkdir', '-p', temp_dir }) - -local function get_dependency(dependency_name) - local dependency_table = { - ['luajit'] = { - repo = 'LuaJIT/LuaJIT', - symbol = 'LUAJIT', - }, - ['libuv'] = { - repo = 'libuv/libuv', - symbol = 'LIBUV', - }, - ['luv'] = { - repo = 'luvit/luv', - symbol = 'LUV', - }, - ['unibilium'] = { - repo = 'neovim/unibilium', - symbol = 'UNIBILIUM', - }, - ['utf8proc'] = { - repo = 'JuliaStrings/utf8proc', - symbol = 'UTF8PROC', - }, - ['tree-sitter'] = { - repo = 'tree-sitter/tree-sitter', - symbol = 'TREESITTER', - }, - ['tree-sitter-c'] = { - repo = 'tree-sitter/tree-sitter-c', - symbol = 'TREESITTER_C', - }, - ['tree-sitter-lua'] = { - repo = 'tree-sitter-grammars/tree-sitter-lua', - symbol = 'TREESITTER_LUA', - }, - ['tree-sitter-vim'] = { - repo = 'tree-sitter-grammars/tree-sitter-vim', - symbol = 'TREESITTER_VIM', - }, - ['tree-sitter-vimdoc'] = { - repo = 'neovim/tree-sitter-vimdoc', - symbol = 'TREESITTER_VIMDOC', - }, - ['tree-sitter-query'] = { - repo = 'tree-sitter-grammars/tree-sitter-query', - symbol = 'TREESITTER_QUERY', - }, - ['tree-sitter-markdown'] = { - repo = 'tree-sitter-grammars/tree-sitter-markdown', - symbol = 'TREESITTER_MARKDOWN', - }, - ['wasmtime'] = { - repo = 'bytecodealliance/wasmtime', - symbol = 'WASMTIME', - }, - ['uncrustify'] = { - repo = 'uncrustify/uncrustify', - symbol = 'UNCRUSTIFY', - }, - } - local dependency = dependency_table[dependency_name] - if dependency == nil then - p('Not a dependency: ' .. dependency_name) - die() - end - dependency.name = dependency_name - return dependency -end - -local function get_gh_commit_sha(repo, ref) - require_executable('gh') - - local sha = run_die( - { 'gh', 'api', 'repos/' .. repo .. '/commits/' .. ref, '--jq', '.sha' }, - 'Failed to get commit hash from GitHub. Not a valid ref?' - ) - return sha -end +--- @param repo string +--- @param ref string local function get_archive_info(repo, ref) - require_executable('curl') + local temp_dir = os.getenv('TMPDIR') or os.getenv('TEMP') local archive_name = ref .. '.tar.gz' local archive_path = temp_dir .. '/' .. archive_name local archive_url = 'https://github.com/' .. repo .. '/archive/' .. archive_name - rm_file_if_present(archive_path) run_die( - { 'curl', '-sL', archive_url, '-o', archive_path }, + { 'curl', '-sfL', archive_url, '-o', archive_path }, 'Failed to download archive from GitHub' ) @@ -166,9 +84,24 @@ local function get_archive_info(repo, ref) return { url = archive_url, sha = archive_sha } end -local function write_cmakelists_line(symbol, kind, value) - require_executable('sed') +local function get_gh_commit_sha(repo, ref) + local full_repo = string.format('https://github.com/%s.git', repo) + local tag_exists = run_die({ 'git', 'ls-remote', full_repo, 'refs/tags/' .. ref }) ~= '' + -- We'd rather use the git tag over commit sha if possible + if tag_exists then + return ref + end + + local sha = assert( + run_die( + { 'gh', 'api', 'repos/' .. repo .. '/commits/' .. ref, '--jq', '.sha' }, + 'Failed to get commit hash from GitHub. Not a valid ref?' + ) + ) + return sha +end +local function update_deps_file(symbol, kind, value) run_die({ 'sed', '-i', @@ -178,290 +111,103 @@ local function write_cmakelists_line(symbol, kind, value) }, 'Failed to write ' .. deps_file) end -local function explicit_create_branch(dep) - require_executable('git') +local function ref(name, _ref) + local repo = dependency_table[name] + local symbol = string.gsub(name, 'tree%-sitter', 'treesitter'):gsub('%-', '_'):upper() - local checked_out_branch = run({ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' }) - if checked_out_branch ~= 'master' then - p('Not on master!') - die() - end - run_die({ 'git', 'checkout', '-b', 'bump-' .. dep }, 'git failed to create branch') -end + run_die( + { 'git', 'diff', '--quiet', 'HEAD', '--', deps_file }, + deps_file .. ' has uncommitted changes' + ) -local function verify_branch(new_branch_suffix) - require_executable('git') + _ref = get_gh_commit_sha(repo, _ref) + + local archive = get_archive_info(repo, _ref) + local comment = string.sub(_ref, 1, 9) local checked_out_branch = assert(run({ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' })) if not checked_out_branch:match('^' .. required_branch_prefix) then - p( + print( "Current branch '" .. checked_out_branch .. "' doesn't seem to start with " .. required_branch_prefix ) - p('Checking out to bump-' .. new_branch_suffix) - explicit_create_branch(new_branch_suffix) + print('Checking out to bump-' .. name) + run_die({ 'git', 'checkout', '-b', 'bump-' .. name }, 'git failed to create branch') end -end - -local function update_cmakelists(dependency, archive, comment) - require_executable('git') - verify_branch(dependency.name) - - p('Updating ' .. dependency.name .. ' to ' .. archive.url .. '\n') - write_cmakelists_line(dependency.symbol, 'URL', archive.url:gsub('/', '\\/')) - write_cmakelists_line(dependency.symbol, 'SHA256', archive.sha) + print('Updating ' .. name .. ' to ' .. archive.url .. '\n') + update_deps_file(symbol, 'URL', archive.url:gsub('/', '\\/')) + update_deps_file(symbol, 'SHA256', archive.sha) run_die({ 'git', 'commit', deps_file, '-m', - commit_prefix .. 'bump ' .. dependency.name .. ' to ' .. comment, + commit_prefix .. 'bump ' .. name .. ' to ' .. comment, }, 'git failed to commit') end -local function verify_cmakelists_committed() - require_executable('git') - - run_die( - { 'git', 'diff', '--quiet', 'HEAD', '--', deps_file }, - deps_file .. ' has uncommitted changes' - ) -end - -local function warn_luv_symbol() - p('warning: ' .. get_dependency('Luv').symbol .. '_VERSION will not be updated') -end - --- return first 9 chars of commit -local function short_commit(commit) - return string.sub(commit, 1, 9) -end - --- TODO: remove hardcoded fork -local function gh_pr(pr_title, pr_body) - require_executable('gh') - - local pr_url = run_die({ - 'gh', - 'pr', - 'create', - '--title', - pr_title, - '--body', - pr_body, - }, 'Failed to create PR') - return pr_url -end - -local function find_git_remote(fork) - require_executable('git') - - local remotes = assert(run({ 'git', 'remote', '-v' })) - local git_remote = '' - for remote in remotes:gmatch('[^\r\n]+') do - local words = {} - for word in remote:gmatch('%w+') do - table.insert(words, word) - end - local match = words[1]:match('/github.com[:/]neovim/neovim/') - if fork == 'fork' then - match = not match - end - if match and words[3] == '(fetch)' then - git_remote = words[0] - break - end - end - if git_remote == '' then - git_remote = 'origin' - end - return git_remote -end - -local function create_pr(pr_title, pr_body) - require_executable('git') - - local push_first = true - - local checked_out_branch = run({ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' }) - if push_first then - local push_remote = - run({ 'git', 'config', '--get', 'branch.' .. checked_out_branch .. '.pushRemote' }) - if push_remote == nil then - push_remote = run({ 'git', 'config', '--get', 'remote.pushDefault' }) - if push_remote == nil then - push_remote = - run({ 'git', 'config', '--get', 'branch.' .. checked_out_branch .. '.remote' }) - if push_remote == nil or push_remote == find_git_remote(nil) then - push_remote = find_git_remote('fork') - end - end - end - - p('Pushing to ' .. push_remote .. '/' .. checked_out_branch) - run_die({ 'git', 'push', push_remote, checked_out_branch }, 'Git failed to push') - end - - local pr_url = gh_pr(pr_title, pr_body) - p('\nCreated PR: ' .. pr_url .. '\n') -end - -function M.commit(dependency_name, commit) - local dependency = assert(get_dependency(dependency_name)) - verify_cmakelists_committed() - local commit_sha = get_gh_commit_sha(dependency.repo, commit) - if commit_sha ~= commit then - p('Not a commit: ' .. commit .. '. Did you mean version?') - die() - end - local archive = get_archive_info(dependency.repo, commit) - if dependency_name == 'Luv' then - warn_luv_symbol() - end - update_cmakelists(dependency, archive, short_commit(commit)) -end - -function M.version(dependency_name, version) - vim.validate('dependency_name', dependency_name, 'string') - vim.validate('version', version, 'string') - local dependency = assert(get_dependency(dependency_name)) - verify_cmakelists_committed() - local commit_sha = get_gh_commit_sha(dependency.repo, version) - if commit_sha == version then - p('Not a version: ' .. version .. '. Did you mean commit?') - die() - end - local archive = get_archive_info(dependency.repo, version) - if dependency_name == 'Luv' then - write_cmakelists_line(dependency.symbol, 'VERSION', version) - end - update_cmakelists(dependency, archive, version) -end - -function M.head(dependency_name) - local dependency = assert(get_dependency(dependency_name)) - verify_cmakelists_committed() - local commit_sha = get_gh_commit_sha(dependency.repo, 'HEAD') - local archive = get_archive_info(dependency.repo, commit_sha) - if dependency_name == 'Luv' then - warn_luv_symbol() - end - update_cmakelists(dependency, archive, 'HEAD - ' .. short_commit(commit_sha)) -end - -function M.create_branch(dep) - explicit_create_branch(dep) -end - -function M.submit_pr() - require_executable('git') - - verify_branch('deps') - - local nvim_remote = find_git_remote(nil) - local relevant_commit = assert(run_die({ - 'git', - 'log', - '--grep=' .. commit_prefix, - '--reverse', - "--format='%s'", - nvim_remote .. '/master..HEAD', - '-1', - }, 'Failed to fetch commits')) - - local pr_title - local pr_body - - if relevant_commit == '' then - pr_title = commit_prefix .. 'bump some dependencies' - pr_body = 'bump some dependencies' - else - relevant_commit = relevant_commit:gsub("'", '') - pr_title = relevant_commit - pr_body = relevant_commit:gsub(commit_prefix:gsub('%(', '%%('):gsub('%)', '%%)'), '') - end - pr_body = pr_body .. '\n\n(add explanations if needed)' - p(pr_title .. '\n' .. pr_body .. '\n') - create_pr(pr_title, pr_body) -end - local function usage() - local this_script = _G.arg[0]:match('[^/]*.lua$') - print(([=[ + local this_script = tostring(vim.fs.basename(_G.arg[0])) + local script_exe = './' .. this_script + local help = ([=[ Bump Nvim dependencies - Usage: nvim -l %s [options] - Bump to HEAD, tagged version, commit, or branch: - nvim -l %s --dep Luv --head - nvim -l %s --dep Luv --version 1.43.0-0 - nvim -l %s --dep Luv --commit abc123 - nvim -l %s --dep Luv --branch - Create a PR: - nvim -l %s --pr + Usage: %s [options] + Bump to HEAD, tagged version or commit: + %s luv --head + %s luv --ref 1.43.0-0 + %s luv --ref abc123 Options: - -h show this message and exit. - --pr submit pr for bumping deps. - --branch <dep> create a branch bump-<dep> from current branch. - --dep <dependency> bump to a specific release or tag. + -h, --help show this message and exit. + --list list all dependencies Dependency Options: - --version <tag> bump to a specific release or tag. - --commit <hash> bump to a specific commit. - --HEAD bump to a current head. + --ref <ref> bump to a specific commit or tag. + --head bump to a current head. + ]=]):format(script_exe, script_exe, script_exe, script_exe) + print(help) +end - <dependency> is one of: - "LuaJIT", "libuv", "Luv", "tree-sitter" - ]=]):format(this_script, this_script, this_script, this_script, this_script, this_script)) +local function list_deps() + local l = 'Dependencies:\n' + for k in vim.spairs(dependency_table) do + l = string.format('%s\n%s%s', l, string.rep(' ', 2), k) + end + print(l) end -local function parseargs() +do local args = {} - for i = 1, #_G.arg do - if _G.arg[i] == '-h' then + local i = 1 + while i <= #_G.arg do + if _G.arg[i] == '-h' or _G.arg[i] == '--help' then args.h = true - elseif _G.arg[i] == '--pr' then - args.pr = true - elseif _G.arg[i] == '--branch' then - args.branch = _G.arg[i + 1] - elseif _G.arg[i] == '--dep' then - args.dep = _G.arg[i + 1] - elseif _G.arg[i] == '--version' then - args.version = _G.arg[i + 1] - elseif _G.arg[i] == '--commit' then - args.commit = _G.arg[i + 1] + elseif _G.arg[i] == '--list' then + args.list = true + elseif _G.arg[i] == '--ref' then + args.ref = _G.arg[i + 1] + i = i + 1 elseif _G.arg[i] == '--head' then - args.head = true + args.ref = 'HEAD' + elseif vim.startswith(_G.arg[i], '--') then + die(string.format('Invalid argument %s\n', _G.arg[i])) + else + args.dep = _G.arg[i] end + i = i + 1 end - return args -end - -local is_main = _G.arg[0]:match('bump_deps.lua') -if is_main then - local args = parseargs() if args.h then usage() - elseif args.pr then - M.submit_pr() - elseif args.head then - M.head(args.dep) - elseif args.branch then - M.create_branch(args.dep) - elseif args.version then - M.version(args.dep, args.version) - elseif args.commit then - M.commit(args.dep, args.commit) - elseif args.pr then - M.submit_pr() + elseif args.list then + list_deps() + elseif args.ref then + ref(args.dep, args.ref) else - print('missing required arg\n') - os.exit(1) + die('missing required arg\n') end -else - return M end diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index a9431ae2e5..aaf76a0411 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -26,11 +26,11 @@ local LUA_API_RETURN_OVERRIDES = { nvim_buf_get_command = 'table<string,vim.api.keyset.command_info>', nvim_buf_get_extmark_by_id = 'vim.api.keyset.get_extmark_item_by_id', nvim_buf_get_extmarks = 'vim.api.keyset.get_extmark_item[]', - nvim_buf_get_keymap = 'vim.api.keyset.keymap[]', + nvim_buf_get_keymap = 'vim.api.keyset.get_keymap[]', nvim_get_autocmds = 'vim.api.keyset.get_autocmds.ret[]', nvim_get_color_map = 'table<string,integer>', nvim_get_command = 'table<string,vim.api.keyset.command_info>', - nvim_get_keymap = 'vim.api.keyset.keymap[]', + nvim_get_keymap = 'vim.api.keyset.get_keymap[]', nvim_get_mark = 'vim.api.keyset.get_mark', -- Can also return table<string,vim.api.keyset.get_hl_info>, however we need to @@ -47,6 +47,18 @@ local LUA_API_RETURN_OVERRIDES = { nvim_win_get_config = 'vim.api.keyset.win_config', } +local LUA_API_KEYSET_OVERRIDES = { + create_autocmd = { + callback = 'string|(fun(args: vim.api.keyset.create_autocmd.callback_args): boolean?)', + }, +} + +local LUA_API_PARAM_OVERRIDES = { + nvim_create_user_command = { + command = 'string|fun(args: vim.api.keyset.create_user_command.command_args)', + }, +} + local LUA_META_HEADER = { '--- @meta _', '-- THIS FILE IS GENERATED', @@ -60,6 +72,10 @@ local LUA_API_META_HEADER = { '-- DO NOT EDIT', "error('Cannot require a meta file')", '', + '--- This file embeds vimdoc as the function descriptions', + '--- so ignore any doc related errors.', + '--- @diagnostic disable: undefined-doc-name,luadoc-miss-symbol', + '', 'vim.api = {}', } @@ -118,10 +134,19 @@ local API_TYPES = { LuaRef = 'function', Dict = 'table<string,any>', Float = 'number', - HLGroupID = 'number|string', + HLGroupID = 'integer|string', void = '', } +--- @param s string +--- @return string +local function luaescape(s) + if LUA_KEYWORDS[s] then + return s .. '_' + end + return s +end + --- @param x string --- @param sep? string --- @return string[] @@ -133,6 +158,10 @@ end --- @param t string --- @return string local function api_type(t) + if vim.startswith(t, '*') then + return api_type(t:sub(2)) .. '?' + end + local as0 = t:match('^ArrayOf%((.*)%)') if as0 then local as = split(as0, ', ') @@ -149,6 +178,33 @@ local function api_type(t) return 'table<string,' .. api_type(d0) .. '>' end + local u = t:match('^Union%((.*)%)') + if u then + local us = vim.split(u, ',%s*') + return table.concat(vim.tbl_map(api_type, us), '|') + end + + local l = t:match('^LuaRefOf%((.*)%)') + if l then + --- @type string + l = l:gsub('%s+', ' ') + --- @type string?, string? + local as, r = l:match('%((.*)%),%s*(.*)') + if not as then + --- @type string + as = assert(l:match('%((.*)%)')) + end + + local as1 = {} --- @type string[] + for a in vim.gsplit(as, ',%s') do + local a1 = vim.split(a, '%s+', { trimempty = true }) + local nm = a1[2]:gsub('%*(.*)$', '%1?') + as1[#as1 + 1] = nm .. ': ' .. api_type(a1[1]) + end + + return ('fun(%s)%s'):format(table.concat(as1, ', '), r and ': ' .. api_type(r) or '') + end + return API_TYPES[t] or t end @@ -165,7 +221,7 @@ local function render_fun_sig(f, params) --- @param v [string,string] --- @return string function(v) - return v[1] + return luaescape(v[1]) end, params ), @@ -181,7 +237,6 @@ local function render_fun_sig(f, params) end --- Uniquify names ---- Fix any names that are lua keywords --- @param params [string,string,string][] --- @return [string,string,string][] local function process_params(params) @@ -189,9 +244,6 @@ local function process_params(params) 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 @@ -251,11 +303,13 @@ local function get_api_meta() sees[#sees + 1] = see.desc end + local pty_overrides = LUA_API_PARAM_OVERRIDES[fun.name] or {} + local params = {} --- @type [string,string][] for _, p in ipairs(fun.params) do params[#params + 1] = { p.name, - api_type(p.type), + api_type(pty_overrides[p.name] or p.type), not deprecated and p.desc or nil, } end @@ -344,10 +398,10 @@ local function render_api_meta(_f, fun, write) 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] + local pname, ptype, pdesc = luaescape(p[1]), p[2], p[3] + param_names[#param_names + 1] = pname if pdesc then - local s = '--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' + local s = '--- @param ' .. pname .. ' ' .. ptype .. ' ' local pdesc_a = split(vim.trim(norm_text(pdesc))) write(s .. pdesc_a[1]) for i = 2, #pdesc_a do @@ -357,7 +411,7 @@ local function render_api_meta(_f, fun, write) write('--- ' .. pdesc_a[i]) end else - write('--- @param ' .. p[1] .. ' ' .. p[2]) + write('--- @param ' .. pname .. ' ' .. ptype) end end @@ -382,9 +436,11 @@ local function get_api_keysets_meta() local keysets = metadata.keysets for _, k in ipairs(keysets) do + local pty_overrides = LUA_API_KEYSET_OVERRIDES[k.name] or {} local params = {} for _, key in ipairs(k.keys) do - table.insert(params, { key .. '?', api_type(k.types[key] or 'any') }) + local pty = pty_overrides[key] or k.types[key] or 'any' + table.insert(params, { key .. '?', api_type(pty) }) end ret[k.name] = { signature = 'NA', @@ -444,10 +500,14 @@ local function render_eval_meta(f, fun, write) end end + for _, text in ipairs(vim.fn.reverse(fun.generics or {})) do + write(fmt('--- @generic %s', text)) + 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 pname, ptype = luaescape(param[1]), param[2] local optional = (pname ~= '...' and i > req_args) and '?' or '' write(fmt('--- @param %s%s %s', pname, optional, ptype)) end @@ -610,7 +670,16 @@ local function render_option_meta(_f, opt, write) write('--- ' .. l) end - write('--- @type ' .. OPTION_TYPES[opt.type]) + if opt.type == 'string' and not opt.list and opt.values then + local values = {} --- @type string[] + for _, e in ipairs(opt.values) do + values[#values + 1] = fmt("'%s'", e) + end + write('--- @type ' .. table.concat(values, '|')) + else + write('--- @type ' .. OPTION_TYPES[opt.type]) + end + 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) diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index b8f80e94be..53a65fd65f 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -48,7 +48,7 @@ local spell_dict = { --- specify the list of keywords to ignore (i.e. allow), or true to disable spell check completely. --- @type table<string, true|string[]> local spell_ignore_files = { - ['backers.txt'] = true, + ['credits.txt'] = { 'Neovim' }, ['news.txt'] = { 'tree-sitter' }, -- in news, may refer to the upstream "tree-sitter" library ['news-0.10.txt'] = { 'tree-sitter' }, } @@ -70,6 +70,8 @@ local new_layout = { ['dev_vimpatch.txt'] = true, ['editorconfig.txt'] = true, ['faq.txt'] = true, + ['gui.txt'] = true, + ['intro.txt'] = true, ['lua.txt'] = true, ['luaref.txt'] = true, ['news.txt'] = true, @@ -84,6 +86,7 @@ local new_layout = { -- Map of new:old pages, to redirect renamed pages. local redirects = { + ['credits'] = 'backers', ['tui'] = 'term', ['terminal'] = 'nvim_terminal_emulator', } @@ -116,7 +119,7 @@ local exclude_invalid_urls = { -- Deprecated, brain-damaged files that I don't care about. local ignore_errors = { ['pi_netrw.txt'] = true, - ['backers.txt'] = true, + ['credits.txt'] = true, } local function tofile(fname, text) diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua index 9cd5b598da..d200050fe1 100755 --- a/scripts/gen_vimdoc.lua +++ b/scripts/gen_vimdoc.lua @@ -274,6 +274,7 @@ local config = { 'diagnostic.lua', 'codelens.lua', 'completion.lua', + 'folding_range.lua', 'inlay_hint.lua', 'tagfunc.lua', 'semantic_tokens.lua', @@ -349,12 +350,14 @@ local config = { helptag_fmt = function(name) if name:lower() == 'treesitter' then return 'lua-treesitter-core' + elseif name:lower() == 'query' then + return 'lua-treesitter-query' elseif name:lower() == 'tstree' then return { 'treesitter-tree', 'TSTree' } elseif name:lower() == 'tsnode' then return { 'treesitter-node', 'TSNode' } end - return 'lua-treesitter-' .. name:lower() + return 'treesitter-' .. name:lower() end, }, editorconfig = { @@ -514,6 +517,8 @@ local function inline_type(obj, classes) elseif desc == '' then if ty_islist then desc = desc .. 'A list of objects with the following fields:' + elseif cls.parent then + desc = desc .. fmt('Extends |%s| with the additional fields:', cls.parent) else desc = desc .. 'A table with the following fields:' end @@ -538,7 +543,8 @@ end --- @param generics? table<string,string> --- @param classes? table<string,nvim.luacats.parser.class> --- @param exclude_types? true -local function render_fields_or_params(xs, generics, classes, exclude_types) +--- @param cfg nvim.gen_vimdoc.Config +local function render_fields_or_params(xs, generics, classes, exclude_types, cfg) local ret = {} --- @type string[] xs = vim.tbl_filter(should_render_field_or_param, xs) @@ -558,7 +564,9 @@ local function render_fields_or_params(xs, generics, classes, exclude_types) p.desc = pdesc inline_type(p, classes) - local nm, ty, desc = p.name, p.type, p.desc + local nm, ty = p.name, p.type + + local desc = p.classvar and string.format('See |%s|.', cfg.fn_helptag_fmt(p)) or p.desc local fnm = p.kind == 'operator' and fmt('op(%s)', nm) or fmt_field_name(nm) local pnm = fmt(' • %-' .. indent .. 's', fnm) @@ -591,7 +599,8 @@ end --- @param class nvim.luacats.parser.class --- @param classes table<string,nvim.luacats.parser.class> -local function render_class(class, classes) +--- @param cfg nvim.gen_vimdoc.Config +local function render_class(class, classes, cfg) if class.access or class.nodoc or class.inlinedoc then return end @@ -610,7 +619,7 @@ local function render_class(class, classes) table.insert(ret, md_to_vimdoc(class.desc, INDENTATION, INDENTATION, TEXT_WIDTH)) end - local fields_txt = render_fields_or_params(class.fields, nil, classes) + local fields_txt = render_fields_or_params(class.fields, nil, classes, nil, cfg) if not fields_txt:match('^%s*$') then table.insert(ret, '\n Fields: ~\n') table.insert(ret, fields_txt) @@ -621,11 +630,12 @@ local function render_class(class, classes) end --- @param classes table<string,nvim.luacats.parser.class> -local function render_classes(classes) +--- @param cfg nvim.gen_vimdoc.Config +local function render_classes(classes, cfg) local ret = {} --- @type string[] for _, class in vim.spairs(classes) do - ret[#ret + 1] = render_class(class, classes) + ret[#ret + 1] = render_class(class, classes, cfg) end return table.concat(ret) @@ -656,10 +666,6 @@ local function render_fun_header(fun, cfg) local proto = fun.table and nm or nm .. '(' .. table.concat(args, ', ') .. ')' - if not cfg.fn_helptag_fmt then - cfg.fn_helptag_fmt = fn_helptag_fmt_common - end - local tag = '*' .. cfg.fn_helptag_fmt(fun) .. '*' if #proto + #tag > TEXT_WIDTH - 8 then @@ -774,7 +780,8 @@ local function render_fun(fun, classes, cfg) end if fun.params and #fun.params > 0 then - local param_txt = render_fields_or_params(fun.params, fun.generics, classes, cfg.exclude_types) + local param_txt = + render_fields_or_params(fun.params, fun.generics, classes, cfg.exclude_types, cfg) if not param_txt:match('^%s*$') then table.insert(ret, '\n Parameters: ~\n') ret[#ret + 1] = param_txt @@ -957,6 +964,7 @@ end --- @param cfg nvim.gen_vimdoc.Config local function gen_target(cfg) + cfg.fn_helptag_fmt = cfg.fn_helptag_fmt or fn_helptag_fmt_common print('Target:', cfg.filename) local sections = {} --- @type table<string,nvim.gen_vimdoc.Section> @@ -987,7 +995,7 @@ local function gen_target(cfg) print(' Processing file:', f) local funs_txt = render_funs(funs, all_classes, cfg) if next(classes) then - local classes_txt = render_classes(classes) + local classes_txt = render_classes(classes, cfg) if vim.trim(classes_txt) ~= '' then funs_txt = classes_txt .. '\n' .. funs_txt end diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh index e8aac42a9c..e683a9dcd1 100755 --- a/scripts/genappimage.sh +++ b/scripts/genappimage.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -e ######################################################################## # Package the binaries built as an AppImage @@ -11,6 +11,7 @@ if [ -z "$ARCH" ]; then ARCH="$(arch)" export ARCH fi +ARCH_ORIGINAL=$ARCH TAG=$1 @@ -40,16 +41,16 @@ export VERSION cd "$APP_BUILD_DIR" || exit # Only downloads linuxdeploy if the remote file is different from local -if [ -e "$APP_BUILD_DIR"/linuxdeploy-x86_64.AppImage ]; then - curl -Lo "$APP_BUILD_DIR"/linuxdeploy-x86_64.AppImage \ - -z "$APP_BUILD_DIR"/linuxdeploy-x86_64.AppImage \ - https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage +if [ -e "$APP_BUILD_DIR"/linuxdeploy-"$ARCH".AppImage ]; then + curl -Lo "$APP_BUILD_DIR"/linuxdeploy-"$ARCH".AppImage \ + -z "$APP_BUILD_DIR"/linuxdeploy-"$ARCH".AppImage \ + https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-"$ARCH".AppImage else - curl -Lo "$APP_BUILD_DIR"/linuxdeploy-x86_64.AppImage \ - https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + curl -Lo "$APP_BUILD_DIR"/linuxdeploy-"$ARCH".AppImage \ + https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-"$ARCH".AppImage fi -chmod +x "$APP_BUILD_DIR"/linuxdeploy-x86_64.AppImage +chmod +x "$APP_BUILD_DIR"/linuxdeploy-"$ARCH".AppImage # metainfo is not packaged automatically by linuxdeploy mkdir -p "$APP_DIR/usr/share/metainfo/" @@ -75,24 +76,30 @@ chmod 755 AppRun cd "$APP_BUILD_DIR" || exit # Get out of AppImage directory. +# We want to be consistent, so always use arm64 over aarch64 +if [[ "$ARCH" == 'aarch64' ]]; then + ARCH="arm64" + export ARCH +fi + # Set the name of the file generated by appimage -export OUTPUT=nvim.appimage +export OUTPUT=nvim-linux-"$ARCH".appimage # If it's a release generate the zsync file if [ -n "$TAG" ]; then - export UPDATE_INFORMATION="gh-releases-zsync|neovim|neovim|$TAG|nvim.appimage.zsync" + export UPDATE_INFORMATION="gh-releases-zsync|neovim|neovim|$TAG|nvim-linux-$ARCH.appimage.zsync" fi # Generate AppImage. # - Expects: $ARCH, $APP, $VERSION env vars # - Expects: ./$APP.AppDir/ directory -# - Produces: ./nvim.appimage -./linuxdeploy-x86_64.AppImage --appdir $APP.AppDir -d "$ROOT_DIR"/runtime/nvim.desktop -i \ +# - Produces: ./nvim-linux-$ARCH.appimage +./linuxdeploy-"$ARCH_ORIGINAL".AppImage --appdir $APP.AppDir -d "$ROOT_DIR"/runtime/nvim.desktop -i \ "$ROOT_DIR/runtime/nvim.png" --output appimage # Moving the final executable to a different folder so it isn't in the # way for a subsequent build. -mv "$ROOT_DIR"/build/nvim.appimage* "$ROOT_DIR"/build/bin +mv "$ROOT_DIR"/build/nvim-linux-"$ARCH".appimage* "$ROOT_DIR"/build/bin echo 'genappimage.sh: finished' diff --git a/scripts/luacats_grammar.lua b/scripts/luacats_grammar.lua index 34c1470fea..b700bcf58f 100644 --- a/scripts/luacats_grammar.lua +++ b/scripts/luacats_grammar.lua @@ -160,9 +160,9 @@ local typedef = P({ return vim.trim(match):gsub('^%((.*)%)$', '%1'):gsub('%?+', '?') end -local opt_exact = opt(Cg(Pf('(exact)'), 'access')) local access = P('private') + P('protected') + P('package') local caccess = Cg(access, 'access') +local cattr = Cg(comma(access + P('exact')), 'access') local desc_delim = Sf '#:' + ws local desc = Cg(rep(any), 'desc') local opt_desc = opt(desc_delim * desc) @@ -178,7 +178,7 @@ local grammar = P { + annot('type', comma1(Ct(v.ctype)) * opt_desc) + annot('cast', ty_name * ws * opt(Sf('+-')) * v.ctype) + annot('generic', ty_name * opt(colon * v.ctype)) - + annot('class', opt_exact * opt(paren(caccess)) * fill * ty_name * opt_parent) + + annot('class', opt(paren(cattr)) * fill * ty_name * opt_parent) + annot('field', opt(caccess * ws) * v.field_name * ws * v.ctype * opt_desc) + annot('operator', ty_name * opt(paren(Cg(v.ctype, 'argtype'))) * colon * v.ctype) + annot(access) diff --git a/scripts/luacats_parser.lua b/scripts/luacats_parser.lua index 9a763e4d7b..8a50077aa8 100644 --- a/scripts/luacats_parser.lua +++ b/scripts/luacats_parser.lua @@ -1,9 +1,6 @@ local luacats_grammar = require('scripts.luacats_grammar') ---- @class nvim.luacats.parser.param ---- @field name string ---- @field type string ---- @field desc string +--- @class nvim.luacats.parser.param : nvim.luacats.Param --- @class nvim.luacats.parser.return --- @field name string @@ -41,21 +38,14 @@ local luacats_grammar = require('scripts.luacats_grammar') --- @field notes? nvim.luacats.parser.note[] --- @field see? nvim.luacats.parser.note[] ---- @class nvim.luacats.parser.field ---- @field name string ---- @field type string ---- @field desc string ---- @field access? 'private'|'package'|'protected' +--- @class nvim.luacats.parser.field : nvim.luacats.Field +--- @field classvar? string --- @field nodoc? true ---- @class nvim.luacats.parser.class ---- @field kind 'class' ---- @field parent? string ---- @field name string ---- @field desc string +--- @class nvim.luacats.parser.class : nvim.luacats.Class +--- @field desc? string --- @field nodoc? true --- @field inlinedoc? true ---- @field access? 'private'|'package'|'protected' --- @field fields nvim.luacats.parser.field[] --- @field notes? string[] @@ -332,7 +322,10 @@ local function process_lua_line(line, state, classes, classvars, has_indent) end -- Add method as the field to the class - table.insert(classes[class].fields, fun2field(cur_obj)) + local cls = classes[class] + local field = fun2field(cur_obj) + field.classvar = cur_obj.classvar + table.insert(cls.fields, field) return end diff --git a/scripts/vimpatch.lua b/scripts/vimpatch.lua index cbec50fc17..5d8bea6a98 100755 --- a/scripts/vimpatch.lua +++ b/scripts/vimpatch.lua @@ -1,7 +1,7 @@ -- Updates version.c list of applied Vim patches. -- -- Usage: --- VIM_SOURCE_DIR=~/neovim/.vim-src/ nvim -V1 -es -i NONE +'luafile ./scripts/vimpatch.lua' +q +-- VIM_SOURCE_DIR=~/neovim/.vim-src/ nvim -l ./scripts/vimpatch.lua local nvim = vim.api |