Skip to content

Formatting

Blak uses stevearc/conform.nvim for formatting. It runs on BufWritePre (when format-on-save is enabled) and via the :BlakFormat command and the <leader>cf keymap.

Spec: lua/blak/plugins/formatting.lua.

format = {
enabled = true,
timeout_ms = 1000,
lsp_format = "fallback",
formatters_by_ft = {
lua = { "stylua" },
sh = { "shfmt" },
bash = { "shfmt" },
zsh = { "shfmt" },
},
}
Option Meaning
enabled Whether format-on-save runs at all.
timeout_ms Per-buffer timeout before Conform gives up.
lsp_format "never", "fallback", "prefer", "first", or "last". Blak defaults to "fallback" — use LSP only when no Conform formatter is available for the filetype.
formatters_by_ft Filetype → ordered formatter list. Each formatter must be installable via Mason (or already on $PATH).

Language extras add to formatters_by_ft:

Extra Adds
lang.typescript, lang.typescript-legacy prettierd (fallback prettier) for js/ts/jsx/tsx/json/jsonc
lang.typescript-tsgo Alias of lang.typescript
lang.python isort then black for python
lang.python-pro ruff_organize_imports then ruff_format for python
lang.markdown prettierd (fallback prettier) for markdown
lang.web prettierd (fallback prettier) for html, css, scss, less
lang.yaml prettierd (fallback prettier) for yaml
lang.json prettierd (fallback prettier) for json, jsonc
lang.go goimports, gofumpt for go
lang.rust rustfmt, taplo with lsp_format = "fallback"
lang.c clang_format for c, cpp, objc, objcpp, cuda
lang.terraform terraform_fmt for terraform, terraform-vars
lang.nix nixfmt for nix

StyLua indents with tabs unless a config tells it otherwise. When no .stylua.toml, stylua.toml, or .editorconfig exists in the file’s directory or above it, and there is no global StyLua config (for example ~/.config/stylua/stylua.toml), Blak passes --indent-type and --indent-width from the buffer’s expandtab and shiftwidth. With Blak’s defaults that is 2 spaces. A project config always wins. Conform’s shfmt already follows the same buffer settings.

Action How
Toggle for current buffer <leader>uf or :BlakFormatToggle
Toggle globally :BlakFormatToggle! (with bang)
Format current buffer once :BlakFormat
Format with or without an LSP <leader>cf
Format selected lines :'<,'>BlakFormat
Format an explicit line range :2,5BlakFormat

The flags are simple booleans:

vim.b.blak_disable_autoformat = true -- buffer-local
vim.g.blak_disable_autoformat = true -- global

You can flip them in your user.lua, an autocmd, or interactively.

Global lsp_format and timeout_ms become Conform defaults. Per-filetype options take precedence, including for manual formatting. To disable both external and LSP formatting for one filetype:

format = {
formatters_by_ft = {
python = { lsp_format = "never" },
},
}

An empty formatter list alone still allows the global LSP fallback. Remove the filetype override to restore its extra’s formatting defaults.

Either via user.lua:

return {
format = {
formatters_by_ft = {
yaml = { "prettierd", "prettier", stop_after_first = true },
sql = { "sqlfluff" },
},
},
mason = {
ensure_installed = { "prettierd", "prettier", "sqlfluff" },
},
}

Or as part of an extra so it’s reversible — see Writing an extra.

Use plugins.specs in user.lua to pass Conform options, including custom formatter arguments:

return {
plugins = {
specs = {
{
"stevearc/conform.nvim",
opts = {
formatters = { shfmt = { prepend_args = { "-i", "2", "-ci" } } },
},
},
},
},
}

Reload uses the same merged plugin options as startup. Explicit options such as format_on_save = false stay in effect, and removed filetypes are removed from Conform’s formatter map.

If you just want to skip once:

:noautocmd write
:lua = require("conform").list_formatters_for_buffer()
:ConformInfo " full report on this buffer