mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00
perf(filetype): cache (more) pattern data during "add" time
This commit is contained in:
@@ -2218,6 +2218,11 @@ local pattern = {
|
|||||||
-- luacheck: pop
|
-- luacheck: pop
|
||||||
-- luacheck: pop
|
-- luacheck: pop
|
||||||
|
|
||||||
|
--- Lookup table/cache for patterns
|
||||||
|
--- @alias vim.filetype.pattern_cache { fullpat: string, has_env: boolean, has_slash: boolean }
|
||||||
|
--- @type table<string,vim.filetype.pattern_cache>
|
||||||
|
local pattern_lookup = {}
|
||||||
|
|
||||||
local function compare_by_priority(a, b)
|
local function compare_by_priority(a, b)
|
||||||
return a[next(a)][2].priority > b[next(b)][2].priority
|
return a[next(a)][2].priority > b[next(b)][2].priority
|
||||||
end
|
end
|
||||||
@@ -2230,19 +2235,24 @@ local function sort_by_priority(t)
|
|||||||
-- will be processed separately
|
-- will be processed separately
|
||||||
local pos = {} --- @type vim.filetype.mapping[]
|
local pos = {} --- @type vim.filetype.mapping[]
|
||||||
local neg = {} --- @type vim.filetype.mapping[]
|
local neg = {} --- @type vim.filetype.mapping[]
|
||||||
for k, v in pairs(t) do
|
for pat, maptbl in pairs(t) do
|
||||||
local ft = type(v) == 'table' and v[1] or v
|
local ft = type(maptbl) == 'table' and maptbl[1] or maptbl
|
||||||
assert(
|
assert(
|
||||||
type(ft) == 'string' or type(ft) == 'function',
|
type(ft) == 'string' or type(ft) == 'function',
|
||||||
'Expected string or function for filetype'
|
'Expected string or function for filetype'
|
||||||
)
|
)
|
||||||
|
|
||||||
local opts = (type(v) == 'table' and type(v[2]) == 'table') and v[2] or {}
|
-- Parse pattern for common data and cache it once
|
||||||
if not opts.priority then
|
pattern_lookup[pat] = pattern_lookup[pat] or {
|
||||||
opts.priority = 0
|
fullpat = '^' .. pat .. '$',
|
||||||
end
|
has_env = pat:find('%$%b{}') ~= nil,
|
||||||
|
has_slash = pat:find('/') ~= nil,
|
||||||
|
}
|
||||||
|
|
||||||
table.insert(opts.priority >= 0 and pos or neg, { [k] = { ft, opts } })
|
local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or {}
|
||||||
|
opts.priority = opts.priority or 0
|
||||||
|
|
||||||
|
table.insert(opts.priority >= 0 and pos or neg, { [pat] = { ft, opts } })
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(pos, compare_by_priority)
|
table.sort(pos, compare_by_priority)
|
||||||
@@ -2420,23 +2430,19 @@ local function dispatch(ft, path, bufnr, ...)
|
|||||||
return ft0, on_detect
|
return ft0, on_detect
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Lookup table/cache for patterns that contain an environment variable pattern, e.g. ${SOME_VAR}.
|
|
||||||
--- @type table<string,boolean>
|
|
||||||
local expand_env_lookup = {}
|
|
||||||
|
|
||||||
--- @param name string
|
--- @param name string
|
||||||
--- @param path string
|
--- @param path string
|
||||||
--- @param tail string
|
--- @param tail string
|
||||||
--- @param pat string
|
--- @param pat string
|
||||||
--- @return string|false?
|
--- @return string|boolean?
|
||||||
local function match_pattern(name, path, tail, pat)
|
local function match_pattern(name, path, tail, pat)
|
||||||
if expand_env_lookup[pat] == nil then
|
local pat_cache = pattern_lookup[pat]
|
||||||
expand_env_lookup[pat] = pat:find('%${') ~= nil
|
local fullpat, has_slash = pat_cache.fullpat, pat_cache.has_slash
|
||||||
end
|
|
||||||
if expand_env_lookup[pat] then
|
if pat_cache.has_env then
|
||||||
local return_early --- @type true?
|
local return_early --- @type true?
|
||||||
--- @type string
|
--- @type string
|
||||||
pat = pat:gsub('%${(%S-)}', function(env)
|
fullpat = fullpat:gsub('%${(%S-)}', function(env)
|
||||||
-- If an environment variable is present in the pattern but not set, there is no match
|
-- If an environment variable is present in the pattern but not set, there is no match
|
||||||
if not vim.env[env] then
|
if not vim.env[env] then
|
||||||
return_early = true
|
return_early = true
|
||||||
@@ -2447,12 +2453,11 @@ local function match_pattern(name, path, tail, pat)
|
|||||||
if return_early then
|
if return_early then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
has_slash = fullpat:find('/') ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If the pattern contains a / match against the full path, otherwise just the tail
|
-- If the pattern contains a / match against the full path, otherwise just the tail
|
||||||
local fullpat = '^' .. pat .. '$'
|
if has_slash then
|
||||||
|
|
||||||
if pat:find('/') then
|
|
||||||
-- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
|
-- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
|
||||||
-- both the short file name (as typed) and the full file name (after expanding to full path
|
-- both the short file name (as typed) and the full file name (after expanding to full path
|
||||||
-- and resolving symlinks)
|
-- and resolving symlinks)
|
||||||
|
Reference in New Issue
Block a user