build: enable lintlua for scripts/ dir #26391

Problem:
We don't enable stylua for many Lua scripts. Automating code-style is an
important tool for reducing time spent on accidental (non-essential)
complexity.

Solution:
- Enable lintlua for `scripts/` directory.
- Specify `call_parentheses = "Input"`, we should allow kwargs-style
  function invocations.
This commit is contained in:
Justin M. Keyes 2023-12-04 12:38:31 -08:00 committed by GitHub
parent e5d7003b02
commit 517f0cc634
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 415 additions and 292 deletions

View File

@ -3,4 +3,4 @@ line_endings = "Unix"
indent_type = "Spaces" indent_type = "Spaces"
indent_width = 2 indent_width = 2
quote_style = "AutoPreferSingle" quote_style = "AutoPreferSingle"
call_parentheses = "Always" call_parentheses = "Input"

View File

@ -2,6 +2,5 @@
/runtime/lua/coxpcall.lua /runtime/lua/coxpcall.lua
/runtime/lua/vim/_meta /runtime/lua/vim/_meta
/runtime/lua/vim/re.lua /runtime/lua/vim/re.lua
/scripts
/src /src
/test /test

View File

@ -233,7 +233,7 @@ add_glob_target(
TARGET lintlua-stylua TARGET lintlua-stylua
COMMAND ${STYLUA_PRG} COMMAND ${STYLUA_PRG}
FLAGS --color=always --check --respect-ignores FLAGS --color=always --check --respect-ignores
GLOB_DIRS runtime/ GLOB_DIRS runtime/ scripts/
GLOB_PAT *.lua GLOB_PAT *.lua
TOUCH_STRATEGY SINGLE) TOUCH_STRATEGY SINGLE)
@ -260,7 +260,7 @@ add_glob_target(
TARGET formatlua TARGET formatlua
COMMAND ${STYLUA_PRG} COMMAND ${STYLUA_PRG}
FLAGS --respect-ignores FLAGS --respect-ignores
GLOB_DIRS runtime GLOB_DIRS runtime/ scripts/
GLOB_PAT *.lua) GLOB_PAT *.lua)
add_custom_target(format) add_custom_target(format)

View File

