mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00:00
perf(filetype): optimize internal data structures
This changes the type for the sorted pattern table from `vim.filetype.mapping[]` to `vim.filetype.mapping.sorted[]` E.g. instead of: ```lua { { ['/debian/changelog$'] = {'debchangelog', { parent = '/debian/' } }, { ['%.git/'] = { detect.git , { parent = 'git/', priority = -1 } }, } ``` It is now: ```lua { { '/debian/, '/debian/changelog$', 'debchangelog' }, { 'git/' , '%.git/' , detect.git , -1 }, } ``` Overall this should roughly cut the amount of tables used by 3, and replaces lots of hash indexes with array indexes.
This commit is contained in:
committed by
Lewis Russell
parent
d0e78b5871
commit
ff575b3886
@ -4,15 +4,22 @@ local fn = vim.fn
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
--- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)?
|
--- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)?
|
||||||
--- @alias vim.filetype.mapopts { parent: string, priority: number }
|
--- @alias vim.filetype.mapopts { priority: number }
|
||||||
--- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts]
|
--- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts]
|
||||||
--- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl
|
--- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl
|
||||||
--- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value>
|
--- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value>
|
||||||
|
|
||||||
|
--- @class vim.filetype.mapping.sorted
|
||||||
|
--- @nodoc
|
||||||
|
--- @field [1] string parent pattern
|
||||||
|
--- @field [2] string pattern
|
||||||
|
--- @field [3] string|vim.filetype.mapfn
|
||||||
|
--- @field [4] integer priority
|
||||||
|
|
||||||
--- @param ft string|vim.filetype.mapfn
|
--- @param ft string|vim.filetype.mapfn
|
||||||
--- @param opts? vim.filetype.mapopts
|
--- @param priority? integer
|
||||||
--- @return vim.filetype.maptbl
|
--- @return vim.filetype.maptbl
|
||||||
local function starsetf(ft, opts)
|
local function starsetf(ft, priority)
|
||||||
return {
|
return {
|
||||||
function(path, bufnr)
|
function(path, bufnr)
|
||||||
-- Note: when `ft` is a function its return value may be nil.
|
-- Note: when `ft` is a function its return value may be nil.
|
||||||
@ -27,11 +34,8 @@ local function starsetf(ft, opts)
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
{
|
{
|
||||||
-- Allow setting "parent" to be reused in closures, but don't have default as it will be
|
|
||||||
-- assigned later from grouping
|
|
||||||
parent = opts and opts.parent,
|
|
||||||
-- Starset matches should have lowest priority by default
|
-- Starset matches should have lowest priority by default
|
||||||
priority = (opts and opts.priority) or -math.huge,
|
priority = priority or -math.huge,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -1874,11 +1878,10 @@ local filename = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- Re-use closures as much as possible
|
-- Re-use closures as much as possible
|
||||||
local detect_apache_diretc = starsetf('apache', { parent = '/etc/' })
|
local detect_apache = starsetf('apache')
|
||||||
local detect_apache_dotconf = starsetf('apache', { parent = '%.conf' })
|
local detect_muttrc = starsetf('muttrc')
|
||||||
local detect_muttrc = starsetf('muttrc', { parent = 'utt' })
|
local detect_neomuttrc = starsetf('neomuttrc')
|
||||||
local detect_neomuttrc = starsetf('neomuttrc', { parent = 'utt' })
|
local detect_xkb = starsetf('xkb')
|
||||||
local detect_xkb = starsetf('xkb', { parent = '/usr/' })
|
|
||||||
|
|
||||||
---@type table<string,vim.filetype.mapping>
|
---@type table<string,vim.filetype.mapping>
|
||||||
local pattern = {
|
local pattern = {
|
||||||
@ -1895,14 +1898,14 @@ local pattern = {
|
|||||||
['/etc/asound%.conf$'] = 'alsaconf',
|
['/etc/asound%.conf$'] = 'alsaconf',
|
||||||
['/etc/apache2/sites%-.*/.*%.com$'] = 'apache',
|
['/etc/apache2/sites%-.*/.*%.com$'] = 'apache',
|
||||||
['/etc/httpd/.*%.conf$'] = 'apache',
|
['/etc/httpd/.*%.conf$'] = 'apache',
|
||||||
['/etc/apache2/.*%.conf'] = detect_apache_diretc,
|
['/etc/apache2/.*%.conf'] = detect_apache,
|
||||||
['/etc/apache2/conf%..*/'] = detect_apache_diretc,
|
['/etc/apache2/conf%..*/'] = detect_apache,
|
||||||
['/etc/apache2/mods%-.*/'] = detect_apache_diretc,
|
['/etc/apache2/mods%-.*/'] = detect_apache,
|
||||||
['/etc/apache2/sites%-.*/'] = detect_apache_diretc,
|
['/etc/apache2/sites%-.*/'] = detect_apache,
|
||||||
['/etc/httpd/conf%..*/'] = detect_apache_diretc,
|
['/etc/httpd/conf%..*/'] = detect_apache,
|
||||||
['/etc/httpd/conf%.d/.*%.conf'] = detect_apache_diretc,
|
['/etc/httpd/conf%.d/.*%.conf'] = detect_apache,
|
||||||
['/etc/httpd/mods%-.*/'] = detect_apache_diretc,
|
['/etc/httpd/mods%-.*/'] = detect_apache,
|
||||||
['/etc/httpd/sites%-.*/'] = detect_apache_diretc,
|
['/etc/httpd/sites%-.*/'] = detect_apache,
|
||||||
['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'),
|
['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'),
|
||||||
['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'),
|
['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'),
|
||||||
['/etc/cdrdao%.conf$'] = 'cdrdaoconf',
|
['/etc/cdrdao%.conf$'] = 'cdrdaoconf',
|
||||||
@ -2193,13 +2196,13 @@ local pattern = {
|
|||||||
},
|
},
|
||||||
['%.conf'] = {
|
['%.conf'] = {
|
||||||
['^proftpd%.conf'] = starsetf('apachestyle'),
|
['^proftpd%.conf'] = starsetf('apachestyle'),
|
||||||
['^access%.conf'] = detect_apache_dotconf,
|
['^access%.conf'] = detect_apache,
|
||||||
['^apache%.conf'] = detect_apache_dotconf,
|
['^apache%.conf'] = detect_apache,
|
||||||
['^apache2%.conf'] = detect_apache_dotconf,
|
['^apache2%.conf'] = detect_apache,
|
||||||
['^httpd%.conf'] = detect_apache_dotconf,
|
['^httpd%.conf'] = detect_apache,
|
||||||
['^httpd%-.*%.conf'] = detect_apache_dotconf,
|
['^httpd%-.*%.conf'] = detect_apache,
|
||||||
['^proxy%-html%.conf'] = detect_apache_dotconf,
|
['^proxy%-html%.conf'] = detect_apache,
|
||||||
['^srm%.conf'] = detect_apache_dotconf,
|
['^srm%.conf'] = detect_apache,
|
||||||
['asterisk/.*%.conf'] = starsetf('asterisk'),
|
['asterisk/.*%.conf'] = starsetf('asterisk'),
|
||||||
['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'),
|
['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'),
|
||||||
['^dictd.*%.conf$'] = 'dictdconf',
|
['^dictd.*%.conf$'] = 'dictdconf',
|
||||||
@ -2372,7 +2375,7 @@ local pattern = {
|
|||||||
['/app%-defaults/'] = starsetf('xdefaults'),
|
['/app%-defaults/'] = starsetf('xdefaults'),
|
||||||
['^Xresources'] = starsetf('xdefaults'),
|
['^Xresources'] = starsetf('xdefaults'),
|
||||||
-- Increase priority to run before the pattern below
|
-- Increase priority to run before the pattern below
|
||||||
['^XF86Config%-4'] = starsetf(detect.xfree86_v4, { priority = -math.huge + 1 }),
|
['^XF86Config%-4'] = starsetf(detect.xfree86_v4, -math.huge + 1),
|
||||||
['^XF86Config'] = starsetf(detect.xfree86_v3),
|
['^XF86Config'] = starsetf(detect.xfree86_v3),
|
||||||
['Xmodmap$'] = 'xmodmap',
|
['Xmodmap$'] = 'xmodmap',
|
||||||
['xmodmap'] = starsetf('xmodmap'),
|
['xmodmap'] = starsetf('xmodmap'),
|
||||||
@ -2398,8 +2401,10 @@ local pattern = {
|
|||||||
--- @type table<string,vim.filetype.pattern_cache>
|
--- @type table<string,vim.filetype.pattern_cache>
|
||||||
local pattern_lookup = {}
|
local pattern_lookup = {}
|
||||||
|
|
||||||
|
--- @param a vim.filetype.mapping.sorted
|
||||||
|
--- @param b vim.filetype.mapping.sorted
|
||||||
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[4] > b[4]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param pat string
|
--- @param pat string
|
||||||
@ -2409,30 +2414,30 @@ local function parse_pattern(pat)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- @param t table<string,vim.filetype.mapping>
|
--- @param t table<string,vim.filetype.mapping>
|
||||||
--- @return vim.filetype.mapping[]
|
--- @return vim.filetype.mapping.sorted[]
|
||||||
--- @return vim.filetype.mapping[]
|
--- @return vim.filetype.mapping.sorted[]
|
||||||
local function sort_by_priority(t)
|
local function sort_by_priority(t)
|
||||||
-- Separate patterns with non-negative and negative priority because they
|
-- Separate patterns with non-negative and negative priority because they
|
||||||
-- will be processed separately
|
-- will be processed separately
|
||||||
local pos = {} --- @type vim.filetype.mapping[]
|
local pos = {} --- @type vim.filetype.mapping.sorted[]
|
||||||
local neg = {} --- @type vim.filetype.mapping[]
|
local neg = {} --- @type vim.filetype.mapping.sorted[]
|
||||||
for parent, ft_map in pairs(t) do
|
for parent, ft_map in pairs(t) do
|
||||||
pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent)
|
pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent)
|
||||||
for pat, maptbl in pairs(ft_map) do
|
for pat, maptbl in pairs(ft_map) do
|
||||||
local ft = type(maptbl) == 'table' and maptbl[1] or maptbl
|
local ft_or_fun = type(maptbl) == 'table' and maptbl[1] or maptbl
|
||||||
assert(
|
assert(
|
||||||
type(ft) == 'string' or type(ft) == 'function',
|
type(ft_or_fun) == 'string' or type(ft_or_fun) == 'function',
|
||||||
'Expected string or function for filetype'
|
'Expected string or function for filetype'
|
||||||
)
|
)
|
||||||
|
|
||||||
-- Parse pattern for common data and cache it once
|
-- Parse pattern for common data and cache it once
|
||||||
pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat)
|
pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat)
|
||||||
|
|
||||||
local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or {}
|
--- @type vim.filetype.mapopts?
|
||||||
opts.parent = opts.parent or parent
|
local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or nil
|
||||||
opts.priority = opts.priority or 0
|
local priority = opts and opts.priority or 0
|
||||||
|
|
||||||
table.insert(opts.priority >= 0 and pos or neg, { [pat] = { ft, opts } })
|
table.insert(priority >= 0 and pos or neg, { parent, pat, ft_or_fun, priority })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2643,7 +2648,8 @@ local function match_pattern(name, path, tail, pat, try_all_candidates)
|
|||||||
if some_env_missing then
|
if some_env_missing then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
pat, has_slash = expanded, expanded:find('/') ~= nil
|
pat = expanded
|
||||||
|
has_slash = has_slash or expanded:find('/') ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Try all possible candidates to make parent patterns not depend on slash presence
|
-- Try all possible candidates to make parent patterns not depend on slash presence
|
||||||
@ -2665,14 +2671,13 @@ end
|
|||||||
--- @param name string
|
--- @param name string
|
||||||
--- @param path string
|
--- @param path string
|
||||||
--- @param tail string
|
--- @param tail string
|
||||||
--- @param pattern_sorted vim.filetype.mapping[]
|
--- @param pattern_sorted vim.filetype.mapping.sorted[]
|
||||||
--- @param parent_matches table<string,boolean>
|
--- @param parent_matches table<string,boolean>
|
||||||
--- @param bufnr integer?
|
--- @param bufnr integer?
|
||||||
local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr)
|
local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr)
|
||||||
for i = 1, #pattern_sorted do
|
for _, p in ipairs(pattern_sorted) do
|
||||||
local pat, ft_data = next(pattern_sorted[i])
|
local parent, pat, ft_or_fn = p[1], p[2], p[3]
|
||||||
|
|
||||||
local parent = ft_data[2].parent
|
|
||||||
local parent_is_matched = parent_matches[parent]
|
local parent_is_matched = parent_matches[parent]
|
||||||
if parent_is_matched == nil then
|
if parent_is_matched == nil then
|
||||||
parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil
|
parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil
|
||||||
@ -2682,7 +2687,7 @@ local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_mat
|
|||||||
if parent_is_matched then
|
if parent_is_matched then
|
||||||
local matches = match_pattern(name, path, tail, pat, false)
|
local matches = match_pattern(name, path, tail, pat, false)
|
||||||
if matches then
|
if matches then
|
||||||
local ft, on_detect = dispatch(ft_data[1], path, bufnr, matches)
|
local ft, on_detect = dispatch(ft_or_fn, path, bufnr, matches)
|
||||||
if ft then
|
if ft then
|
||||||
return ft, on_detect
|
return ft, on_detect
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user