Neovim Syntax Highlighting and Formatting for Caddy
I’ve been working with Caddyfiles a lot recently and Neovim doesn’t handle syntax highlighting or formatting them out of the box. Fortunately, it’s very easy to get set up with the help of the nvim-treesitter/nvim-treesitter and stevearc/conform.nvim packages.
First, you’ll need to set up the filetype. I use a .caddy extension for external imports.
-- Filetypes
vim.filetype.add {
extension = {
caddy = 'caddy',
},
filename = {
Caddyfile = 'caddy',
},
}
Next add the Caddyfile parser to nvim-treesitter.
return { -- Highlight, edit, and navigate code
'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
main = 'nvim-treesitter.configs', -- Sets main module to use for opts
opts = {
ensure_installed = {
'php',
'bash',
'c',
'diff',
'html',
'lua',
'luadoc',
'markdown',
'markdown_inline',
'query',
'vim',
'vimdoc',
'caddy', -- added
},
auto_install = true,
highlight = {
enable = true,
additional_vim_regex_highlighting = { 'ruby' },
},
indent = { enable = true, disable = { 'ruby' } },
},
}
Finally, add a custom formatter for Caddyfiles to conform.nvim. This assumes that the caddy binary is available in your path. Adjust the command as needed for your system.
return { -- Autoformat
'stevearc/conform.nvim',
event = { 'BufWritePre' },
cmd = { 'ConformInfo' },
keys = {
{
'<leader>cf',
function()
require('conform').format { async = true, lsp_format = 'fallback' }
end,
mode = 'n',
desc = '[F]ormat buffer',
},
},
opts = {
notify_on_error = true,
format_on_save = function(bufnr)
local disable_filetypes = { c = true, cpp = true }
if disable_filetypes[vim.bo[bufnr].filetype] then
return nil
else
return {
timeout_ms = 4000,
lsp_format = 'fallback',
}
end
end,
formatters = {
caddy = { -- added
command = 'caddy',
args = { 'fmt', '-' },
stdin = true,
},
},
formatters_by_ft = {
lua = { 'stylua' },
php = { 'pint', 'mago_format', stop_after_first = true },
blade = { 'blade-formatter', stop_after_first = true },
javascript = { 'biome', 'prettier', stop_after_first = true },
json = { 'biome', 'prettier', stop_after_first = true },
html = { 'prettier', stop_after_first = true },
css = { 'prettier', stop_after_first = true },
caddy = { 'caddy' }, --added
},
},
}
And the result…
