How do I register custom filetype detection rules in Neovim using Lua without editing filetype.vim?
Answer
vim.filetype.add()
Explanation
vim.filetype.add() is the Neovim Lua API for registering custom filetype detection rules, available since Neovim 0.8. It replaces the traditional approach of creating ~/.vim/ftdetect/ Vimscript files. Rules can match by file extension, exact filename, or full file path pattern — and optionally inspect buffer contents via a callback.
How it works
The function accepts a table with up to three keys:
extension— maps file extensions (without the dot) to filetype namesfilename— maps exact filenames to filetypes (e.g.,Dockerfile.prod)pattern— maps Lua patterns matched against the full file path to filetypes; value can be a string or a function receiving(path, bufnr)
Example
vim.filetype.add({
extension = {
mdx = 'mdx',
tf = 'terraform',
},
filename = {
['.env.local'] = 'sh',
['Brewfile'] = 'ruby',
},
pattern = {
['%.env%.[%w_.-]+$'] = 'sh',
['*/templates/*.html'] = function(path, bufnr)
local firstline = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or ''
if firstline:match('^{%%') then return 'htmldjango' end
return 'html'
end,
},
})
Tips
- Call
vim.filetype.add()early ininit.lua, before anyFileTypeautocmds fire - Verify detection with
:set filetype?after opening a test file - The callback form lets you sniff file contents to distinguish ambiguous types (e.g., Jinja vs plain HTML)
- Neovim checks rules in order:
filenamefirst, thenextension, thenpattern