local M = {} M.install = { src = "https://github.com/neovim/nvim-lspconfig" } M.setup = function() vim.api.nvim_create_autocmd("LspAttach", { group = vim.api.nvim_create_augroup("LspAttach", { clear = true }), callback = function(event) vim.keymap.set("n", "gr", function() vim.lsp.buf.references() end, { desc = "LSP References" }) vim.keymap.set("n", "gd", function() vim.lsp.buf.definition() end, { desc = "LSP Definition" }) -- LSP implementations vim.keymap.set('n', 'gi', function() vim.lsp.buf.implementation() end, { desc = 'LSP implementation' }) -- LSP type definitions vim.keymap.set('n', 'gt', function() vim.lsp.buf.type_definition() end, { desc = 'LSP type definition' }) -- LSP document symbols vim.keymap.set('n', 'gs', function() vim.lsp.buf.document_symbol() end, { desc = 'LSP document symbols' }) -- LSP workspace symbols vim.keymap.set('n', 'gS', function() vim.lsp.buf.workspace_symbol() end, { desc = 'LSP workspace symbols' }) -- LSP Declaration vim.keymap.set("n", "gD", function() vim.lsp.buf.declaration() end, { desc = "Go to declaration" }) -- LSP Code Actions vim.keymap.set({ "n", "v" }, "ca", function() vim.lsp.buf.code_action() end, { desc = "LSP Code Actions" }) -- LSP Rename vim.keymap.set("n", "rn", function() vim.lsp.buf.rename() end, { desc = "LSP Rename" }) -- LSP diagnostics for current buffer vim.keymap.set('n', 'd', function() vim.diagnostic.setloclist() end, { desc = 'Buffer diagnostics' }) -- LSP Format vim.keymap.set("n", "F", function() vim.lsp.buf.format() end, { desc = "LSP Format" }) -- LSP diagnostics for entire workspace vim.keymap.set('n', 'D', function() vim.diagnostic.setqflist() end, { desc = 'Workspace diagnostics' }) vim.keymap.set("n", "[d", function() vim.diagnostic.jump({ count = -1, on_jump = function() vim.diagnostic.open_float() end }) end, { desc = "Go to previous diagnostic" }) vim.keymap.set("n", "]d", function() vim.diagnostic.jump({ count = 1, on_jump = function() vim.diagnostic.open_float() end }) end, { desc = "Go to next diagnostic" }) vim.keymap.set("n", "[e", function() vim.diagnostic.jump({ count = -1, severity = vim.diagnostic.severity.ERROR, on_jump = function() vim.diagnostic.open_float() end }) end, { desc = "Go to previous diagnostic (error only)" }) vim.keymap.set("n", "]e", function() vim.diagnostic.jump({ count = 1, severity = vim.diagnostic.severity.ERROR, on_jump = function() vim.diagnostic.open_float() end }) end, { desc = "Go to next diagnostic (error only)" }) vim.keymap.set("n", "df", function() vim.diagnostic.open_float() end, { desc = "Show diagnostic in floating window" }) local client = vim.lsp.get_client_by_id(event.data.client_id) if client and client:supports_method('textDocument/completion') then -- Optional: trigger autocompletion on EVERY keypress. May be slow! local chars = {}; for i = 32, 126 do table.insert(chars, string.char(i)) end client.server_capabilities.completionProvider.triggerCharacters = chars vim.lsp.completion.enable(true, client.id, event.buf, { autotrigger = true, -- Prevent auto-selection of first item autocomplete = false }) -- Map Ctrl+y to select first item and accept completion vim.keymap.set('i', '', function() if vim.fn.pumvisible() == 1 then -- If completion menu is visible, select first item if nothing selected, then accept local selected = vim.fn.complete_info({'selected'}).selected if selected == -1 then -- Nothing selected, select first item then accept return '' else -- Something already selected, just accept return '' end else return '' end end, { expr = true, buffer = event.buf, desc = 'Accept completion' }) end if client and client.server_capabilities.documentHighlightProvider then vim.api.nvim_create_autocmd("LspDetach", { group = vim.api.nvim_create_augroup("LspDetach", { clear = true }), callback = function() vim.lsp.buf.clear_references() end, }) end end, }) -- Load server configurations from separate files local servers_path = vim.fn.stdpath("config") .. "/lua/lsp/servers" local server_files = vim.fn.glob(servers_path .. "/*.lua", false, true) local servers = {} for _, file in ipairs(server_files) do local server_name = vim.fn.fnamemodify(file, ":t:r") local ok, server_config = pcall(require, "lsp.servers." .. server_name) if ok then servers[server_name] = server_config else vim.notify("Failed to load server config: " .. server_name, vim.log.levels.WARN) end end -- Setup all servers using the new vim.lsp.config and vim.lsp.enable APIs for server_name, server in pairs(servers) do vim.lsp.config(server_name, server or {}) vim.lsp.enable(server_name) end end return M