@ -138,9 +138,10 @@ local function get_archive_info(repo, ref)
'Failed to download archive from GitHub' 'Failed to download archive from GitHub'
) )
local shacmd = (vim.fn.executable('sha256sum') == 1 local shacmd = (
and{ 'sha256sum', archive_path } vim.fn.executable('sha256sum') == 1 and { 'sha256sum', archive_path }
or { 'shasum', '-a', '256', archive_path }) or { 'shasum', '-a', '256', archive_path }
)
local archive_sha = run(shacmd):gmatch('%w+')() local archive_sha = run(shacmd):gmatch('%w+')()
return { url = archive_url, sha = archive_sha } return { url = archive_url, sha = archive_sha }
end end
@ -152,18 +153,7 @@ local function write_cmakelists_line(symbol, kind, value)
'sed', 'sed',
'-i', '-i',
'-e', '-e',
's/' 's/' .. symbol .. '_' .. kind .. '.*$' .. '/' .. symbol .. '_' .. kind .. ' ' .. value .. '/',
.. symbol
.. '_'
.. kind
.. '.*$'
.. '/'
.. symbol
.. '_'
.. kind
.. ' '
.. value
.. '/',
deps_file, deps_file,
}, 'Failed to write ' .. deps_file) }, 'Failed to write ' .. deps_file)
end end
@ -203,16 +193,13 @@ local function update_cmakelists(dependency, archive, comment)
p('Updating ' .. dependency.name .. ' to ' .. archive.url .. '\n') p('Updating ' .. dependency.name .. ' to ' .. archive.url .. '\n')
write_cmakelists_line(dependency.symbol, 'URL', archive.url:gsub('/', '\\/')) write_cmakelists_line(dependency.symbol, 'URL', archive.url:gsub('/', '\\/'))
write_cmakelists_line(dependency.symbol, 'SHA256', archive.sha) write_cmakelists_line(dependency.symbol, 'SHA256', archive.sha)
run_die( run_die({
{
'git', 'git',
'commit', 'commit',
deps_file, deps_file,
'-m', '-m',
commit_prefix .. 'bump ' .. dependency.name .. ' to ' .. comment, commit_prefix .. 'bump ' .. dependency.name .. ' to ' .. comment,
}, }, 'git failed to commit')
'git failed to commit'
)
end end
local function verify_cmakelists_committed() local function verify_cmakelists_committed()
@ -384,7 +371,7 @@ function M.submit_pr()
end end
local function usage() local function usage()
local this_script = _G.arg[0]:match("[^/]*.lua$") local this_script = _G.arg[0]:match('[^/]*.lua$')
print(([=[ print(([=[
Bump Nvim dependencies Bump Nvim dependencies

View File

@ -473,7 +473,7 @@ local function render_option_default(d, vimdoc)
end end
end end
if dt == "" or dt == nil or type(dt) == 'function' then if dt == '' or dt == nil or type(dt) == 'function' then
dt = d.meta dt = d.meta
end end
@ -541,7 +541,7 @@ local function scope_to_doc(s)
global = 'global', global = 'global',
buffer = 'local to buffer', buffer = 'local to buffer',
window = 'local to window', window = 'local to window',
tab = 'local to tab page' tab = 'local to tab page',
} }
if #s == 1 then if #s == 1 then
@ -618,7 +618,7 @@ local function build_option_tags(opt)
end end
for i, t in ipairs(tags) do for i, t in ipairs(tags) do
tags[i] = "*"..t.."*" tags[i] = '*' .. t .. '*'
end end
return tags return tags
@ -751,11 +751,11 @@ local CONFIG = {
header = { '' }, header = { '' },
from = 'A jump table for the options with a short description can be found at |Q_op|.', from = 'A jump table for the options with a short description can be found at |Q_op|.',
footer = { footer = {
' vim:tw=78:ts=8:noet:ft=help:norl:' ' vim:tw=78:ts=8:noet:ft=help:norl:',
}, },
funcs = get_option_meta, funcs = get_option_meta,
render = render_option_doc, render = render_option_doc,
} },
} }
--- @param elem nvim.gen_eval_files.elem --- @param elem nvim.gen_eval_files.elem

View File

@ -8,18 +8,18 @@ if do_not_run then
return return
end end
local filetype_vim = "runtime/filetype.vim" local filetype_vim = 'runtime/filetype.vim'
local filetype_lua = "runtime/lua/vim/filetype.lua" local filetype_lua = 'runtime/lua/vim/filetype.lua'
local keywords = { local keywords = {
["for"] = true, ['for'] = true,
["or"] = true, ['or'] = true,
["and"] = true, ['and'] = true,
["end"] = true, ['end'] = true,
["do"] = true, ['do'] = true,
["if"] = true, ['if'] = true,
["while"] = true, ['while'] = true,
["repeat"] = true, ['repeat'] = true,
} }
local sections = { local sections = {
@ -28,42 +28,42 @@ local sections = {
pattern = { str = {}, func = {} }, pattern = { str = {}, func = {} },
} }
local specialchars = "%*%?\\%$%[%]%{%}" local specialchars = '%*%?\\%$%[%]%{%}'
local function add_pattern(pat, ft) local function add_pattern(pat, ft)
local ok = true local ok = true
-- Patterns that start or end with { or } confuse splitting on commas and make parsing harder, so just skip those -- Patterns that start or end with { or } confuse splitting on commas and make parsing harder, so just skip those
if not string.find(pat, "^%{") and not string.find(pat, "%}$") then if not string.find(pat, '^%{') and not string.find(pat, '%}$') then
for part in string.gmatch(pat, "[^,]+") do for part in string.gmatch(pat, '[^,]+') do
if not string.find(part, "[" .. specialchars .. "]") then if not string.find(part, '[' .. specialchars .. ']') then
if type(ft) == "string" then if type(ft) == 'string' then
sections.filename.str[part] = ft sections.filename.str[part] = ft
else else
sections.filename.func[part] = ft sections.filename.func[part] = ft
end end
elseif string.match(part, "^%*%.[^%./" .. specialchars .. "]+$") then elseif string.match(part, '^%*%.[^%./' .. specialchars .. ']+$') then
if type(ft) == "string" then if type(ft) == 'string' then
sections.extension.str[part:sub(3)] = ft sections.extension.str[part:sub(3)] = ft
else else
sections.extension.func[part:sub(3)] = ft sections.extension.func[part:sub(3)] = ft
end end
else else
if string.match(part, "^%*/[^" .. specialchars .. "]+$") then if string.match(part, '^%*/[^' .. specialchars .. ']+$') then
-- For patterns matching */some/pattern we want to easily match files -- For patterns matching */some/pattern we want to easily match files
-- with path /some/pattern, so include those in filename detection -- with path /some/pattern, so include those in filename detection
if type(ft) == "string" then if type(ft) == 'string' then
sections.filename.str[part:sub(2)] = ft sections.filename.str[part:sub(2)] = ft
else else
sections.filename.func[part:sub(2)] = ft sections.filename.func[part:sub(2)] = ft
end end
end end
if string.find(part, "^[%w-_.*?%[%]/]+$") then if string.find(part, '^[%w-_.*?%[%]/]+$') then
local p = part:gsub("%.", "%%."):gsub("%*", ".*"):gsub("%?", ".") local p = part:gsub('%.', '%%.'):gsub('%*', '.*'):gsub('%?', '.')
-- Insert into array to maintain order rather than setting -- Insert into array to maintain order rather than setting
-- key-value directly -- key-value directly
if type(ft) == "string" then if type(ft) == 'string' then
sections.pattern.str[p] = ft sections.pattern.str[p] = ft
else else
sections.pattern.func[p] = ft sections.pattern.func[p] = ft
@ -80,14 +80,16 @@ end
local function parse_line(line) local function parse_line(line)
local pat, ft local pat, ft
pat, ft = line:match("^%s*au%a* Buf[%a,]+%s+(%S+)%s+setf%s+(%S+)") pat, ft = line:match('^%s*au%a* Buf[%a,]+%s+(%S+)%s+setf%s+(%S+)')
if pat then if pat then
return add_pattern(pat, ft) return add_pattern(pat, ft)
else else
local func local func
pat, func = line:match("^%s*au%a* Buf[%a,]+%s+(%S+)%s+call%s+(%S+)") pat, func = line:match('^%s*au%a* Buf[%a,]+%s+(%S+)%s+call%s+(%S+)')
if pat then if pat then
return add_pattern(pat, function() return func end) return add_pattern(pat, function()
return func
end)
end end
end end
end end
@ -95,12 +97,12 @@ end
local unparsed = {} local unparsed = {}
local full_line local full_line
for line in io.lines(filetype_vim) do for line in io.lines(filetype_vim) do
local cont = string.match(line, "^%s*\\%s*(.*)$") local cont = string.match(line, '^%s*\\%s*(.*)$')
if cont then if cont then
full_line = full_line .. " " .. cont full_line = full_line .. ' ' .. cont
else else
if full_line then if full_line then
if not parse_line(full_line) and string.find(full_line, "^%s*au%a* Buf") then if not parse_line(full_line) and string.find(full_line, '^%s*au%a* Buf') then
table.insert(unparsed, full_line) table.insert(unparsed, full_line)
end end
end end
@ -109,40 +111,46 @@ for line in io.lines(filetype_vim) do
end end
if #unparsed > 0 then if #unparsed > 0 then
print("Failed to parse the following patterns:") print('Failed to parse the following patterns:')
for _, v in ipairs(unparsed) do for _, v in ipairs(unparsed) do
print(v) print(v)
end end
end end
local function add_item(indent, key, ft) local function add_item(indent, key, ft)
if type(ft) == "string" then if type(ft) == 'string' then
if string.find(key, "%A") or keywords[key] then if string.find(key, '%A') or keywords[key] then
key = string.format("[\"%s\"]", key) key = string.format('["%s"]', key)
end end
return string.format([[%s%s = "%s",]], indent, key, ft) return string.format([[%s%s = "%s",]], indent, key, ft)
elseif type(ft) == "function" then elseif type(ft) == 'function' then
local func = ft() local func = ft()
if string.find(key, "%A") or keywords[key] then if string.find(key, '%A') or keywords[key] then
key = string.format("[\"%s\"]", key) key = string.format('["%s"]', key)
end end
-- Right now only a single argument is supported, which covers -- Right now only a single argument is supported, which covers
-- everything in filetype.vim as of this writing -- everything in filetype.vim as of this writing
local arg = string.match(func, "%((.*)%)$") local arg = string.match(func, '%((.*)%)$')
func = string.gsub(func, "%(.*$", "") func = string.gsub(func, '%(.*$', '')
if arg == "" then if arg == '' then
-- Function with no arguments, call the function directly -- Function with no arguments, call the function directly
return string.format([[%s%s = function() vim.fn["%s"]() end,]], indent, key, func) return string.format([[%s%s = function() vim.fn["%s"]() end,]], indent, key, func)
elseif string.match(arg, [[^(["']).*%1$]]) then elseif string.match(arg, [[^(["']).*%1$]]) then
-- String argument -- String argument
if func == "s:StarSetf" then if func == 's:StarSetf' then
return string.format([[%s%s = starsetf(%s),]], indent, key, arg) return string.format([[%s%s = starsetf(%s),]], indent, key, arg)
else else
return string.format([[%s%s = function() vim.fn["%s"](%s) end,]], indent, key, func, arg) return string.format([[%s%s = function() vim.fn["%s"](%s) end,]], indent, key, func, arg)
end end
elseif string.find(arg, "%(") then elseif string.find(arg, '%(') then
-- Function argument -- Function argument
return string.format([[%s%s = function() vim.fn["%s"](vim.fn.%s) end,]], indent, key, func, arg) return string.format(
[[%s%s = function() vim.fn["%s"](vim.fn.%s) end,]],
indent,
key,
func,
arg
)
else else
assert(false, arg) assert(false, arg)
end end
@ -153,7 +161,7 @@ do
local lines = {} local lines = {}
local start = false local start = false
for line in io.lines(filetype_lua) do for line in io.lines(filetype_lua) do
if line:match("^%s+-- END [A-Z]+$") then if line:match('^%s+-- END [A-Z]+$') then
start = false start = false
end end
@ -161,7 +169,7 @@ do
table.insert(lines, line) table.insert(lines, line)
end end
local indent, section = line:match("^(%s+)-- BEGIN ([A-Z]+)$") local indent, section = line:match('^(%s+)-- BEGIN ([A-Z]+)$')
if section then if section then
start = true start = true
local t = sections[string.lower(section)] local t = sections[string.lower(section)]
@ -195,7 +203,7 @@ do
end end
end end
end end
local f = io.open(filetype_lua, "w") local f = io.open(filetype_lua, 'w')
f:write(table.concat(lines, "\n") .. "\n") f:write(table.concat(lines, '\n') .. '\n')
f:close() f:close()
end end

View File

@ -60,26 +60,26 @@ local new_layout = {
-- TODO: These known invalid |links| require an update to the relevant docs. -- TODO: These known invalid |links| require an update to the relevant docs.
local exclude_invalid = { local exclude_invalid = {
["'string'"] = "eval.txt", ["'string'"] = 'eval.txt',
Query = 'treesitter.txt', Query = 'treesitter.txt',
matchit = 'vim_diff.txt', matchit = 'vim_diff.txt',
["set!"] = "treesitter.txt", ['set!'] = 'treesitter.txt',
} }
-- False-positive "invalid URLs". -- False-positive "invalid URLs".
local exclude_invalid_urls = { local exclude_invalid_urls = {
["http://"] = "usr_23.txt", ['http://'] = 'usr_23.txt',
["http://."] = "usr_23.txt", ['http://.'] = 'usr_23.txt',
["http://aspell.net/man-html/Affix-Compression.html"] = "spell.txt", ['http://aspell.net/man-html/Affix-Compression.html'] = 'spell.txt',
["http://aspell.net/man-html/Phonetic-Code.html"] = "spell.txt", ['http://aspell.net/man-html/Phonetic-Code.html'] = 'spell.txt',
["http://canna.sourceforge.jp/"] = "mbyte.txt", ['http://canna.sourceforge.jp/'] = 'mbyte.txt',
["http://gnuada.sourceforge.net"] = "ft_ada.txt", ['http://gnuada.sourceforge.net'] = 'ft_ada.txt',
["http://lua-users.org/wiki/StringLibraryTutorial"] = "lua.txt", ['http://lua-users.org/wiki/StringLibraryTutorial'] = 'lua.txt',
["http://michael.toren.net/code/"] = "pi_tar.txt", ['http://michael.toren.net/code/'] = 'pi_tar.txt',
["http://papp.plan9.de"] = "syntax.txt", ['http://papp.plan9.de'] = 'syntax.txt',
["http://wiki.services.openoffice.org/wiki/Dictionaries"] = "spell.txt", ['http://wiki.services.openoffice.org/wiki/Dictionaries'] = 'spell.txt',
["http://www.adapower.com"] = "ft_ada.txt", ['http://www.adapower.com'] = 'ft_ada.txt',
["http://www.jclark.com/"] = "quickfix.txt", ['http://www.jclark.com/'] = 'quickfix.txt',
} }
-- Deprecated, brain-damaged files that I don't care about. -- Deprecated, brain-damaged files that I don't care about.
@ -98,19 +98,18 @@ local function tofile(fname, text)
end end
local function html_esc(s) local function html_esc(s)
return s:gsub( return s:gsub('&', '&amp;'):gsub('<', '&lt;'):gsub('>', '&gt;')
'&', '&amp;'):gsub(
'<', '&lt;'):gsub(
'>', '&gt;')
end end
local function url_encode(s) local function url_encode(s)
-- Credit: tpope / vim-unimpaired -- Credit: tpope / vim-unimpaired
-- NOTE: these chars intentionally *not* escaped: ' ( ) -- NOTE: these chars intentionally *not* escaped: ' ( )
return vim.fn.substitute(vim.fn.iconv(s, 'latin1', 'utf-8'), return vim.fn.substitute(
vim.fn.iconv(s, 'latin1', 'utf-8'),
[=[[^A-Za-z0-9()'_.~-]]=], [=[[^A-Za-z0-9()'_.~-]]=],
[=[\="%".printf("%02X",char2nr(submatch(0)))]=], [=[\="%".printf("%02X",char2nr(submatch(0)))]=],
'g') 'g'
)
end end
local function expandtabs(s) local function expandtabs(s)
@ -151,7 +150,7 @@ local function fix_url(url)
local removed_chars = '' local removed_chars = ''
local fixed_url = url local fixed_url = url
-- Remove up to one of each char from end of the URL, in this order. -- Remove up to one of each char from end of the URL, in this order.
for _, c in ipairs({ '.', ')', }) do for _, c in ipairs({ '.', ')' }) do
if fixed_url:sub(-1) == c then if fixed_url:sub(-1) == c then
removed_chars = c .. removed_chars removed_chars = c .. removed_chars
fixed_url = fixed_url:sub(1, -2) fixed_url = fixed_url:sub(1, -2)
@ -162,7 +161,7 @@ end
--- Checks if a given line is a "noise" line that doesn't look good in HTML form. --- Checks if a given line is a "noise" line that doesn't look good in HTML form.
local function is_noise(line, noise_lines) local function is_noise(line, noise_lines)
if ( if
-- First line is always noise. -- First line is always noise.
(noise_lines ~= nil and vim.tbl_count(noise_lines) == 0) (noise_lines ~= nil and vim.tbl_count(noise_lines) == 0)
or line:find('Type .*gO.* to see the table of contents') or line:find('Type .*gO.* to see the table of contents')
@ -177,7 +176,7 @@ local function is_noise(line, noise_lines)
or line:find('^%s*vim?%:.*ft=help') or line:find('^%s*vim?%:.*ft=help')
or line:find('^%s*vim?%:.*filetype=help') or line:find('^%s*vim?%:.*filetype=help')
or line:find('[*>]local%-additions[*<]') or line:find('[*>]local%-additions[*<]')
) then then
-- table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0)) -- table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0))
table.insert(noise_lines or {}, line) table.insert(noise_lines or {}, line)
return true return true
@ -188,20 +187,23 @@ end
--- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content. --- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content.
local function get_bug_url_vimdoc(fname, to_fname, sample_text) local function get_bug_url_vimdoc(fname, to_fname, sample_text)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname)) local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
local bug_url = ('https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+' local bug_url = (
'https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+'
.. vim.fs.basename(fname) .. vim.fs.basename(fname)
.. '+&body=Found+%60tree-sitter-vimdoc%60+parse+error+at%3A+' .. '+&body=Found+%60tree-sitter-vimdoc%60+parse+error+at%3A+'
.. this_url .. this_url
.. '%0D%0DContext%3A%0D%0D%60%60%60%0D' .. '%0D%0DContext%3A%0D%0D%60%60%60%0D'
.. url_encode(sample_text) .. url_encode(sample_text)
..'%0D%60%60%60') .. '%0D%60%60%60'
)
return bug_url return bug_url
end end
--- Creates a github issue URL at neovim/neovim with prefilled content. --- Creates a github issue URL at neovim/neovim with prefilled content.
local function get_bug_url_nvim(fname, to_fname, sample_text, token_name) local function get_bug_url_nvim(fname, to_fname, sample_text, token_name)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname)) local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
local bug_url = ('https://github.com/neovim/neovim/issues/new?labels=bug&title=user+docs+HTML%3A+' local bug_url = (
'https://github.com/neovim/neovim/issues/new?labels=bug&title=user+docs+HTML%3A+'
.. vim.fs.basename(fname) .. vim.fs.basename(fname)
.. '+&body=%60gen_help_html.lua%60+problem+at%3A+' .. '+&body=%60gen_help_html.lua%60+problem+at%3A+'
.. this_url .. this_url
@ -209,7 +211,8 @@ local function get_bug_url_nvim(fname, to_fname, sample_text, token_name)
.. (token_name and '+unhandled+token%3A+%60' .. token_name .. '%60' or '') .. (token_name and '+unhandled+token%3A+%60' .. token_name .. '%60' or '')
.. '%0DContext%3A%0D%0D%60%60%60%0D' .. '%0DContext%3A%0D%0D%60%60%60%0D'
.. url_encode(sample_text) .. url_encode(sample_text)
..'%0D%60%60%60') .. '%0D%60%60%60'
)
return bug_url return bug_url
end end
@ -274,7 +277,9 @@ end
local function get_tagname(node, bufnr) local function get_tagname(node, bufnr)
local text = vim.treesitter.get_node_text(node, bufnr) local text = vim.treesitter.get_node_text(node, bufnr)
local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink') and ("'%s'"):format(text) or text local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink')
and ("'%s'"):format(text)
or text
local helpfile = vim.fs.basename(tagmap[tag]) or nil -- "api.txt" local helpfile = vim.fs.basename(tagmap[tag]) or nil -- "api.txt"
local helppage = get_helppage(helpfile) -- "api.html" local helppage = get_helppage(helpfile) -- "api.html"
return helppage, tag return helppage, tag
@ -295,11 +300,9 @@ local function ignore_parse_error(fname, s)
if ignore_errors[vim.fs.basename(fname)] then if ignore_errors[vim.fs.basename(fname)] then
return true return true
end end
return (
-- Ignore parse errors for unclosed tag. -- Ignore parse errors for unclosed tag.
-- This is common in vimdocs and is treated as plaintext by :help. -- This is common in vimdocs and is treated as plaintext by :help.
s:find("^[`'|*]") return s:find("^[`'|*]")
)
end end
local function has_ancestor(node, ancestor_name) local function has_ancestor(node, ancestor_name)
@ -377,7 +380,8 @@ local function visit_validate(root, level, lang_tree, opt, stats)
-- Flatten the sample text to a single, truncated line. -- Flatten the sample text to a single, truncated line.
sample_text = vim.trim(sample_text):gsub('[\t\n]', ' '):sub(1, 80) sample_text = vim.trim(sample_text):gsub('[\t\n]', ' '):sub(1, 80)
table.insert(stats.parse_errors, sample_text) table.insert(stats.parse_errors, sample_text)
elseif (node_name == 'word' or node_name == 'uppercase_name') elseif
(node_name == 'word' or node_name == 'uppercase_name')
and (not vim.tbl_contains({ 'codespan', 'taglink', 'tag' }, parent)) and (not vim.tbl_contains({ 'codespan', 'taglink', 'tag' }, parent))
then then
local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation. local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation.
@ -411,9 +415,15 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
local node_name = (root.named and root:named()) and root:type() or nil local node_name = (root.named and root:named()) and root:type() or nil
-- Previous sibling kind (string). -- Previous sibling kind (string).
local prev = root:prev_sibling() and (root:prev_sibling().named and root:prev_sibling():named()) and root:prev_sibling():type() or nil local prev = root:prev_sibling()
and (root:prev_sibling().named and root:prev_sibling():named())
and root:prev_sibling():type()
or nil
-- Next sibling kind (string). -- Next sibling kind (string).
local next_ = root:next_sibling() and (root:next_sibling().named and root:next_sibling():named()) and root:next_sibling():type() or nil local next_ = root:next_sibling()
and (root:next_sibling().named and root:next_sibling():named())
and root:next_sibling():type()
or nil
-- Parent kind (string). -- Parent kind (string).
local parent = root:parent() and root:parent():type() or nil local parent = root:parent() and root:parent():type() or nil
local text = '' local text = ''
@ -466,11 +476,15 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
-- Use the first *tag* node as the heading anchor, if any. -- Use the first *tag* node as the heading anchor, if any.
local tagnode = first(root, 'tag') local tagnode = first(root, 'tag')
-- Use the *tag* as the heading anchor id, if possible. -- Use the *tag* as the heading anchor id, if possible.
local tagname = tagnode and url_encode(node_text(tagnode:child(1), false)) or to_heading_tag(hname) local tagname = tagnode and url_encode(node_text(tagnode:child(1), false))
or to_heading_tag(hname)
if node_name == 'h1' or #headings == 0 then if node_name == 'h1' or #headings == 0 then
table.insert(headings, { name = hname, subheadings = {}, tag = tagname }) table.insert(headings, { name = hname, subheadings = {}, tag = tagname })
else else
table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, tag = tagname }) table.insert(
headings[#headings].subheadings,
{ name = hname, subheadings = {}, tag = tagname }
)
end end
local el = node_name == 'h1' and 'h2' or 'h3' local el = node_name == 'h1' and 'h2' or 'h3'
return ('<%s id="%s" class="help-heading">%s</%s>\n'):format(el, tagname, text, el) return ('<%s id="%s" class="help-heading">%s</%s>\n'):format(el, tagname, text, el)
@ -490,11 +504,16 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end end
return string.format('<div class="help-para">\n%s\n</div>\n', text) return string.format('<div class="help-para">\n%s\n</div>\n', text)
elseif node_name == 'line' then elseif node_name == 'line' then
if (parent ~= 'codeblock' or parent ~= 'code') and (is_blank(text) or is_noise(text, stats.noise_lines)) then if
(parent ~= 'codeblock' or parent ~= 'code')
and (is_blank(text) or is_noise(text, stats.noise_lines))
then
return '' -- Discard common "noise" lines. return '' -- Discard common "noise" lines.
end end
-- XXX: Avoid newlines (too much whitespace) after block elements in old (preformatted) layout. -- XXX: Avoid newlines (too much whitespace) after block elements in old (preformatted) layout.
local div = opt.old and root:child(0) and vim.list_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type()) local div = opt.old
and root:child(0)
and vim.list_contains({ 'column_heading', 'h1', 'h2', 'h3' }, root:child(0):type())
return string.format('%s%s', div and trim(text) or text, div and '' or '\n') return string.format('%s%s', div and trim(text) or text, div and '' or '\n')
elseif node_name == 'line_li' then elseif node_name == 'line_li' then
local sib = root:prev_sibling() local sib = root:prev_sibling()
@ -520,7 +539,12 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
if ignored then if ignored then
return text return text
end end
local s = ('%s<a href="%s#%s">%s</a>'):format(ws(), helppage, url_encode(tagname), html_esc(tagname)) local s = ('%s<a href="%s#%s">%s</a>'):format(
ws(),
helppage,
url_encode(tagname),
html_esc(tagname)
)
if opt.old and node_name == 'taglink' then if opt.old and node_name == 'taglink' then
s = fix_tab_after_conceal(s, node_text(root:next_sibling())) s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
end end
@ -547,7 +571,10 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end end
local code local code
if language then if language then
code = ('<pre><code class="language-%s">%s</code></pre>'):format(language,trim(trim_indent(text), 2)) code = ('<pre><code class="language-%s">%s</code></pre>'):format(
language,
trim(trim_indent(text), 2)
)
language = nil language = nil
else else
code = ('<pre>%s</pre>'):format(trim(trim_indent(text), 2)) code = ('<pre>%s</pre>'):format(trim(trim_indent(text), 2))
@ -558,7 +585,8 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
return text return text
end end
local in_heading = vim.list_contains({ 'h1', 'h2', 'h3' }, parent) local in_heading = vim.list_contains({ 'h1', 'h2', 'h3' }, parent)
local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right' or 'help-tag' local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right'
or 'help-tag'
local tagname = node_text(root:child(1), false) local tagname = node_text(root:child(1), false)
if vim.tbl_count(stats.first_tags) < 2 then if vim.tbl_count(stats.first_tags) < 2 then
-- Force the first 2 tags in the doc to be anchored at the main heading. -- Force the first 2 tags in the doc to be anchored at the main heading.
@ -567,14 +595,29 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end end
local el = in_heading and 'span' or 'code' local el = in_heading and 'span' or 'code'
local encoded_tagname = url_encode(tagname) local encoded_tagname = url_encode(tagname)
local s = ('%s<%s id="%s" class="%s"><a href="#%s">%s</a></%s>'):format(ws(), el, encoded_tagname, cssclass, encoded_tagname, trimmed, el) local s = ('%s<%s id="%s" class="%s"><a href="#%s">%s</a></%s>'):format(
ws(),
el,
encoded_tagname,
cssclass,
encoded_tagname,
trimmed,
el
)
if opt.old then if opt.old then
s = fix_tab_after_conceal(s, node_text(root:next_sibling())) s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
end end
if in_heading and prev ~= 'tag' then if in_heading and prev ~= 'tag' then
-- Don't set "id", let the heading use the tag as its "id" (used by search engines). -- Don't set "id", let the heading use the tag as its "id" (used by search engines).
s = ('%s<%s class="%s"><a href="#%s">%s</a></%s>'):format(ws(), el, cssclass, encoded_tagname, trimmed, el) s = ('%s<%s class="%s"><a href="#%s">%s</a></%s>'):format(
ws(),
el,
cssclass,
encoded_tagname,
trimmed,
el
)
-- Start the <span> container for tags in a heading. -- Start the <span> container for tags in a heading.
-- This makes "justify-content:space-between" right-align the tags. -- This makes "justify-content:space-between" right-align the tags.
-- <h2>foo bar<span>tag1 tag2</span></h2> -- <h2>foo bar<span>tag1 tag2</span></h2>
@ -593,11 +636,17 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
local sample_text = level > 0 and getbuflinestr(root, opt.buf, 3) or '[top level!]' local sample_text = level > 0 and getbuflinestr(root, opt.buf, 3) or '[top level!]'
table.insert(stats.parse_errors, sample_text) table.insert(stats.parse_errors, sample_text)
return ('<a class="parse-error" target="_blank" title="Report bug... (parse error)" href="%s">%s</a>'):format( return ('<a class="parse-error" target="_blank" title="Report bug... (parse error)" href="%s">%s</a>'):format(
get_bug_url_vimdoc(opt.fname, opt.to_fname, sample_text), trimmed) get_bug_url_vimdoc(opt.fname, opt.to_fname, sample_text),
trimmed
)
else -- Unknown token. else -- Unknown token.
local sample_text = level > 0 and getbuflinestr(root, opt.buf, 3) or '[top level!]' local sample_text = level > 0 and getbuflinestr(root, opt.buf, 3) or '[top level!]'
return ('<a class="unknown-token" target="_blank" title="Report bug... (unhandled token "%s")" href="%s">%s</a>'):format( return ('<a class="unknown-token" target="_blank" title="Report bug... (unhandled token "%s")" href="%s">%s</a>'):format(
node_name, get_bug_url_nvim(opt.fname, opt.to_fname, sample_text, node_name), trimmed), ('unknown-token:"%s"'):format(node_name) node_name,
get_bug_url_nvim(opt.fname, opt.to_fname, sample_text, node_name),
trimmed
),
('unknown-token:"%s"'):format(node_name)
end end
end end
@ -605,9 +654,11 @@ local function get_helpfiles(include)
local dir = './build/runtime/doc' local dir = './build/runtime/doc'
local rv = {} local rv = {}
for f, type in vim.fs.dir(dir) do for f, type in vim.fs.dir(dir) do
if (vim.endswith(f, '.txt') if
vim.endswith(f, '.txt')
and type == 'file' and type == 'file'
and (not include or vim.list_contains(include, f))) then and (not include or vim.list_contains(include, f))
then
local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p') local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p')
table.insert(rv, fullpath) table.insert(rv, fullpath)
end end
@ -671,7 +722,7 @@ local function validate_one(fname, parser_path)
} }
local lang_tree, buf = parse_buf(fname, parser_path) local lang_tree, buf = parse_buf(fname, parser_path)
for _, tree in ipairs(lang_tree:trees()) do for _, tree in ipairs(lang_tree:trees()) do
visit_validate(tree:root(), 0, tree, { buf = buf, fname = fname, }, stats) visit_validate(tree:root(), 0, tree, { buf = buf, fname = fname }, stats)
end end
lang_tree:destroy() lang_tree:destroy()
vim.cmd.close() vim.cmd.close()
@ -777,9 +828,17 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
local main = '' local main = ''
for _, tree in ipairs(lang_tree:trees()) do for _, tree in ipairs(lang_tree:trees()) do
main = main .. (visit_node(tree:root(), 0, tree, headings, main = main
{ buf = buf, old = old, fname = fname, to_fname = to_fname, indent = 1, }, .. (
stats)) visit_node(
tree:root(),
0,
tree,
headings,
{ buf = buf, old = old, fname = fname, to_fname = to_fname, indent = 1 },
stats
)
)
end end
main = ([[ main = ([[
@ -809,7 +868,14 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
<hr/> <hr/>
%s %s
</div> </div>
]]):format(logo_svg, stats.first_tags[2] or '', stats.first_tags[1] or '', title, vim.fs.basename(fname), main) ]]):format(
logo_svg,
stats.first_tags[2] or '',
stats.first_tags[1] or '',
title,
vim.fs.basename(fname),
main
)
local toc = [[ local toc = [[
<div class="col-narrow toc"> <div class="col-narrow toc">
@ -820,12 +886,15 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
]] ]]
local n = 0 -- Count of all headings + subheadings. local n = 0 -- Count of all headings + subheadings.
for _, h1 in ipairs(headings) do n = n + 1 + #h1.subheadings end for _, h1 in ipairs(headings) do
n = n + 1 + #h1.subheadings
end
for _, h1 in ipairs(headings) do for _, h1 in ipairs(headings) do
toc = toc .. ('<div class="help-toc-h1"><a href="#%s">%s</a>\n'):format(h1.tag, h1.name) toc = toc .. ('<div class="help-toc-h1"><a href="#%s">%s</a>\n'):format(h1.tag, h1.name)
if n < 30 or #headings < 10 then -- Show subheadings only if there aren't too many. if n < 30 or #headings < 10 then -- Show subheadings only if there aren't too many.
for _, h2 in ipairs(h1.subheadings) do for _, h2 in ipairs(h1.subheadings) do
toc = toc .. ('<div class="help-toc-h2"><a href="#%s">%s</a></div>\n'):format(h2.tag, h2.name) toc = toc
.. ('<div class="help-toc-h2"><a href="#%s">%s</a></div>\n'):format(h2.tag, h2.name)
end end
end end
toc = toc .. '</div>' toc = toc .. '</div>'
@ -859,11 +928,16 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
</footer> </footer>
]]):format( ]]):format(
os.date('%Y-%m-%d %H:%M'), commit, commit:sub(1, 7), #stats.parse_errors, bug_link, os.date('%Y-%m-%d %H:%M'),
html_esc(table.concat(stats.noise_lines, '\n')), #stats.noise_lines) commit,
commit:sub(1, 7),
#stats.parse_errors,
bug_link,
html_esc(table.concat(stats.noise_lines, '\n')),
#stats.noise_lines
)
html = ('%s%s%s</div>\n%s</body>\n</html>\n'):format( html = ('%s%s%s</div>\n%s</body>\n</html>\n'):format(html, main, toc, footer)
html, main, toc, footer)
vim.cmd('q!') vim.cmd('q!')
lang_tree:destroy() lang_tree:destroy()
return html, stats return html, stats
@ -1038,9 +1112,15 @@ function M._test()
helpfiles = get_helpfiles() helpfiles = get_helpfiles()
local function ok(cond, expected, actual) local function ok(cond, expected, actual)
assert((not expected and not actual) or (expected and actual), 'if "expected" is given, "actual" is also required') assert(
(not expected and not actual) or (expected and actual),
'if "expected" is given, "actual" is also required'
)
if expected then if expected then
return assert(cond, ('expected %s, got: %s'):format(vim.inspect(expected), vim.inspect(actual))) return assert(
cond,
('expected %s, got: %s'):format(vim.inspect(expected), vim.inspect(actual))
)
else else
return assert(cond) return assert(cond)
end end
@ -1050,7 +1130,11 @@ function M._test()
end end
ok(vim.tbl_count(tagmap) > 3000, '>3000', vim.tbl_count(tagmap)) ok(vim.tbl_count(tagmap) > 3000, '>3000', vim.tbl_count(tagmap))
ok(vim.endswith(tagmap['vim.diagnostic.set()'], 'diagnostic.txt'), tagmap['vim.diagnostic.set()'], 'diagnostic.txt') ok(
vim.endswith(tagmap['vim.diagnostic.set()'], 'diagnostic.txt'),
tagmap['vim.diagnostic.set()'],
'diagnostic.txt'
)
ok(vim.endswith(tagmap['%:s'], 'cmdline.txt'), tagmap['%:s'], 'cmdline.txt') ok(vim.endswith(tagmap['%:s'], 'cmdline.txt'), tagmap['%:s'], 'cmdline.txt')
ok(is_noise([[vim:tw=78:isk=!-~,^*,^\|,^\":ts=8:noet:ft=help:norl:]])) ok(is_noise([[vim:tw=78:isk=!-~,^*,^\|,^\":ts=8:noet:ft=help:norl:]]))
ok(is_noise([[ NVIM REFERENCE MANUAL by Thiago de Arruda ]])) ok(is_noise([[ NVIM REFERENCE MANUAL by Thiago de Arruda ]]))
@ -1060,7 +1144,10 @@ function M._test()
eq(1, get_indent(' a')) eq(1, get_indent(' a'))
eq(2, get_indent(' a\n b\n c\n')) eq(2, get_indent(' a\n b\n c\n'))
eq(5, get_indent(' a\n \n b\n c\n d\n e\n')) eq(5, get_indent(' a\n \n b\n c\n d\n e\n'))
eq('a\n \n b\n c\n d\n e\n', trim_indent(' a\n \n b\n c\n d\n e\n')) eq(
'a\n \n b\n c\n d\n e\n',
trim_indent(' a\n \n b\n c\n d\n e\n')
)
local fixed_url, removed_chars = fix_url('https://example.com).') local fixed_url, removed_chars = fix_url('https://example.com).')
eq('https://example.com', fixed_url) eq('https://example.com', fixed_url)
@ -1094,11 +1181,23 @@ end
--- @returns info dict --- @returns info dict
function M.gen(help_dir, to_dir, include, commit, parser_path) function M.gen(help_dir, to_dir, include, commit, parser_path)
vim.validate { vim.validate {
help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'}, help_dir = {
help_dir,
function(d)
return vim.fn.isdirectory(vim.fn.expand(d)) == 1
end,
'valid directory',
},
to_dir = { to_dir, 's' }, to_dir = { to_dir, 's' },
include = { include, 't', true }, include = { include, 't', true },
commit = { commit, 's', true }, commit = { commit, 's', true },
parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'}, parser_path = {
parser_path,
function(f)
return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1
end,
'valid vimdoc.{so,dll} filepath',
},
} }
local err_count = 0 local err_count = 0
@ -1117,7 +1216,13 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
local to_fname = ('%s/%s'):format(to_dir, get_helppage(helpfile)) local to_fname = ('%s/%s'):format(to_dir, get_helppage(helpfile))
local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?', parser_path) local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?', parser_path)
tofile(to_fname, html) tofile(to_fname, html)
print(('generated (%-4s errors): %-15s => %s'):format(#stats.parse_errors, helpfile, vim.fs.basename(to_fname))) print(
('generated (%-4s errors): %-15s => %s'):format(
#stats.parse_errors,
helpfile,
vim.fs.basename(to_fname)
)
)
err_count = err_count + #stats.parse_errors err_count = err_count + #stats.parse_errors
end end
print(('generated %d html pages'):format(#helpfiles)) print(('generated %d html pages'):format(#helpfiles))
@ -1140,9 +1245,21 @@ end
-- @returns results dict -- @returns results dict
function M.validate(help_dir, include, parser_path) function M.validate(help_dir, include, parser_path)
vim.validate { vim.validate {
help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'}, help_dir = {
help_dir,
function(d)
return vim.fn.isdirectory(vim.fn.expand(d)) == 1
end,
'valid directory',
},
include = { include, 't', true }, include = { include, 't', true },
parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'}, parser_path = {
parser_path,
function(f)
return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1
end,
'valid vimdoc.{so,dll} filepath',
},
} }
local err_count = 0 local err_count = 0
local files_to_errors = {} local files_to_errors = {}
@ -1157,7 +1274,9 @@ function M.validate(help_dir, include, parser_path)
print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile)) print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile))
if #rv.parse_errors > 0 then if #rv.parse_errors > 0 then
files_to_errors[helpfile] = rv.parse_errors files_to_errors[helpfile] = rv.parse_errors
vim.print(('%s'):format(vim.iter(rv.parse_errors):fold('', function(s, v) return s..'\n '..v end))) vim.print(('%s'):format(vim.iter(rv.parse_errors):fold('', function(s, v)
return s .. '\n ' .. v
end)))
end end
err_count = err_count + #rv.parse_errors err_count = err_count + #rv.parse_errors
end end

