local lspKeys = function(client, bufnr) local base_opts = { noremap = true, silent = false, buffer = bufnr } local function opts(desc) return vim.tbl_extend('error', base_opts, { desc = desc }) end local mappings = { { mode = { 'n', 'x' }, key = 'a', fn = vim.lsp.buf.code_action, desc = 'Code action' }, { mode = 'n', key = 'e', fn = vim.lsp.buf.declaration, desc = 'Declaration' }, { mode = 'n', key = 'h', fn = function() vim.lsp.buf.hover({ border = 'none' }) end, desc = 'Hover' }, { mode = 'n', key = 'c', fn = vim.lsp.buf.outgoing_calls, desc = 'Outgoing calls' }, { mode = 'n', key = 'C', fn = vim.lsp.buf.incoming_calls, desc = 'Incoming calls' }, { mode = 'n', key = 'm', fn = vim.lsp.buf.rename, desc = 'Rename' }, { mode = 'n', key = 'D', fn = vim.lsp.buf.type_definition, desc = 'Type definition' }, { mode = { 'n', 'i', 'x' }, key = '', fn = vim.lsp.buf.signature_help, desc = 'Signature help' }, { mode = 'n', key = 'v', fn = function() vim.diagnostic.open_float({ border = 'rounded' }) end, desc = 'Diagnostics Float' }, { mode = 'n', key = '', fn = 'ClangdSwitchSourceHeader', desc = 'Switch Source/Header' }, } for _, map in ipairs(mappings) do vim.keymap.set(map.mode, map.key, map.fn, opts(map.desc)) end if client.supports_method('inlayHintProvider') then vim.keymap.set( 'n', 'i', function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }), { bufnr = bufnr }) end, opts('Toggle inlay hints') ) end end return { { 'neovim/nvim-lspconfig', dependencies = { 'williamboman/mason.nvim', 'williamboman/mason-lspconfig.nvim', 'SmiteshP/nvim-navic', }, lazy = false, config = function() local servers = { basedpyright = { settings = { basedpyright = { typeCheckingMode = 'standard', }, }, }, ruff = {}, clangd = { cmd = { 'clangd', '--compile-commands-dir=build_nvim', '--query-driver', '/opt/cortex-a78-2022.08-gcc12.1-linux5.15/bin/aarch64-linux-gnu-g*', '--clang-tidy', '--background-index', '--use-dirty-headers', '--completion-style=detailed', }, root_markers = { '.clangd', '.clang-tidy', '.clang-format', 'compile_flags.txt', 'configure.ac', '.git', 'build_nvim', }, }, lua_ls = { settings = { Lua = { workspace = { checkThirdParty = false, }, completion = { callSnippet = 'Replace', }, -- Do not send telemetry data containing a randomized but unique identifier telemetry = { enable = false, }, diagnostics = { disable = { 'missing-fields' }, }, format = { enable = false, }, }, }, }, jsonls = {}, dockerls = {}, yamlls = { settings = { yaml = { validate = true, }, }, }, neocmake = {}, markdown_oxide = {}, } require('mason').setup() require('mason-lspconfig').setup({ ensure_installed = vim.tbl_keys(servers or {}), }) local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) vim.lsp.config('*', { capabilities = capabilities, }) for server, settings in pairs(servers) do vim.lsp.config(server, settings) vim.lsp.enable(server) end local lsp_group = vim.api.nvim_create_augroup('UserLspAttach', { clear = true }) vim.api.nvim_create_autocmd('LspAttach', { group = lsp_group, desc = 'Set buffer‑local keymaps and options after an LSP client attaches', callback = function(args) local bufnr = args.buf local client = vim.lsp.get_client_by_id(args.data.client_id) if not client then return end lspKeys(client, bufnr) if client.server_capabilities.completionProvider then vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc' vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr()' end if client.server_capabilities.documentSymbolProvider then local navic = require('nvim-navic') navic.attach(client, bufnr) end end, }) end, }, }