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" }, "<leader>ca", function()
|
|
vim.lsp.buf.code_action()
|
|
end, { desc = "LSP Code Actions" })
|
|
|
|
-- LSP Rename
|
|
vim.keymap.set("n", "<leader>rn", function()
|
|
vim.lsp.buf.rename()
|
|
end, { desc = "LSP Rename" })
|
|
|
|
-- LSP diagnostics for current buffer
|
|
vim.keymap.set('n', '<leader>d', function()
|
|
vim.diagnostic.setloclist()
|
|
end, { desc = 'Buffer diagnostics' })
|
|
|
|
-- LSP Format
|
|
vim.keymap.set("n", "<leader>F", function()
|
|
vim.lsp.buf.format()
|
|
end, { desc = "LSP Format" })
|
|
|
|
-- LSP diagnostics for entire workspace
|
|
vim.keymap.set('n', '<leader>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", "<leader>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', '<C-y>', 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 '<C-n><C-y>'
|
|
else
|
|
-- Something already selected, just accept
|
|
return '<C-y>'
|
|
end
|
|
else
|
|
return '<C-y>'
|
|
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
|