vimtricks.wiki Concise Vim tricks, one at a time.

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 names
  • filename — 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 in init.lua, before any FileType autocmds 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: filename first, then extension, then pattern

Next

What is the difference between the inner word (iw) and inner WORD (iW) text objects in Vim?