Home

Awesome

This plugin is no longer needed as the optimization has been merged into Neovim core. It is only here for archival purposes.

filetype.nvim

Easily speed up your neovim startup time!

What does this do?

This plugin is a replacement for the included filetype.vim that is sourced on startup. The purpose of that file is to create a series of autocommands that set the filetype variable depending on the filename. The issue is that creating autocommands have significant overhead, and creating 800+ of them as filetype.vim does is a very inefficient way to get the job done.

As you can see, filetype.vim is by far the heaviest nvim runtime file

13.782    [runtime] 
-	9.144     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/filetype.vim
	1.662     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/matchit.vim
	0.459     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/synload.vim
	0.388     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/netrwPlugin.vim
	0.334     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/gzip.vim
	0.251     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/rplugin.vim
	0.248     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/syntax.vim
	0.216     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tarPlugin.vim
	0.205     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/zipPlugin.vim
	0.186     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/syncolor.vim
	0.173     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/matchparen.vim
	0.123     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/shada.vim
	0.114     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tohtml.vim
	0.075     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/man.vim
	0.056     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/ftplugin.vim
	0.048     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/indent.vim
	0.039     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/spellfile.vim
	0.038     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tutor.vim
	0.022     /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/health.vim

filetype.nvim fixes the issue by only creating a single autocommand that resolves the file type when a buffer is opened. This method is ~175x faster*!

Usage

First, install using your favorite package manager. Using packer:

use("nathom/filetype.nvim")

If using a Neovim version earlier than 0.6.0, add the following to init.lua

-- Do not source the default filetype.vim
vim.g.did_load_filetypes = 1

That's it! You should now have a much snappier neovim experience!

Customization

filetype.nvim allows you to easily add custom filetypes using the setup function. Here's an example:

-- In init.lua or filetype.nvim's config file
require("filetype").setup({
    overrides = {
        extensions = {
            -- Set the filetype of *.pn files to potion
            pn = "potion",
        },
        literal = {
            -- Set the filetype of files named "MyBackupFile" to lua
            MyBackupFile = "lua",
        },
        complex = {
            -- Set the filetype of any full filename matching the regex to gitconfig
            [".*git/config"] = "gitconfig", -- Included in the plugin
        },

        -- The same as the ones above except the keys map to functions
        function_extensions = {
            ["cpp"] = function()
                vim.bo.filetype = "cpp"
                -- Remove annoying indent jumping
                vim.bo.cinoptions = vim.bo.cinoptions .. "L0"
            end,
            ["pdf"] = function()
                vim.bo.filetype = "pdf"
                -- Open in PDF viewer (Skim.app) automatically
                vim.fn.jobstart(
                    "open -a skim " .. '"' .. vim.fn.expand("%") .. '"'
                )
            end,
        },
        function_literal = {
            Brewfile = function()
                vim.cmd("syntax off")
            end,
        },
        function_complex = {
            ["*.math_notes/%w+"] = function()
                vim.cmd("iabbrev $ $$")
            end,
        },

        shebang = {
            -- Set the filetype of files with a dash shebang to sh
            dash = "sh",
        },
    },
})

The extensions and literal tables are orders faster than the other ones because they only require a table lookup. Always try to use these before resorting to the complex tables, which require looping over the entries and running a regex for each one.

Performance Comparison

These were measured using startuptime.vim

Without filetype.nvim

Average startup time (100 rounds): 36.410 ms

