return { { "williamboman/mason.nvim", cmd = "Mason", }, { "williamboman/mason-lspconfig.nvim", event = { "BufReadPre", "BufNewFile" }, config = function() require("mason").setup() require("mason-lspconfig").setup_handlers({ -- The first entry (without a key) will be the default handler -- and will be called for each installed server that doesn't have -- a dedicated handler. function(server_name) -- default handler (optional) require("lspconfig")[server_name].setup({}) end, -- Next, you can provide a dedicated handler for specific servers. -- For example, a handler override for the `rust_analyzer`: -- ["rust_analyzer"] = function () -- require("rust-tools").setup {} -- end }) end, }, "neovim/nvim-lspconfig", { "stevearc/conform.nvim", event = { "BufWritePre" }, cmd = { "ConformInfo" }, opts = function() local mason_reg = require("mason-registry") local formatters = {} local formatters_by_ft = {} -- add diff langue vs filetype local keymap = { ["c++"] = "cpp", ["c#"] = "cs", } -- add dif conform vs mason local name_map = { ["cmakelang"] = "cmake_format", ["deno"] = "deno_fmt", ["elm-format"] = "elm_format", ["gdtoolkit"] = "gdformat", ["nixpkgs-fmt"] = "nixpkgs_fmt", ["opa"] = "opa_fmt", ["php-cs-fixer"] = "php_cs_fixer", ["ruff"] = "ruff_format", ["sql-formatter"] = "sql_formatter", ["xmlformatter"] = "xmlformat", } for _, pkg in pairs(mason_reg.get_installed_packages()) do for _, type in pairs(pkg.spec.categories) do -- only act upon a formatter if type == "Formatter" then -- if formatter doesn't have a builtin config, create our own from a generic template if not require("conform").get_formatter_config(pkg.spec.name) then -- the key of the entry to this table -- is the name of the bare executable -- the actual value may not be the absolute path -- in some cases local bin = next(pkg.spec.bin) -- this should be replaced by a function -- that quieries the configured mason install path local prefix = vim.fn.stdpath("data") .. "/mason/bin/" formatters[pkg.spec.name] = { command = prefix .. bin, args = { "$FILENAME" }, stdin = true, require_cwd = false, } end -- finally add the formatter to it's compatible filetype(s) for _, ft in pairs(pkg.spec.languages) do local ftl = string.lower(ft) local ready = mason_reg.get_package(pkg.spec.name):is_installed() if ready then if keymap[ftl] ~= nil then ftl = keymap[ftl] end if name_map[pkg.spec.name] ~= nil then pkg.spec.name = name_map[pkg.spec.name] end formatters_by_ft[ftl] = formatters_by_ft[ftl] or {} table.insert(formatters_by_ft[ftl], pkg.spec.name) end end end end end return { format_on_save = { lsp_fallback = true, timeout_ms = 500, }, formatters = formatters, formatters_by_ft = formatters_by_ft, } end, keys = { { "fm", function() require("conform").format({ async = true }) end, mode = "", desc = "Format buffer", }, { "ca", function() vim.lsp.buf.code_action() end, mode = "", desc = "Code Action", }, { "rn", function() vim.lsp.buf.rename() end, mode = "", desc = "[R]e[N]ame", }, { "gd", function() vim.lsp.buf.definition() end, mode = "", desc = "[G]oto [D]efinition", }, { "gD", function() vim.lsp.buf.declaration() end, mode = "", desc = "[G]oto [D]eclaration", }, }, }, }