Formatting
FtVim uses conform.nvim for code formatting, providing fast and reliable formatting with support for many formatters.
Default Configuration
FtVim comes with these formatters pre-configured:
| Language | Formatter |
|---|---|
| Lua | stylua |
| Shell/Bash | shfmt |
These formatters are automatically installed via Mason. The extras add more: c_formatter_42 for C (42), clang-format for C++ (C++) and prettier for web files (Web).
Formatting Keymaps
| Keymap | Mode | Description |
|---|---|---|
<leader>cf | Normal, Visual | Format buffer or selection |
<leader>uf | Normal | Toggle format on save |
Manual Formatting
To format the current buffer, press <leader>cf in normal mode.
To format a selection, select the text in visual mode and press <leader>cf.
You can also use the command:
:lua require("conform").format()
Format on Save
Format on save is disabled by default in FtVim. Toggle it for the session with <leader>uf, or enable it permanently in ~/.config/nvim/lua/config/options.lua:
vim.g.ftvim_autoformat = true
To enable or disable it for a single buffer, set vim.b.ftvim_autoformat (it overrides the global option):
vim.api.nvim_create_autocmd("FileType", {
pattern = { "markdown" },
callback = function()
vim.b.ftvim_autoformat = false
end,
})
Custom Format on Save
For full control, override conform's format_on_save (this replaces FtVim's toggle):
-- ~/.config/nvim/lua/plugins/formatting.lua
return {
{
"stevearc/conform.nvim",
opts = {
format_on_save = {
timeout_ms = 500, -- Timeout for formatting
lsp_format = "fallback", -- Use LSP if no formatter is configured
},
},
},
}
Disable Format on Save for Specific Filetypes
return {
{
"stevearc/conform.nvim",
opts = {
format_on_save = function(bufnr)
-- Disable for certain filetypes
local ignore_filetypes = { "sql", "java" }
if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
return nil
end
return {
timeout_ms = 500,
lsp_format = "fallback",
}
end,
},
},
}
Adding New Formatters
Step 1: Install the Formatter
Add the formatter to Mason's ensure_installed list:
return {
{
"mason-org/mason.nvim",
opts = {
ensure_installed = {
"prettier", -- JavaScript/TypeScript/JSON/etc.
"black", -- Python
"clang-format", -- C/C++
},
},
},
}
Or install manually via :Mason.
Step 2: Configure the Formatter
Add the formatter to conform.nvim:
return {
{
"stevearc/conform.nvim",
opts = {
formatters_by_ft = {
javascript = { "prettier" },
typescript = { "prettier" },
json = { "prettier" },
python = { "black" },
c = { "clang-format" },
cpp = { "clang-format" },
},
},
},
}
Using Multiple Formatters
Run formatters in sequence:
formatters_by_ft = {
python = { "isort", "black" }, -- Run isort first, then black
}
Use the first available formatter:
formatters_by_ft = {
javascript = { "prettierd", "prettier", stop_after_first = true },
}
Customizing Formatter Options
Override formatter settings:
return {
{
"stevearc/conform.nvim",
opts = {
formatters = {
stylua = {
prepend_args = { "--indent-type", "Spaces", "--indent-width", "2" },
},
shfmt = {
prepend_args = { "-i", "2" }, -- 2-space indent
},
prettier = {
prepend_args = { "--tab-width", "2", "--single-quote" },
},
},
},
},
}
Disabling Formatting
For Specific Filetypes
return {
{
"stevearc/conform.nvim",
opts = {
formatters_by_ft = {
-- Set to empty table to disable
markdown = {},
},
},
},
}
Disable LSP Fallback
return {
{
"stevearc/conform.nvim",
opts = {
default_format_opts = {
lsp_format = "never", -- Don't use LSP for formatting
},
},
},
}
Troubleshooting
Check Conform Status
:ConformInfo
Shows configured formatters and their status for the current buffer.
Common Issues
Formatter not working:
- Check
:ConformInfoto see if the formatter is detected - Ensure the formatter is installed (
:Mason) - Verify the formatter binary is in your PATH
Formatting slow:
- Some formatters (like prettier) can be slow on large files
- Consider using faster alternatives (e.g.,
prettierdinstead ofprettier) - Increase
timeout_msif needed
Format on save not working:
- Ensure it is enabled (
<leader>uforvim.g.ftvim_autoformat = true), it is disabled by default - Check
:ConformInfofor the formatter status - Look for errors with
:messages
Recommended Formatters by Language
| Language | Formatter | Notes |
|---|---|---|
| Lua | stylua | Default in FtVim |
| Shell/Bash | shfmt | Default in FtVim |
| JavaScript/TypeScript | prettier or prettierd | prettierd is faster |
| Python | black or ruff_format | ruff is faster |
| Go | gofmt or goimports | goimports also organizes imports |
| Rust | rustfmt | Comes with Rust toolchain |
| C (42) | c_formatter_42 | 42 extra |
| C/C++ | clang-format | Highly configurable, C++ extra |
| JSON | prettier or jq | jq for JSON-only projects |
| YAML | prettier or yamlfmt | |
| Markdown | prettier | |
| HTML/CSS | prettier |
Example: Complete Formatting Setup
Here's a full example for a web development setup:
return {
-- Install formatters
{
"mason-org/mason.nvim",
opts = {
ensure_installed = {
"prettierd",
"eslint_d",
},
},
},
-- Configure formatting
{
"stevearc/conform.nvim",
opts = {
formatters_by_ft = {
javascript = { "prettierd" },
typescript = { "prettierd" },
javascriptreact = { "prettierd" },
typescriptreact = { "prettierd" },
json = { "prettierd" },
html = { "prettierd" },
css = { "prettierd" },
markdown = { "prettierd" },
},
},
},
}
Then enable format on save with vim.g.ftvim_autoformat = true or <leader>uf.
The Web extra already sets up prettier for these filetypes.