nvim/lua/plugins/conform_formatter.lua
RingOfStorms (Joshua Bell) 8a0dd46473 more
2025-10-27 21:53:43 -05:00

114 lines
3.6 KiB
Lua

local function formatCurrent(retry)
require("conform").format({ async = true, lsp_fallback = true }, function(err, edited)
if edited then
print("Formatted!")
elseif err then
-- Sometimes I am too fast and vim is saving from my InsertExit and this fails so
-- I give it one retry
if not retry and string.find(err, "concurrent modification") then
return formatCurrent(true)
end
print(err)
else
print("Nothing to format!")
end
end)
end
---@param bufnr integer
---@param ... string
---@return string
local function first(bufnr, ...)
local conform = require("conform")
for i = 1, select("#", ...) do
local formatter = select(i, ...)
if conform.get_formatter_info(formatter, bufnr).available then
return formatter
end
end
return select(1, ...)
end
-- Make function that converts { { "prettierd", "prettier" }, "rustywind" } to
--function (bufnr)
-- return { first(bufnr, "prettierd", "prettier"), "rustywind" }
-- end,
local function expandFormatters(formatters)
return function(bufnr)
local result = {}
for i = 1, #formatters do
local formatter = formatters[i]
if type(formatter) == "table" then
result[i] = first(bufnr, unpack(formatter))
else
result[i] = formatter
end
end
return result
end
end
return {
"stevearc/conform.nvim",
init = function()
-- Check for common formatters and warn if missing
local formatters_to_check = {
{ cmd = "stylua", desc = "Lua formatting" },
{ cmd = "nixfmt", desc = "Nix formatting" },
{ cmd = "prettier", desc = "JS/TS/Svelte formatting (alternative: prettierd)" },
{ cmd = "rustywind", desc = "Tailwind class sorting" },
{ cmd = "markdownlint-cli2", desc = "Markdown formatting" },
{ cmd = "sql-formatter", desc = "SQL formatting" },
{ cmd = "rustfmt", desc = "Rust formatting" },
}
for _, formatter in ipairs(formatters_to_check) do
if not U.cmd_executable(formatter.cmd) then
-- Only warn once on startup, not on every format attempt
vim.schedule(function()
vim.notify(
string.format("Formatter '%s' not found. Used for: %s", formatter.cmd, formatter.desc),
vim.log.levels.WARN
)
end)
end
end
end,
opts = {
-- https://github.com/stevearc/conform.nvim?tab=readme-ov-file#setup
notify_on_error = true,
formatters = {
-- v_fmt = {
-- command = "v",
-- args = { "fmt" },
-- },
},
-- Formatters are checked lazily on format attempt
-- conform.nvim will show errors if formatters are missing
formatters_by_ft = {
sql = { "sql_formatter", lsp_format = "first" },
lua = { "stylua", lsp_format = "first" },
nix = { "nixfmt", lsp_format = "first" },
qml = { "qmlformat", lsp_format = "first" },
typescript = expandFormatters({ { "prettierd", "prettier" }, "rustywind", lsp_format = "first" }),
typescriptreact = expandFormatters({ { "prettierd", "prettier" }, "rustywind", lsp_format = "first" }),
javascript = expandFormatters({ { "prettierd", "prettier" }, "rustywind", lsp_format = "first" }),
javascriptreact = expandFormatters({ { "prettierd", "prettier" }, "rustywind", lsp_format = "first" }),
svelte = expandFormatters({ { "prettierd", "prettier" }, "rustywind", lsp_format = "first" }),
-- TODO revisit these I'd like to use them but they are not in nixpkgs yet
-- https://nixos.org/guides/nix-pills/
-- markdown = { "mdslw", "mdsf"},
markdown = { "markdownlint-cli2", lsp_format = "first" },
rust = { "rustfmt", lsp_format = "first" },
},
},
keys = {
{
"<leader>l<leader>",
formatCurrent,
mode = { "n", "v", "x" },
desc = "Format buffer",
},
},
}