{ pkgs, lib, ... }: { programs.nixvim = { extraPackages = with pkgs; [ shellcheck shellharden shfmt ruff stylua nixfmt-rfc-style clang-tools csharpier prettierd ]; plugins = { conform-nvim = { enable = true; settings = { formatters_by_ft = let prettier = { __unkeyed-1 = "prettierd"; __unkeyed_2 = "prettier"; timeout_ms = "5000"; stop_after_first = "true"; }; in { bash = [ "shellcheck" "shellharden" "shfmt" ]; python = [ "ruff_fix" "ruff_format" "ruff_organize_imports" ]; c = [ "clang-format" ]; cpp = [ "clang-format" ]; cs = [ "csharpier" ]; csharp = [ "csharpier" ]; lua = [ "stylua" ]; nix = [ "nixfmt" ]; javascript = prettier; javascriptreact = prettier; typescript = prettier; typescriptreact = prettier; markdown = prettier; yaml = prettier; json = prettier; jsonc = prettier; svelte = prettier; html = prettier; css = prettier; graphql = prettier; "_" = [ "trim_whitespace" "trim_newlines" ]; }; log_level = "warn"; notify_on_error = true; notify_no_formatters = true; default_format_opts = { lsp_format = "fallback"; timeout_ms = 1000; }; formatters = { shellcheck = { command = lib.getExe pkgs.shellcheck; }; shfmt = { command = lib.getExe pkgs.shfmt; }; shellharden = { command = lib.getExe pkgs.shellharden; }; nixfmt = { command = lib.getExe pkgs.nixfmt-rfc-style; }; stylua = { command = lib.getExe pkgs.stylua; }; clang-format = { command = "${pkgs.clang-tools}/bin/clang-format"; }; csharpier = { command = lib.getExe pkgs.csharpier; }; ruff_fix = { command = lib.getExe pkgs.ruff; }; ruff_format = { command = lib.getExe pkgs.ruff; }; ruff_organize_imports = { command = lib.getExe pkgs.ruff; }; }; format_on_save = # lua '' function(bufnr) if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then return end if slow_format_filetypes[vim.bo[bufnr].filetype] then return end local function on_format(err) if err and err:match("timeout$") then slow_format_filetypes[vim.bo[bufnr].filetype] = true end end return { timeout_ms = 200, lsp_fallback = true }, on_format end ''; format_after_save = # lua '' function(bufnr) if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then return end if not slow_format_filetypes[vim.bo[bufnr].filetype] then return end return { lsp_fallback = true } end ''; }; luaConfig.post = # lua '' slow_format_filetypes = {} -- Filetypes that are slow to format, and should be formatted after saving a buffer instead of before require("conform").formatters.injected = { options = { lang_to_ext = { c = "c", cpp = "cpp", cs = "cs", csharp = "cs", lua = "lua", nix = "nix", python = "py", bash = "sh", javascript = "js", javascriptreact = "jsx", typescript = "ts", typescriptreact = "tsx", markdown = "md", yaml = "yaml", json = "json", jsonc = "jsonc", svelte = "svelte", html = "html", css = "css", graphql = "graphql", }, }, } vim.api.nvim_create_user_command("Format", function(args) local range = nil if args.count ~= -1 then local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1] range = { start = { args.line1, 0 }, ["end"] = { args.line2, end_line:len() }, } end require("conform").format({ async = true, lsp_format = "fallback", range = range }) end, { range = true }) ''; }; }; keymaps = [ { mode = "n"; key = "f"; action = "Format"; options = { desc = "Format"; silent = true; }; } ]; }; }