View File

@ -43,14 +43,14 @@ end
local function validate_commit(commit_message) local function validate_commit(commit_message)
-- Return nil if the commit message starts with "fixup" as it signifies it's -- Return nil if the commit message starts with "fixup" as it signifies it's
-- a work in progress and shouldn't be linted yet. -- a work in progress and shouldn't be linted yet.
if vim.startswith(commit_message, "fixup") then if vim.startswith(commit_message, 'fixup') then
return nil return nil
end end
local commit_split = vim.split(commit_message, ":", {plain = true}) local commit_split = vim.split(commit_message, ':', { plain = true })
-- Return nil if the type is vim-patch since most of the normal rules don't -- Return nil if the type is vim-patch since most of the normal rules don't
-- apply. -- apply.
if commit_split[1] == "vim-patch" then if commit_split[1] == 'vim-patch' then
return nil return nil
end end
@ -81,31 +81,33 @@ local function validate_commit(commit_message)
end end
-- Check if commit introduces a breaking change. -- Check if commit introduces a breaking change.
if vim.endswith(before_colon, "!") then if vim.endswith(before_colon, '!') then
before_colon = before_colon:sub(1, -2) before_colon = before_colon:sub(1, -2)
end end
-- Check if type is correct -- Check if type is correct
local type = vim.split(before_colon, "(", {plain = true})[1] local type = vim.split(before_colon, '(', { plain = true })[1]
local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch'} local allowed_types =
{ 'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch' }
if not vim.tbl_contains(allowed_types, type) then if not vim.tbl_contains(allowed_types, type) then
return string.format( return string.format(
[[Invalid commit type "%s". Allowed types are: [[Invalid commit type "%s". Allowed types are:
%s. %s.
If none of these seem appropriate then use "fix"]], If none of these seem appropriate then use "fix"]],
type, type,
vim.inspect(allowed_types)) vim.inspect(allowed_types)
)
end end
-- Check if scope is appropriate -- Check if scope is appropriate
if before_colon:match("%(") then if before_colon:match('%(') then
local scope = vim.trim(commit_message:match("%((.-)%)")) local scope = vim.trim(commit_message:match('%((.-)%)'))
if scope == '' then if scope == '' then
return [[Scope can't be empty]] return [[Scope can't be empty]]
end end
if vim.startswith(scope, "nvim_") then if vim.startswith(scope, 'nvim_') then
return [[Scope should be "api" instead of "nvim_..."]] return [[Scope should be "api" instead of "nvim_..."]]
end end
@ -123,17 +125,17 @@ local function validate_commit(commit_message)
end end
-- Check that description doesn't end with a period -- Check that description doesn't end with a period
if vim.endswith(after_colon, ".") then if vim.endswith(after_colon, '.') then
return [[Description ends with a period (".").]] return [[Description ends with a period (".").]]
end end
-- Check that description starts with a whitespace. -- Check that description starts with a whitespace.
if after_colon:sub(1,1) ~= " " then if after_colon:sub(1, 1) ~= ' ' then
return [[There should be a whitespace after the colon.]] return [[There should be a whitespace after the colon.]]
end end
-- Check that description doesn't start with multiple whitespaces. -- Check that description doesn't start with multiple whitespaces.
if after_colon:sub(1,2) == " " then if after_colon:sub(1, 2) == ' ' then
return [[There should only be one whitespace after the colon.]] return [[There should only be one whitespace after the colon.]]
end end
@ -143,7 +145,7 @@ local function validate_commit(commit_message)
end end
-- Check that description isn't just whitespaces -- Check that description isn't just whitespaces
if vim.trim(after_colon) == "" then if vim.trim(after_colon) == '' then
return [[Description shouldn't be empty.]] return [[Description shouldn't be empty.]]
end end
@ -164,7 +166,7 @@ function M.main(opt)
assert(commits_str) assert(commits_str)
local commits = {} --- @type string[] local commits = {} --- @type string[]
for substring in commits_str:gmatch("%S+") do for substring in commits_str:gmatch('%S+') do
table.insert(commits, substring) table.insert(commits, substring)
end end
@ -183,14 +185,16 @@ function M.main(opt)
p('\n') p('\n')
end end
p(string.format([[ p(string.format(
[[
Invalid commit message: "%s" Invalid commit message: "%s"
Commit: %s Commit: %s
%s %s
]], ]],
msg, msg,
commit_id, commit_id,
invalid_msg)) invalid_msg
))
end end
end end
end end
@ -259,7 +263,7 @@ function M._test()
['feat(:grep/:make)'] = false, ['feat(:grep/:make)'] = false,
['feat(:grep'] = false, ['feat(:grep'] = false,
['feat(:grep/:make'] = false, ['feat(:grep/:make'] = false,
['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false, ["ci: you're saying this commit message just goes on and on and on and on and on and on for way too long?"] = false,
} }
local failed = 0 local failed = 0
@ -267,14 +271,15 @@ function M._test()
local is_valid = (nil == validate_commit(message)) local is_valid = (nil == validate_commit(message))
if is_valid ~= expected then if is_valid ~= expected then
failed = failed + 1 failed = failed + 1
p(string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)) p(
string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)
)
end end
end end
if failed > 0 then if failed > 0 then
os.exit(1) os.exit(1)
end end
end end
--- @class LintcommitOptions --- @class LintcommitOptions

