317 lines
7.5 KiB
Lua
Executable File
317 lines
7.5 KiB
Lua
Executable File
#!/bin/sh
|
|
_=[[
|
|
exec nvim -l "$0" "$@"
|
|
]]
|
|
-- Simple script to update the help doc by reading the config schema.
|
|
|
|
local inspect = vim.inspect
|
|
local config = require('lua.gitsigns.config')
|
|
|
|
function table.slice(tbl, first, last, step)
|
|
local sliced = {}
|
|
for i = first or 1, last or #tbl, step or 1 do
|
|
sliced[#sliced+1] = tbl[i]
|
|
end
|
|
return sliced
|
|
end
|
|
|
|
local function startswith(str, start)
|
|
return str.sub(str, 1, string.len(start)) == start
|
|
end
|
|
|
|
local function read_file(path)
|
|
local f = assert(io.open(path, 'r'))
|
|
local t = f:read("*all")
|
|
f:close()
|
|
return t
|
|
end
|
|
|
|
-- To make sure the output is consistent between runs (to minimise diffs), we
|
|
-- need to iterate through the schema keys in a deterministic way. To do this we
|
|
-- do a smple scan over the file the schema is defined in and collect the keys
|
|
-- in the order they are defined.
|
|
--- @return string[]
|
|
local function get_ordered_schema_keys()
|
|
local c = read_file('lua/gitsigns/config.lua')
|
|
|
|
local ci = c:gmatch("[^\n\r]+")
|
|
|
|
for l in ci do
|
|
if startswith(l, 'M.schema = {') then
|
|
break
|
|
end
|
|
end
|
|
|
|
local keys = {}
|
|
for l in ci do
|
|
if startswith(l, '}') then
|
|
break
|
|
end
|
|
if l:find('^ (%w+).*') then
|
|
local lc = l:gsub('^%s*([%w_]+).*', '%1')
|
|
table.insert(keys, lc)
|
|
end
|
|
end
|
|
|
|
return keys
|
|
end
|
|
|
|
local function gen_config_doc_deprecated(dep_info, out)
|
|
if type(dep_info) == 'table' and dep_info.hard then
|
|
out(' HARD-DEPRECATED')
|
|
else
|
|
out(' DEPRECATED')
|
|
end
|
|
if type(dep_info) == 'table' then
|
|
if dep_info.message then
|
|
out(' '..dep_info.message)
|
|
end
|
|
if dep_info.new_field then
|
|
out('')
|
|
local opts_key, field = dep_info.new_field:match('(.*)%.(.*)')
|
|
if opts_key and field then
|
|
out((' Please instead use the field `%s` in |gitsigns-config-%s|.'):format(field, opts_key))
|
|
else
|
|
out((' Please instead use |gitsigns-config-%s|.'):format(dep_info.new_field))
|
|
end
|
|
end
|
|
end
|
|
out('')
|
|
end
|
|
|
|
local function gen_config_doc_field(field, out)
|
|
local v = config.schema[field]
|
|
|
|
-- Field heading and tag
|
|
local t = ('*gitsigns-config-%s*'):format(field)
|
|
if #field + #t < 80 then
|
|
out(('%-29s %48s'):format(field, t))
|
|
else
|
|
out(('%-29s'):format(field))
|
|
out(('%78s'):format(t))
|
|
end
|
|
|
|
if v.deprecated then
|
|
gen_config_doc_deprecated(v.deprecated, out)
|
|
end
|
|
|
|
if v.description then
|
|
local d --- @type string
|
|
if v.default_help ~= nil then
|
|
d = v.default_help
|
|
else
|
|
d = inspect(v.default):gsub('\n', '\n ')
|
|
d = ('`%s`'):format(d)
|
|
end
|
|
|
|
local vtype = (function()
|
|
if v.type == 'table' and v.deep_extend then
|
|
return 'table[extended]'
|
|
end
|
|
if type(v.type) == 'table' then
|
|
v.type = table.concat(v.type, '|')
|
|
end
|
|
return v.type
|
|
end)()
|
|
|
|
if d:find('\n') then
|
|
out((' Type: `%s`'):format(vtype))
|
|
out(' Default: >')
|
|
out(' '..d:gsub('\n([^\n\r])', '\n %1'))
|
|
out('<')
|
|
else
|
|
out((' Type: `%s`, Default: %s'):format(vtype, d))
|
|
out()
|
|
end
|
|
|
|
out(v.description:gsub(' +$', ''))
|
|
end
|
|
end
|
|
|
|
--- @return string
|
|
local function gen_config_doc()
|
|
local res = {} ---@type string[]
|
|
local function out(line)
|
|
res[#res+1] = line or ''
|
|
end
|
|
for _, k in ipairs(get_ordered_schema_keys()) do
|
|
gen_config_doc_field(k, out)
|
|
end
|
|
return table.concat(res, '\n')
|
|
end
|
|
|
|
--- @param line string
|
|
--- @return string
|
|
local function parse_func_header(line)
|
|
local func = line:match('%w+%.([%w_]+)')
|
|
if not func then
|
|
error('Unable to parse: '..line)
|
|
end
|
|
local args_raw =
|
|
line:match('function%((.*)%)') or -- M.name = function(args)
|
|
line:match('function%s+%w+%.[%w_]+%((.*)%)') -- function M.name(args)
|
|
local args = {}
|
|
for k in string.gmatch(args_raw, "([%w_]+)") do
|
|
if k:sub(1, 1) ~= '_' then
|
|
args[#args+1] = string.format('{%s}', k)
|
|
end
|
|
end
|
|
return string.format(
|
|
'%-40s%38s',
|
|
string.format('%s(%s)', func, table.concat(args, ', ')),
|
|
'*gitsigns.'..func..'()*'
|
|
)
|
|
end
|
|
|
|
--- @param path string
|
|
--- @return string
|
|
local function gen_functions_doc_from_file(path)
|
|
local i = read_file(path):gmatch("([^\n]*)\n?")
|
|
|
|
local res = {}
|
|
local blocks = {}
|
|
local block = {''}
|
|
|
|
local in_block = false
|
|
for l in i do
|
|
local l1 = l:match('^%-%-%- ?(.*)')
|
|
if l1 then
|
|
in_block = true
|
|
if l1 ~= '' and l1 ~= '<' then
|
|
l1 = ' '..l1
|
|
end
|
|
block[#block+1] = l1
|
|
else
|
|
if in_block then
|
|
-- First line after block
|
|
local ok, header = pcall(parse_func_header, l)
|
|
if ok then
|
|
block[1] = header
|
|
blocks[#blocks+1] = block
|
|
end
|
|
block = {''}
|
|
end
|
|
in_block = false
|
|
end
|
|
end
|
|
|
|
for j = #blocks, 1, -1 do
|
|
local b = blocks[j]
|
|
for k = 1, #b do
|
|
res[#res+1] = b[k]
|
|
end
|
|
res[#res+1] = ''
|
|
end
|
|
|
|
return table.concat(res, '\n')
|
|
end
|
|
|
|
--- @param files string[]
|
|
--- @return string
|
|
local function gen_functions_doc(files)
|
|
local res = ''
|
|
for _, path in ipairs(files) do
|
|
res = res..'\n'..gen_functions_doc_from_file(path)
|
|
end
|
|
return res
|
|
end
|
|
|
|
--- @return string
|
|
local function gen_highlights_doc()
|
|
local res = {} --- @type string[]
|
|
local highlights = require('lua.gitsigns.highlight')
|
|
|
|
local name_max = 0
|
|
for _, hl in ipairs(highlights.hls) do
|
|
for name, _ in pairs(hl) do
|
|
if name:len() > name_max then
|
|
name_max = name:len()
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, hl in ipairs(highlights.hls) do
|
|
for name, spec in pairs(hl) do
|
|
if not spec.hidden then
|
|
local fallbacks_tbl = {} --- @type string[]
|
|
for _, f in ipairs(spec) do
|
|
fallbacks_tbl[#fallbacks_tbl+1] = string.format('`%s`', f)
|
|
end
|
|
local fallbacks = table.concat(fallbacks_tbl, ', ')
|
|
res[#res+1] = string.format('%s*hl-%s*', string.rep(' ', 56), name)
|
|
res[#res+1] = string.format('%s', name)
|
|
if spec.desc then
|
|
res[#res+1] = string.format('%s%s', string.rep(' ', 8), spec.desc)
|
|
res[#res+1] = ''
|
|
end
|
|
res[#res+1] = string.format('%sFallbacks: %s', string.rep(' ', 8), fallbacks)
|
|
end
|
|
end
|
|
end
|
|
|
|
return table.concat(res, '\n')
|
|
end
|
|
|
|
--- @return string
|
|
local function get_setup_from_readme()
|
|
local i = read_file('README.md'):gmatch("([^\n]*)\n?")
|
|
local res = {} --- @type string[]
|
|
local function append(line)
|
|
res[#res+1] = line ~= '' and ' '..line or ''
|
|
end
|
|
for l in i do
|
|
if l:match("require%('gitsigns'%).setup {") then
|
|
append(l)
|
|
break
|
|
end
|
|
end
|
|
|
|
for l in i do
|
|
append(l)
|
|
if l == '}' then
|
|
break
|
|
end
|
|
end
|
|
|
|
return table.concat(res, '\n')
|
|
end
|
|
|
|
local function get_marker_text(marker)
|
|
return ({
|
|
VERSION = '0.7-dev',
|
|
CONFIG = function() return gen_config_doc() end,
|
|
FUNCTIONS = function()
|
|
return gen_functions_doc{
|
|
'lua/gitsigns.lua',
|
|
'lua/gitsigns/attach.lua',
|
|
'lua/gitsigns/actions.lua',
|
|
}
|
|
end,
|
|
HIGHLIGHTS = function() return gen_highlights_doc() end,
|
|
SETUP = function() return get_setup_from_readme() end,
|
|
})[marker]
|
|
end
|
|
|
|
local function main()
|
|
local i = read_file('etc/doc_template.txt'):gmatch("([^\n]*)\n?")
|
|
|
|
local out = io.open('doc/gitsigns.txt', 'w')
|
|
|
|
for l in i do
|
|
local marker = l:match('{{(.*)}}')
|
|
if marker then
|
|
local sub = get_marker_text(marker)
|
|
if sub then
|
|
if type(sub) == 'function' then
|
|
sub = sub()
|
|
end
|
|
sub = sub:gsub('%%', '%%%%')
|
|
l = l:gsub('{{'..marker..'}}', sub)
|
|
end
|
|
end
|
|
out:write(l or '', '\n')
|
|
end
|
|
end
|
|
|
|
main()
|