return { "neovim/nvim-lspconfig", event = { "BufReadPre", "BufNewFile" }, dependencies = { { "williamboman/mason.nvim", optional = true, dependencies = { { "williamboman/mason-lspconfig.nvim", config = function () end } } }, { -- Autocomplete source "hrsh7th/nvim-cmp", optional = true, dependencies = { "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-nvim-lsp-signature-help" }, }, { "ray-x/lsp_signature.nvim", event = "VeryLazy", opts = { hint_enable = false, fix_pos = true, handler_opts = { border = "none" } }, }, -- LSP often return markdown that neovim parses. -- make sure we have a plugin that can render markdown to nicer text { 'MeanderingProgrammer/render-markdown.nvim', dependencies = { 'nvim-tree/nvim-web-devicons', { "nvim-treesitter/nvim-treesitter", opts = { ensure_installed = { "markdown", "markdown_inline" } } } }, opts = { overrides = { buftype = { -- LSP Hover = "nofile" nofile = { code = { left_pad = 0, right_pad = 0 }, }, }, }, } } }, --- @class LSPServerOptions : LSPFeatures --- @field on_save function | nil --- @class LSPOptions opts = { --- @class LSPFeatures features = { document_highlight = { enabled = true, }, codelens = { enabled = false, }, inlay_hints = { enabled = true, exclude = {}, }, diagnostics = true, hover = true, definition = true, }, --- @type { string: LSPServerOptions } servers = {}, }, --- @param opts LSPOptions config = function(_, opts) local lspconfig = require("lspconfig") local utils = require("user.utils.lsp") local augroup = vim.api.nvim_create_augroup("Lsp", {}) local has_cmp, cmp_lsp = pcall(require, "cmp_nvim_lsp") local capabilities = vim.tbl_deep_extend('force', vim.lsp.protocol.make_client_capabilities() or {}, has_cmp and cmp_lsp.default_capabilities() or {}) --- @param server string local function setup(server) local server_opts = opts.servers[server] or {} if type(server_opts) == "function" then server_opts = server_opts() end -- Set missing features to default ones in server options. server_opts = vim.tbl_deep_extend("keep", server_opts, opts.features) ---@param client vim.lsp.Client ---@param bufnr number local on_attach = function(client, bufnr) vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr }) -- disable diagnostics if server_opts.diagnostics == false then client.server_capabilities.diagnosticProvider = false end -- disable hover if server_opts.hover == false then client.server_capabilities.hoverProvider = false end if server_opts.definition == false then client.server_capabilities.definitionProvider = false end if server_opts.inlay_hints.enabled and client.supports_method("textDocument/inlayHint") then vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) end if server_opts.codelens.enabled and client.supports_method("textDocument/codeLens") then utils.codelens(augroup, bufnr) end if server_opts.document_highlight.enabled and client.supports_method("textDocument/documentHighlight") then utils.document_highlight(bufnr) end -- Setup on save handler if server_opts.on_save then vim.api.nvim_create_autocmd("BufWritePre", { group = augroup, buffer = bufnr, callback = server_opts.on_save, }) end end server_opts = vim.tbl_deep_extend("force", { on_attach = on_attach, capabilities = capabilities }, server_opts or {}) lspconfig[server].setup(server_opts) end local have_mason, mlsp = pcall(require, "mason-lspconfig") local all_mslp_servers = {} if have_mason then all_mslp_servers = vim.tbl_keys(require("mason-lspconfig.mappings.server").lspconfig_to_package) end local ensure_installed = {} ---@type string[] for name, server_opts in pairs(opts.servers) do if server_opts.mason == false or not vim.tbl_contains(all_mslp_servers, name) then setup(name) else ensure_installed[#ensure_installed + 1] = name end end if have_mason then mlsp.setup({ ensure_installed = ensure_installed, handlers = { setup }, }) end end, }