<details> <summary>Sample log</summary>
times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.008  000.008: --- NVIM STARTING ---
000.827  000.819: locale set
001.304  000.477: inits 1
001.358  000.054: window checked
001.369  000.011: parsing arguments
002.537  001.168: expanding arguments
002.626  000.089: inits 2
002.998  000.372: init highlight
012.731  000.961  000.961: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/vim-gruvbox8/colors/gruvbox8.vim
012.829  009.549  008.588: sourcing /Users/nathan/.config/nvim/init.lua
012.837  000.290: sourcing vimrc file(s)
019.775  000.035  000.035: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/elixir.vim
019.867  000.026  000.026: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/fish.vim
019.949  000.022  000.022: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gdresource.vim
020.025  000.017  000.017: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gdscript.vim
020.108  000.018  000.018: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gomod.vim
020.194  000.029  000.029: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/graphql.vim
020.280  000.029  000.029: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/hcl.vim
020.358  000.021  000.021: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/heex.vim
020.436  000.021  000.021: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/json5.vim
020.517  000.024  000.024: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/julia.vim
020.601  000.028  000.028: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/ledger.vim
020.680  000.022  000.022: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/nix.vim
020.764  000.028  000.028: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/ql.vim
020.851  000.031  000.031: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/query.vim
020.933  000.025  000.025: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/surface.vim
021.127  000.031  000.031: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/teal.vim
021.218  000.025  000.025: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/tlaplus.vim
021.301  000.023  000.023: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/yang.vim
021.382  000.023  000.023: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/zig.vim
- 022.213  009.200  008.722: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/filetype.vim
022.820  000.046  000.046: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/ftplugin.vim
023.350  000.042  000.042: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/indent.vim
025.075  000.180  000.180: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/syncolor.vim
026.263  001.786  001.606: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/vim-gruvbox8/colors/gruvbox8.vim
026.338  002.204  000.418: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/synload.vim
026.432  002.447  000.243: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/syntax.vim
030.711  000.317  000.317: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/gzip.vim
030.810  000.021  000.021: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/health.vim
030.951  000.074  000.074: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/man.vim
032.470  000.187  000.187: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/pack/dist/opt/matchit/plugin/matchit.vim
032.781  001.760  001.573: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/matchit.vim
033.095  000.240  000.240: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/matchparen.vim
033.539  000.364  000.364: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/netrwPlugin.vim
033.873  000.021  000.021: sourcing /Users/nathan/.local/share/nvim/rplugin.vim
033.883  000.251  000.231: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/rplugin.vim
034.065  000.106  000.106: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/shada.vim
034.185  000.036  000.036: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/spellfile.vim
034.472  000.205  000.205: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tarPlugin.vim
034.664  000.104  000.104: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tohtml.vim
034.781  000.034  000.034: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tutor.vim
035.048  000.178  000.178: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/zipPlugin.vim
042.395  000.030  000.030: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/opt/vim-markdown/ftdetect/markdown.vim
042.409  007.066  007.036: sourcing /Users/nathan/.config/nvim/plugin/packer_compiled.lua
043.195  007.867: loading plugins
043.813  000.037  000.037: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/easy-replace.nvim/plugin/easy_replace.vim
044.564  000.032  000.032: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-bqf/plugin/bqf.vim
046.955  001.984  001.984: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/plugin/nvim-treesitter.vim
047.595  000.050  000.050: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/elixir.vim
047.693  000.030  000.030: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/fish.vim
047.851  000.092  000.092: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gdresource.vim
047.978  000.026  000.026: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gdscript.vim
048.082  000.026  000.026: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gomod.vim
048.183  000.031  000.031: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/graphql.vim
048.284  000.031  000.031: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/hcl.vim
048.378  000.024  000.024: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/heex.vim
048.470  000.023  000.023: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/json5.vim
048.562  000.022  000.022: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/julia.vim
048.659  000.027  000.027: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/ledger.vim
048.749  000.021  000.021: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/nix.vim
048.842  000.024  000.024: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/ql.vim
048.943  000.032  000.032: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/query.vim
049.035  000.019  000.019: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/surface.vim
049.115  000.018  000.018: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/teal.vim
049.197  000.017  000.017: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/tlaplus.vim
049.276  000.017  000.017: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/yang.vim
049.390  000.017  000.017: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/zig.vim
049.772  000.047  000.047: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-web-devicons/plugin/nvim-web-devicons.vim
050.319  000.043  000.043: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/plenary.nvim/plugin/plenary.vim
051.424  000.301  000.301: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/vim-rooter/plugin/rooter.vim
051.751  005.565: loading packages
052.307  000.556: loading after plugins
052.316  000.010: inits 3
052.328  000.012: clearing screen
054.268  001.940: opening buffers
054.539  000.271: BufEnter autocommands
- 054.542  000.003: editing files in windows
</details>

With filetype.nvim

Average startup time (100 rounds): 26.492 ms

<details> <summary>Sample log</summary>
  times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.008  000.008: --- NVIM STARTING ---
