aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/filetype.lua
diff options
context:
space:
mode:
authorGregory Anders <8965202+gpanders@users.noreply.github.com>2022-06-09 13:12:36 -0600
committerGitHub <noreply@github.com>2022-06-09 13:12:36 -0600
commit58323b1fe2e494cf6a75f108780e21c08996c08e (patch)
treea301a6d047003efa3835460a793a87d4f205f785 /runtime/lua/vim/filetype.lua
parent28e43881b74b800fa37957e77b5e56994e1120cd (diff)
downloadrneovim-58323b1fe2e494cf6a75f108780e21c08996c08e.tar.gz
rneovim-58323b1fe2e494cf6a75f108780e21c08996c08e.tar.bz2
rneovim-58323b1fe2e494cf6a75f108780e21c08996c08e.zip
feat(filetype): remove side effects from vim.filetype.match (#18894)
Many filetypes from filetype.vim set buffer-local variables, meaning vim.filetype.match cannot be used without side effects. Instead of setting these buffer-local variables in the filetype detection functions themselves, have vim.filetype.match return an optional function value that, when called, sets these variables. This allows vim.filetype.match to work without side effects.
Diffstat (limited to 'runtime/lua/vim/filetype.lua')
-rw-r--r--runtime/lua/vim/filetype.lua127
1 files changed, 79 insertions, 48 deletions
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index c091e2f35c..536580c604 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -26,7 +26,7 @@ end
---@private
local function getline(bufnr, start_lnum, end_lnum)
end_lnum = end_lnum or start_lnum
- local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
+ local lines = api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
return table.concat(lines) or ''
end
@@ -40,9 +40,9 @@ end
function M.getlines(bufnr, start_lnum, end_lnum)
if not end_lnum then
-- Return a single line as a string
- return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1]
+ return api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1]
end
- return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
+ return api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
end
---@private
@@ -1513,12 +1513,14 @@ local filename = {
['/.pinforc'] = 'pinfo',
['.povrayrc'] = 'povini',
['printcap'] = function(path, bufnr)
- vim.b[bufnr].ptcap_type = 'print'
- return 'ptcap'
+ return 'ptcap', function(b)
+ vim.b[b].ptcap_type = 'print'
+ end
end,
['termcap'] = function(path, bufnr)
- vim.b[bufnr].ptcap_type = 'term'
- return 'ptcap'
+ return 'ptcap', function(b)
+ vim.b[b].ptcap_type = 'term'
+ end
end,
['.procmailrc'] = 'procmail',
['.procmail'] = 'procmail',
@@ -1604,12 +1606,14 @@ local filename = {
['xdm-config'] = 'xdefaults',
['.Xdefaults'] = 'xdefaults',
['xorg.conf'] = function(path, bufnr)
- vim.b[bufnr].xf86conf_xfree86_version = 4
- return 'xf86conf'
+ return 'xf86conf', function(b)
+ vim.b[b].xf86conf_xfree86_version = 4
+ end
end,
['xorg.conf-4'] = function(path, bufnr)
- vim.b[bufnr].xf86conf_xfree86_version = 4
- return 'xf86conf'
+ return 'xf86conf', function(b)
+ vim.b[b].xf86conf_xfree86_version = 4
+ end
end,
['/etc/xinetd.conf'] = 'xinetd',
fglrxrc = 'xml',
@@ -1662,7 +1666,7 @@ local filename = {
bashrc = function(path, bufnr)
return require('vim.filetype.detect').sh(path, bufnr, 'bash')
end,
- crontab = starsetf('crontab'),
+ crontab = 'crontab',
['csh.cshrc'] = function(path, bufnr)
return require('vim.filetype.detect').csh(path, bufnr)
end,
@@ -1682,7 +1686,7 @@ local filename = {
return require('vim.filetype.detect').shell(path, bufnr, 'tcsh')
end,
['XF86Config'] = function(path, bufnr)
- return require('vim.filetype.detect').xf86conf(bufnr)
+ return require('vim.filetype.detect').xfree86(bufnr)
end,
-- END FILENAME
}
@@ -1830,8 +1834,9 @@ local pattern = {
['.*/etc/protocols'] = 'protocols',
['.*printcap.*'] = starsetf(function(path, bufnr)
if vim.fn.did_filetype() == 0 then
- vim.b[bufnr].ptcap_type = 'print'
- return 'ptcap'
+ return 'ptcap', function(b)
+ vim.b[b].ptcap_type = 'print'
+ end
end
end),
['.*baseq[2-3]/.*%.cfg'] = 'quake',
@@ -1881,8 +1886,9 @@ local pattern = {
['.*/%.config/systemd/user/%.#.*'] = 'systemd',
['.*termcap.*'] = starsetf(function(path, bufnr)
if vim.fn.did_filetype() == 0 then
- vim.b[bufnr].ptcap_type = 'term'
- return 'ptcap'
+ return 'ptcap', function(b)
+ vim.b[b].ptcap_type = 'term'
+ end
end
end),
['.*%.t%.html'] = 'tilde',
@@ -1966,12 +1972,14 @@ local pattern = {
['.*%.vhdl_[0-9].*'] = starsetf('vhdl'),
['.*/%.fvwm/.*'] = starsetf('fvwm'),
['.*fvwmrc.*'] = starsetf(function(path, bufnr)
- vim.b[bufnr].fvwm_version = 1
- return 'fvwm'
+ return 'fvwm', function(b)
+ vim.b[b].fvwm_version = 1
+ end
end),
['.*fvwm95.*%.hook'] = starsetf(function(path, bufnr)
- vim.b[bufnr].fvwm_version = 1
- return 'fvwm'
+ return 'fvwm', function(b)
+ vim.b[b].fvwm_version = 1
+ end
end),
['.*/%.gitconfig%.d/.*'] = starsetf('gitconfig'),
['.*/Xresources/.*'] = starsetf('xdefaults'),
@@ -2117,17 +2125,18 @@ local pattern = {
['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries
['.*,v'] = 'rcs',
['.*/xorg%.conf%.d/.*%.conf'] = function(path, bufnr)
- vim.b[bufnr].xf86conf_xfree86_version = 4
- return 'xf86config'
+ return 'xf86config', function(b)
+ vim.b[b].xf86conf_xfree86_version = 4
+ end
end,
-- Increase priority to run before the pattern below
- ['XF86Config%-4'] = starsetf(function(path, bufnr)
- vim.b[bufnr].xf86conf_xfree86_version = 4
- return 'xf86config'
+ ['XF86Config%-4.*'] = starsetf(function(path, bufnr)
+ return 'xf86conf', function(b)
+ vim.b[b].xf86conf_xfree86_version = 4
+ end
end, { priority = -math.huge + 1 }),
['XF86Config.*'] = starsetf(function(path, bufnr)
- vim.b[bufnr].xf86conf_xfree86_version = 4
- return require('vim.filetype.detect').xf86conf(bufnr)
+ return require('vim.filetype.detect').xfree86(bufnr)
end),
['[cC]hange[lL]og.*'] = starsetf(function(path, bufnr)
local line = getline(bufnr, 1):lower()
@@ -2141,8 +2150,9 @@ local pattern = {
if vim.fn.fnamemodify(path, ':e') == 'm4' then
return 'fvwm2m4'
else
- vim.b[bufnr].fvwm_version = 2
- return 'fvwm'
+ return 'fvwm', function(b)
+ vim.b[b].fvwm_version = 2
+ end
end
end),
['.*%.[Ll][Oo][Gg]'] = function(path, bufnr)
@@ -2220,7 +2230,9 @@ end
--- filetype directly) or a function. If a function, it takes the full path and
--- buffer number of the file as arguments (along with captures from the matched
--- pattern, if any) and should return a string that will be used as the
---- buffer's filetype.
+--- buffer's filetype. Optionally, the function can return a second function
+--- value which, when called, modifies the state of the buffer. This can be used
+--- to, for example, set filetype-specific buffer variables.
---
--- Filename patterns can specify an optional priority to resolve cases when a
--- file path matches multiple patterns. Higher priorities are matched first.
@@ -2238,7 +2250,10 @@ end
--- foo = "fooscript",
--- bar = function(path, bufnr)
--- if some_condition() then
---- return "barscript"
+--- return "barscript", function(bufnr)
+--- -- Set a buffer variable
+--- vim.b[bufnr].barscript_version = 2
+--- end
--- end
--- return "bar"
--- end,
@@ -2283,13 +2298,13 @@ end
---@private
local function dispatch(ft, path, bufnr, ...)
+ local on_detect
if type(ft) == 'function' then
- ft = ft(path, bufnr, ...)
+ ft, on_detect = ft(path, bufnr, ...)
end
if type(ft) == 'string' then
- api.nvim_buf_set_option(bufnr, 'filetype', ft)
- return true
+ return ft, on_detect
end
-- Any non-falsey value (that is, anything other than 'nil' or 'false') will
@@ -2314,11 +2329,20 @@ local function match_pattern(name, path, tail, pat)
return matches
end
---- Set the filetype for the given buffer from a file name.
+--- Find the filetype for the given filename and buffer.
---
---@param name string File name (can be an absolute or relative path)
---@param bufnr number|nil The buffer to set the filetype for. Defaults to the current buffer.
+---@return string|nil If a match was found, the matched filetype.
+---@return function|nil A function that modifies buffer state when called (for example, to set some
+--- filetype specific buffer variables). The function accepts a buffer number as
+--- its only argument.
function M.match(name, bufnr)
+ vim.validate({
+ name = { name, 's' },
+ bufnr = { bufnr, 'n', true },
+ })
+
-- When fired from the main filetypedetect autocommand the {bufnr} argument is omitted, so we use
-- the current buffer. The {bufnr} argument is provided to allow extensibility in case callers
-- wish to perform filetype detection on buffers other than the current one.
@@ -2326,16 +2350,20 @@ function M.match(name, bufnr)
name = normalize_path(name)
+ local ft, on_detect
+
-- First check for the simple case where the full path exists as a key
local path = vim.fn.resolve(vim.fn.fnamemodify(name, ':p'))
- if dispatch(filename[path], path, bufnr) then
- return
+ ft, on_detect = dispatch(filename[path], path, bufnr)
+ if ft then
+ return ft, on_detect
end
-- Next check against just the file name
local tail = vim.fn.fnamemodify(name, ':t')
- if dispatch(filename[tail], path, bufnr) then
- return
+ ft, on_detect = dispatch(filename[tail], path, bufnr)
+ if ft then
+ return ft, on_detect
end
-- Next, check the file path against available patterns with non-negative priority
@@ -2348,19 +2376,21 @@ function M.match(name, bufnr)
break
end
- local ft = v[k][1]
+ local filetype = v[k][1]
local matches = match_pattern(name, path, tail, k)
if matches then
- if dispatch(ft, path, bufnr, matches) then
- return
+ ft, on_detect = dispatch(filetype, path, bufnr, matches)
+ if ft then
+ return ft, on_detect
end
end
end
-- Next, check file extension
local ext = vim.fn.fnamemodify(name, ':e')
- if dispatch(extension[ext], path, bufnr) then
- return
+ ft, on_detect = dispatch(extension[ext], path, bufnr)
+ if ft then
+ return ft, on_detect
end
-- Finally, check patterns with negative priority
@@ -2368,11 +2398,12 @@ function M.match(name, bufnr)
local v = pattern_sorted[i]
local k = next(v)
- local ft = v[k][1]
+ local filetype = v[k][1]
local matches = match_pattern(name, path, tail, k)
if matches then
- if dispatch(ft, path, bufnr, matches) then
- return
+ ft, on_detect = dispatch(filetype, path, bufnr, matches)
+ if ft then
+ return ft, on_detect
end
end
end