Custom File Type Syntax Highlighting with Neovim
There may come a time where you want to set a few different types of files to a specific file type for better editor support.
Here’s a couple of use cases I had:
- Syntax highlight an
.env.example
file differently than.env
so I had a visual cue between the example file and the real file - Syntax highlight
requirements-lock.txt
the same asrequirements.txt
- Syntax highlight a bunch of variant files like
.aliases.local
or.zprofile.local
the same as a regular shell script
Even if you have different use cases you’ll be able to see how to apply it back to your set up. We’ll also go over how to split out LSP support and syntax highlighting with Treesitter.
Here’s a few examples from my .config/nvim/filetype.lua
file in my
dotfiles. The comments should help you
get going here, I found :help vim.filetype.add
to be quite helpful too:
-- Set .aliases or any variant as "bash".
vim.filetype.add({ pattern = { ["%.*aliases.*"] = "bash" } })
-- Set .zprofile or any variant as "bash".
vim.filetype.add({ pattern = { ["%.*zprofile.*"] = "bash" } })
-- Set .env or any variant as "dotenv" except we want .env.example files to be
-- treated differently so it's easier to know we are editing an example file.
-- This has less syntax highlighting and comes up with a different explorer
-- icon so it's easier to know it's not the "real" env file.
vim.filetype.add({
pattern = {
["%.env.*"] = "dotenv",
["%.env.*.example"] = { "conf", { priority = 1 } },
},
})
-- Ensure all .env files and variants are syntax highlighted as shell scripts.
-- This goes along with the filetype addition above. We do this to avoid using
-- bash or sh so the BashLSP linter and formatter doesn't affect env files
-- since that can create a lot of unwanted false positives and side effects.
vim.treesitter.language.register("bash", "dotenv")
-- Set git config variarts as "git_config".
vim.filetype.add({ pattern = { [".*/git/config.*"] = "git_config" } })
-- Set requirements-lock.txt or any variant as "requirements".
vim.filetype.add({ pattern = { ["requirements.*.txt"] = "requirements" } })
The video below demos and covers what’s listed above.
# Demo Video
Timestamps
- 0:09 – Example env file vs real one
- 1:24 – Handling file variants
- 2:22 – Using Vim’s filetype add in Lua script
- 4:06 – Multiple patterns with a priority
- 5:04 – Registering file types with Treesitter
- 6:03 – Customize things for your use cases
- 6:14 – Neovim’s help for filetype was really helpful
When was the last time you did something similar? Let me know below.