feat(filetype): add fast option for faster filetype detection

This commit is contained in:
Evgeni Chasnovski 2024-10-31 10:17:41 +02:00
parent 5ead170642
commit c3eb5740ad
No known key found for this signature in database
GPG Key ID: BB32E27DDF942DFB
4 changed files with 59 additions and 6 deletions

View File

@ -2848,6 +2848,10 @@ vim.filetype.match({args}) *vim.filetype.match()*
• {contents}? (`string[]`) An array of lines representing file
contents to use for matching. Can be used with {filename}.
Mutually exclusive with {buf}.
• {fast}? (`boolean`) Whether to skip time consuming detection
steps, like pattern and content matching. Makes detection
significantly faster at the cost of slightly fewer filetypes
detected.
Return (multiple): ~
(`string?`) If a match was found, the matched filetype.

View File

@ -206,6 +206,7 @@ LSP
LUA
• |vim.fs.rm()| can delete files and directories.
• |vim.filetype.match()| now takes `fast` option to perform fast detection.
• |vim.validate()| now has a new signature which uses less tables,
is more peformant and easier to read.
• |vim.str_byteindex()| and |vim.str_utfindex()| gained overload signatures
@ -218,7 +219,7 @@ OPTIONS
PERFORMANCE
TODO
|vim.filetype.match()| overall performance is improved.
PLUGINS

View File

@ -2704,6 +2704,11 @@ end
--- matching. Can be used with {filename}. Mutually exclusive
--- with {buf}.
--- @field contents? string[]
---
--- Whether to skip time consuming detection steps, like
--- pattern and content matching. Makes detection significantly
--- faster at the cost of slightly fewer filetypes detected.
--- @field fast? boolean
--- Perform filetype detection.
---
@ -2750,6 +2755,7 @@ function M.match(args)
local bufnr = args.buf
local name = args.filename
local contents = args.contents
local not_fast = not args.fast
if bufnr and not name then
name = api.nvim_buf_get_name(bufnr)
@ -2778,8 +2784,10 @@ function M.match(args)
-- Next, check the file path against available patterns with non-negative priority
-- Cache match results of all parent patterns to improve performance
local parent_matches = {}
ft, on_detect =
match_pattern_sorted(name, path, tail, pattern_sorted_pos, parent_matches, bufnr)
if not_fast then
ft, on_detect =
match_pattern_sorted(name, path, tail, pattern_sorted_pos, parent_matches, bufnr)
end
if ft then
return ft, on_detect
end
@ -2794,15 +2802,17 @@ function M.match(args)
end
-- Next, check patterns with negative priority
ft, on_detect =
match_pattern_sorted(name, path, tail, pattern_sorted_neg, parent_matches, bufnr)
if not_fast then
ft, on_detect =
match_pattern_sorted(name, path, tail, pattern_sorted_neg, parent_matches, bufnr)
end
if ft then
return ft, on_detect
end
end
-- Finally, check file contents
if contents or bufnr then
if not_fast and (contents or bufnr) then
if contents == nil then
assert(bufnr)
if api.nvim_buf_line_count(bufnr) > 101 then

View File

@ -128,6 +128,44 @@ describe('vim.filetype', function()
)
end)
it('can be fast', function()
eq(
exec_lua(function()
return vim.filetype.match({ filename = 'init.lua', fast = true })
end),
'lua'
)
eq(
exec_lua(function()
return vim.filetype.match({ filename = 'Dockerfile', fast = true })
end),
'dockerfile'
)
-- Pattern and content matching should be skipped
eq(
exec_lua(function()
return {
no_fast = vim.filetype.match({ filename = '/etc/a2ps/top-secret.cfg' }),
yes_fast = vim.filetype.match({ filename = '/etc/a2ps/top-secret.cfg', fast = true }),
}
end),
{ no_fast = 'a2ps', yes_fast = nil }
)
eq(
exec_lua(function()
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, { '" vim' })
return {
no_fast = vim.filetype.match({ buf = buf }),
yes_fast = vim.filetype.match({ buf = buf, fast = true }),
}
end),
{ no_fast = 'vim', yes_fast = nil }
)
end)
it('considers extension mappings when matching from hashbang', function()
eq(
'fooscript',