From 32ff674cefd8142f4e8c210b6fb3bd23eef7ab84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Tue, 7 Oct 2025 23:45:38 +0200 Subject: [PATCH] feat: add lsp config and neovim/nvim-lspconfig --- after/lsp/lua_ls.lua | 62 ++++++++++++++++++++++++++++++++++++++++++++ lua/plugins/lsp.lua | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 after/lsp/lua_ls.lua diff --git a/after/lsp/lua_ls.lua b/after/lsp/lua_ls.lua new file mode 100644 index 0000000..26bb69d --- /dev/null +++ b/after/lsp/lua_ls.lua @@ -0,0 +1,62 @@ +local filter_line_locations = function(locations) + local present, res = {}, {} + for _, l in ipairs(locations) do + local t = present[l.filename] or {} + if not t[l.lnum] then + table.insert(res, l) + t[l.lnum] = true + end + present[l.filename] = t + end + return res +end + +local show_location = function(location) + local buf_id = location.bufnr or vim.fn.bufadd(location.filename) + vim.bo[buf_id].buflisted = true + vim.api.nvim_win_set_buf(0, buf_id) + vim.api.nvim_win_set_cursor(0, { location.lnum, location.col - 1 }) + vim.cmd("normal! zv") +end + +local on_list = function(args) + local items = filter_line_locations(args.items) + if #items > 1 then + vim.fn.setqflist({}, " ", { title = "LSP locations", items = items }) + return vim.cmd("botright copen") + end + show_location(items[1]) +end + +local luals_unique_definition = function() + return vim.lsp.buf.definition({ on_list = on_list }) +end + +return { + on_attach = function(client, buf_id) + -- Reduce unnecessarily long list of completion triggers for better + -- 'mini.completion' experience + client.server_capabilities.completionProvider.triggerCharacters = + { ".", ":", "#", "(" } + + -- Override global "Go to source" mapping with dedicated buffer-local + local opts = { buffer = buf_id, desc = "Lua source definition" } + vim.keymap.set("n", "ls", luals_unique_definition, opts) + end, + settings = { + Lua = { + runtime = { version = "LuaJIT", path = vim.split(package.path, ";") }, + diagnostics = { + -- Don't analyze whole workspace, as it consumes too much CPU and RAM + workspaceDelay = -1, + }, + workspace = { + -- Don't analyze code from submodules + ignoreSubmodules = true, + -- Add Neovim's methods for easier code writing + library = { vim.env.VIMRUNTIME }, + }, + telemetry = { enable = false }, + }, + }, +} diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua index efa064b..8a18536 100644 --- a/lua/plugins/lsp.lua +++ b/lua/plugins/lsp.lua @@ -13,4 +13,54 @@ later(function() "stylua", "lua_ls", }) + + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + local bufnr = args.buf + + ---@param keys string + ---@param func function + ---@param desc string + ---@param modes? string | table + local map_lsp = function(keys, func, desc, modes) + modes = modes or "n" + vim.keymap.set( + modes, + "l" .. keys, + func, + { buffer = bufnr, desc = "lsp: " .. desc } + ) + end + + local fzf = require("fzf-lua") + + map_lsp("d", fzf.lsp_definitions, "definition") + map_lsp("D", fzf.lsp_declarations, "declaration") + map_lsp("i", fzf.lsp_implementations, "implementation") + map_lsp("r", fzf.lsp_references, "references") + + map_lsp("t", fzf.lsp_typedefs, "type definition") + + map_lsp("a", fzf.lsp_code_actions, "code action", { "n", "x" }) + map_lsp("n", vim.lsp.buf.rename, "rename") + + map_lsp("W", fzf.lsp_live_workspace_symbols, "workspace symbols") + map_lsp("L", fzf.lsp_document_symbols, "document symbols") + + map_lsp("w", fzf.lsp_workspace_diagnostics, "workspace diagnostics") + map_lsp("l", fzf.lsp_document_diagnostics, "document diagnostics") + + map_lsp( + "f", + function() vim.lsp.buf.format({ timeout_ms = 2000 }) end, + "format" + ) + + -- inlay hints + if client and client.server_capabilities.inlayHintProvider then + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) + end + end, + }) end)