View File

@ -59,9 +59,12 @@ local TAGGED_TYPES = { 'TSNode', 'LanguageTree' }
-- Document these as 'table' -- Document these as 'table'
local ALIAS_TYPES = { local ALIAS_TYPES = {
'Range', 'Range4', 'Range6', 'TSMetadata', 'Range',
'Range4',
'Range6',
'TSMetadata',
'vim.filetype.add.filetypes', 'vim.filetype.add.filetypes',
'vim.filetype.match.args' 'vim.filetype.match.args',
} }
local debug_outfile = nil --- @type string? local debug_outfile = nil --- @type string?
@ -176,9 +179,15 @@ local function process_magic(line, generics)
local magic_split = vim.split(magic, ' ', { plain = true }) local magic_split = vim.split(magic, ' ', { plain = true })
local directive = magic_split[1] local directive = magic_split[1]
if vim.list_contains({ if
'cast', 'diagnostic', 'overload', 'meta', 'type' vim.list_contains({
}, directive) then 'cast',
'diagnostic',
'overload',
'meta',
'type',
}, directive)
then
-- Ignore LSP directives -- Ignore LSP directives
return '// gg:"' .. line .. '"' return '// gg:"' .. line .. '"'
end end
@ -202,8 +211,7 @@ local function process_magic(line, generics)
if directive == 'param' then if directive == 'param' then
for _, type in ipairs(TYPES) do for _, type in ipairs(TYPES) do
magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2') magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2')
magic = magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2')
magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2')
end end
magic_split = vim.split(magic, ' ', { plain = true }) magic_split = vim.split(magic, ' ', { plain = true })
type_index = 3 type_index = 3
@ -245,13 +253,10 @@ local function process_magic(line, generics)
-- surround some types by () -- surround some types by ()
for _, type in ipairs(TYPES) do for _, type in ipairs(TYPES) do
ty = ty ty = ty:gsub('^(' .. type .. '|nil):?$', '(%1)'):gsub('^(' .. type .. '):?$', '(%1)')
:gsub('^(' .. type .. '|nil):?$', '(%1)')
:gsub('^(' .. type .. '):?$', '(%1)')
end end
magic_split[type_index] = ty magic_split[type_index] = ty
end end
magic = table.concat(magic_split, ' ') magic = table.concat(magic_split, ' ')
@ -330,10 +335,7 @@ local function process_function_header(line)
comma = ', ' comma = ', '
end end
fn = fn:sub(1, paren_start) fn = fn:sub(1, paren_start) .. 'self' .. comma .. fn:sub(paren_start + 1)
.. 'self'
.. comma
.. fn:sub(paren_start + 1)
end end
if line:match('local') then if line:match('local') then
@ -418,7 +420,7 @@ local TApp = {
timestamp = os.date('%c %Z', os.time()), timestamp = os.date('%c %Z', os.time()),
name = 'Lua2DoX', name = 'Lua2DoX',
version = '0.2 20130128', version = '0.2 20130128',
copyright = 'Copyright (c) Simon Dales 2012-13' copyright = 'Copyright (c) Simon Dales 2012-13',
} }
setmetatable(TApp, { __index = TApp }) setmetatable(TApp, { __index = TApp })
@ -452,7 +454,10 @@ else -- It's a filter.
if arg[2] == '--outdir' then if arg[2] == '--outdir' then
local outdir = arg[3] local outdir = arg[3]
if type(outdir) ~= 'string' or (0 ~= vim.fn.filereadable(outdir) and 0 == vim.fn.isdirectory(outdir)) then if
type(outdir) ~= 'string'
or (0 ~= vim.fn.filereadable(outdir) and 0 == vim.fn.isdirectory(outdir))
then
error(('invalid --outdir: "%s"'):format(tostring(outdir))) error(('invalid --outdir: "%s"'):format(tostring(outdir)))
end end
vim.fn.mkdir(outdir, 'p') vim.fn.mkdir(outdir, 'p')

View File

@ -16,7 +16,7 @@ local function systemlist(...)
end end
local function vimpatch_sh_list_numbers() local function vimpatch_sh_list_numbers()
return systemlist( { { 'bash', '-c', 'scripts/vim-patch.sh -M', } } ) return systemlist({ { 'bash', '-c', 'scripts/vim-patch.sh -M' } })
end end
-- Generates the lines to be inserted into the src/version.c -- Generates the lines to be inserted into the src/version.c