000.813  000.805: locale set
001.282  000.470: inits 1
001.334  000.052: window checked
001.345  000.011: parsing arguments
002.386  001.041: expanding arguments
002.459  000.073: inits 2
002.859  000.400: init highlight
013.346  001.066  001.066: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/vim-gruvbox8/colors/gruvbox8.vim
013.471  010.343  009.276: sourcing /Users/nathan/.config/nvim/init.lua
013.485  000.283: sourcing vimrc file(s)
+ 013.666  000.025  000.025: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/filetype.vim
014.360  000.057  000.057: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/ftplugin.vim
014.993  000.043  000.043: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/indent.vim
016.715  000.168  000.168: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/syncolor.vim
017.849  001.667  001.499: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/vim-gruvbox8/colors/gruvbox8.vim
017.932  002.321  000.654: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/synload.vim
018.025  002.551  000.230: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/syntax/syntax.vim
021.955  000.187  000.187: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/gzip.vim
022.056  000.021  000.021: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/health.vim
022.175  000.047  000.047: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/man.vim
023.777  000.207  000.207: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/pack/dist/opt/matchit/plugin/matchit.vim
024.039  001.791  001.584: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/matchit.vim
024.276  000.164  000.164: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/matchparen.vim
024.668  000.318  000.318: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/netrwPlugin.vim
024.992  000.017  000.017: sourcing /Users/nathan/.local/share/nvim/rplugin.vim
025.001  000.245  000.228: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/rplugin.vim
025.153  000.077  000.077: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/shada.vim
025.270  000.035  000.035: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/spellfile.vim
025.469  000.118  000.118: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tarPlugin.vim
025.719  000.163  000.163: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tohtml.vim
025.834  000.031  000.031: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/tutor.vim
026.077  000.169  000.169: sourcing /usr/local/Cellar/neovim/0.5.0/share/nvim/runtime/plugin/zipPlugin.vim
033.400  000.027  000.027: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/opt/vim-markdown/ftdetect/markdown.vim
033.411  007.043  007.016: sourcing /Users/nathan/.config/nvim/plugin/packer_compiled.lua
034.214  007.645: loading plugins
034.853  000.030  000.030: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/easy-replace.nvim/plugin/easy_replace.vim
+ 035.412  000.022  000.022: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/filetype.nvim/plugin/filetype.vim
036.064  000.027  000.027: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-bqf/plugin/bqf.vim
038.325  001.867  001.867: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/plugin/nvim-treesitter.vim
038.937  000.037  000.037: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/elixir.vim
039.039  000.032  000.032: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/fish.vim
039.132  000.023  000.023: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gdresource.vim
039.284  000.023  000.023: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gdscript.vim
039.427  000.022  000.022: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/gomod.vim
039.523  000.028  000.028: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/graphql.vim
039.620  000.030  000.030: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/hcl.vim
039.711  000.023  000.023: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/heex.vim
039.800  000.022  000.022: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/json5.vim
039.888  000.021  000.021: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/julia.vim
039.983  000.029  000.029: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/ledger.vim
040.075  000.026  000.026: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/nix.vim
040.169  000.025  000.025: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/ql.vim
040.271  000.035  000.035: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/query.vim
040.362  000.024  000.024: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/surface.vim
040.455  000.027  000.027: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/teal.vim
040.547  000.025  000.025: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/tlaplus.vim
040.638  000.025  000.025: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/yang.vim
040.731  000.027  000.027: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-treesitter/ftdetect/zig.vim
041.143  000.047  000.047: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/nvim-web-devicons/plugin/nvim-web-devicons.vim
041.688  000.042  000.042: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/plenary.nvim/plugin/plenary.vim
042.618  000.203  000.203: sourcing /Users/nathan/.local/share/nvim/site/pack/packer/start/vim-rooter/plugin/rooter.vim
042.980  006.026: loading packages
043.533  000.553: loading after plugins
043.543  000.010: inits 3
043.554  000.011: clearing screen
045.378  001.823: opening buffers
045.676  000.298: BufEnter autocommands
+ 045.679  000.003: editing files in windows
</details>

* The time my machine takes to source the file goes from 9.1 ms to (0.022 + 0.03) ms, which is a 175x speedup.

Contributions

All contributions are appreciated! But please make sure to follow these guidelines: