mirror of
https://github.com/neovim/neovim.git
synced 2024-12-25 13:45:15 -07:00
210 lines
5.7 KiB
Lua
210 lines
5.7 KiB
Lua
|
local do_not_run = true
|
||
|
if do_not_run then
|
||
|
print([[
|
||
|
This script was used to bootstrap the filetype patterns in runtime/lua/vim/filetype.lua. It
|
||
|
should no longer be used except for testing purposes. New filetypes, or changes to existing
|
||
|
filetypes, should be ported manually as part of the vim-patch process.
|
||
|
]])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local filetype_vim = 'runtime/filetype.vim'
|
||
|
local filetype_lua = 'runtime/lua/vim/filetype.lua'
|
||
|
|
||
|
local keywords = {
|
||
|
['for'] = true,
|
||
|
['or'] = true,
|
||
|
['and'] = true,
|
||
|
['end'] = true,
|
||
|
['do'] = true,
|
||
|
['if'] = true,
|
||
|
['while'] = true,
|
||
|
['repeat'] = true,
|
||
|
}
|
||
|
|
||
|
local sections = {
|
||
|
extension = { str = {}, func = {} },
|
||
|
filename = { str = {}, func = {} },
|
||
|
pattern = { str = {}, func = {} },
|
||
|
}
|
||
|
|
||
|
local specialchars = '%*%?\\%$%[%]%{%}'
|
||
|
|
||
|
local function add_pattern(pat, ft)
|
||
|
local ok = true
|
||
|
|
||
|
-- 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
|
||
|
for part in string.gmatch(pat, '[^,]+') do
|
||
|
if not string.find(part, '[' .. specialchars .. ']') then
|
||
|
if type(ft) == 'string' then
|
||
|
sections.filename.str[part] = ft
|
||
|
else
|
||
|
sections.filename.func[part] = ft
|
||
|
end
|
||
|
elseif string.match(part, '^%*%.[^%./' .. specialchars .. ']+$') then
|
||
|
if type(ft) == 'string' then
|
||
|
sections.extension.str[part:sub(3)] = ft
|
||
|
else
|
||
|
sections.extension.func[part:sub(3)] = ft
|
||
|
end
|
||
|
else
|
||
|
if string.match(part, '^%*/[^' .. specialchars .. ']+$') then
|
||
|
-- For patterns matching */some/pattern we want to easily match files
|
||
|
-- with path /some/pattern, so include those in filename detection
|
||
|
if type(ft) == 'string' then
|
||
|
sections.filename.str[part:sub(2)] = ft
|
||
|
else
|
||
|
sections.filename.func[part:sub(2)] = ft
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if string.find(part, '^[%w-_.*?%[%]/]+$') then
|
||
|
local p = part:gsub('%.', '%%.'):gsub('%*', '.*'):gsub('%?', '.')
|
||
|
-- Insert into array to maintain order rather than setting
|
||
|
-- key-value directly
|
||
|
if type(ft) == 'string' then
|
||
|
sections.pattern.str[p] = ft
|
||
|
else
|
||
|
sections.pattern.func[p] = ft
|
||
|
end
|
||
|
else
|
||
|
ok = false
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return ok
|
||
|
end
|
||
|
|
||
|
local function parse_line(line)
|
||
|
local pat, ft
|
||
|
pat, ft = line:match('^%s*au%a* Buf[%a,]+%s+(%S+)%s+setf%s+(%S+)')
|
||
|
if pat then
|
||
|
return add_pattern(pat, ft)
|
||
|
else
|
||
|
local func
|
||
|
pat, func = line:match('^%s*au%a* Buf[%a,]+%s+(%S+)%s+call%s+(%S+)')
|
||
|
if pat then
|
||
|
return add_pattern(pat, function()
|
||
|
return func
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local unparsed = {}
|
||
|
local full_line
|
||
|
for line in io.lines(filetype_vim) do
|
||
|
local cont = string.match(line, '^%s*\\%s*(.*)$')
|
||
|
if cont then
|
||
|
full_line = full_line .. ' ' .. cont
|
||
|
else
|
||
|
if full_line then
|
||
|
if not parse_line(full_line) and string.find(full_line, '^%s*au%a* Buf') then
|
||
|
table.insert(unparsed, full_line)
|
||
|
end
|
||
|
end
|
||
|
full_line = line
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if #unparsed > 0 then
|
||
|
print('Failed to parse the following patterns:')
|
||
|
for _, v in ipairs(unparsed) do
|
||
|
print(v)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function add_item(indent, key, ft)
|
||
|
if type(ft) == 'string' then
|
||
|
if string.find(key, '%A') or keywords[key] then
|
||
|
key = string.format('["%s"]', key)
|
||
|
end
|
||
|
return string.format([[%s%s = "%s",]], indent, key, ft)
|
||
|
elseif type(ft) == 'function' then
|
||
|
local func = ft()
|
||
|
if string.find(key, '%A') or keywords[key] then
|
||
|
key = string.format('["%s"]', key)
|
||
|
end
|
||
|
-- Right now only a single argument is supported, which covers
|
||
|
-- everything in filetype.vim as of this writing
|
||
|
local arg = string.match(func, '%((.*)%)$')
|
||
|
func = string.gsub(func, '%(.*$', '')
|
||
|
if arg == '' then
|
||
|
-- Function with no arguments, call the function directly
|
||
|
return string.format([[%s%s = function() vim.fn["%s"]() end,]], indent, key, func)
|
||
|
elseif string.match(arg, [[^(["']).*%1$]]) then
|
||
|
-- String argument
|
||
|
if func == 's:StarSetf' then
|
||
|
return string.format([[%s%s = starsetf(%s),]], indent, key, arg)
|
||
|
else
|
||
|
return string.format([[%s%s = function() vim.fn["%s"](%s) end,]], indent, key, func, arg)
|
||
|
end
|
||
|
elseif string.find(arg, '%(') then
|
||
|
-- Function argument
|
||
|
return string.format(
|
||
|
[[%s%s = function() vim.fn["%s"](vim.fn.%s) end,]],
|
||
|
indent,
|
||
|
key,
|
||
|
func,
|
||
|
arg
|
||
|
)
|
||
|
else
|
||
|
assert(false, arg)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
do
|
||
|
local lines = {}
|
||
|
local start = false
|
||
|
for line in io.lines(filetype_lua) do
|
||
|
if line:match('^%s+-- END [A-Z]+$') then
|
||
|
start = false
|
||
|
end
|
||
|
|
||
|
if not start then
|
||
|
table.insert(lines, line)
|
||
|
end
|
||
|
|
||
|
local indent, section = line:match('^(%s+)-- BEGIN ([A-Z]+)$')
|
||
|
if section then
|
||
|
start = true
|
||
|
local t = sections[string.lower(section)]
|
||
|
|
||
|
local sorted = {}
|
||
|
for k, v in pairs(t.str) do
|
||
|
table.insert(sorted, { [k] = v })
|
||
|
end
|
||
|
|
||
|
table.sort(sorted, function(a, b)
|
||
|
return a[next(a)] < b[next(b)]
|
||
|
end)
|
||
|
|
||
|
for _, v in ipairs(sorted) do
|
||
|
local k = next(v)
|
||
|
table.insert(lines, add_item(indent, k, v[k]))
|
||
|
end
|
||
|
|
||
|
sorted = {}
|
||
|
for k, v in pairs(t.func) do
|
||
|
table.insert(sorted, { [k] = v })
|
||
|
end
|
||
|
|
||
|
table.sort(sorted, function(a, b)
|
||
|
return next(a) < next(b)
|
||
|
end)
|
||
|
|
||
|
for _, v in ipairs(sorted) do
|
||
|
local k = next(v)
|
||
|
table.insert(lines, add_item(indent, k, v[k]))
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
local f = io.open(filetype_lua, 'w')
|
||
|
f:write(table.concat(lines, '\n') .. '\n')
|
||
|
f:close()
|
||
|
end
|