-- Native LSP and automatic completion for Neovim 0.12/0.13. -- Requires nvim-lspconfig only for its server presets in runtimepath. -- No nvim-cmp, cmp-nvim-lsp, lspkind, or vsnip required. vim.opt.autocomplete = true vim.opt.complete = 'o' vim.opt.completeopt = { 'menu', 'menuone', 'noselect', 'popup' } vim.opt.shortmess:append('c') -- Keep the old LSP bindings; all are buffer-local. local function map(buf, lhs, rhs, desc) vim.keymap.set('n', lhs, rhs, { buffer = buf, silent = true, desc = desc }) end local group = vim.api.nvim_create_augroup('UserNativeLsp', { clear = true }) vim.api.nvim_create_autocmd('LspAttach', { group = group, 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 -- Completion requests are sent automatically while typing, without cmp. -- C-n/C-p move through suggestions; C-y accepts one; C-e dismisses. if client:supports_method('textDocument/completion') then vim.lsp.completion.enable(true, client.id, bufnr, { autotrigger = true }) end map(bufnr, 'rn', vim.lsp.buf.rename, 'LSP rename') map(bufnr, 'ca', vim.lsp.buf.code_action, 'LSP code action') map(bufnr, '', vim.lsp.buf.hover, 'LSP hover') map(bufnr, 'g0', vim.lsp.buf.document_symbol, 'Document symbols') map(bufnr, 'gW', vim.lsp.buf.workspace_symbol, 'Workspace symbols') map(bufnr, 'gd', vim.lsp.buf.definition, 'Go to definition') map(bufnr, 'gD', vim.lsp.buf.declaration, 'Go to declaration') map(bufnr, 'gi', vim.lsp.buf.implementation, 'Go to implementation') map(bufnr, 'gr', vim.lsp.buf.references, 'Find references') map(bufnr, '', vim.lsp.buf.signature_help, 'Signature help') map(bufnr, 'g', vim.lsp.buf.type_definition, 'Type definition') map(bufnr, '[d', function() vim.diagnostic.jump({ count = -1 }) end, 'Previous diagnostic') map(bufnr, ']d', function() vim.diagnostic.jump({ count = 1 }) end, 'Next diagnostic') vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc' vim.opt_local.signcolumn = 'yes' if client:supports_method('textDocument/documentHighlight') then -- Per-buffer autocommands, shared across clients to avoid duplicates. local hlgroup = vim.api.nvim_create_augroup('UserLspHighlight' .. bufnr, { clear = true }) vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { group = hlgroup, buffer = bufnr, callback = vim.lsp.buf.document_highlight, }) vim.api.nvim_create_autocmd({ 'CursorMoved', 'InsertLeave' }, { group = hlgroup, buffer = bufnr, callback = vim.lsp.buf.clear_references, }) end end, }) vim.diagnostic.config({ signs = { text = { [vim.diagnostic.severity.ERROR] = '✘', [vim.diagnostic.severity.WARN] = '▲', [vim.diagnostic.severity.INFO] = '●', [vim.diagnostic.severity.HINT] = '◆' } }, underline = true, severity_sort = true, }) -- nvim-lspconfig's modern lsp/*.lua presets supply cmd, filetypes and root detection. -- Only list your desired servers and their overrides here. local servers = { bashls = { filetypes = { 'bash', 'sh' } }, clangd = { filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda' } }, mlir = {}, jqls = {}, lua_ls = { settings = { Lua = { runtime = { version = 'LuaJIT' }, workspace = { checkThirdParty = false, library = { vim.env.VIMRUNTIME } }, }, }, }, ocamllsp = {}, perlpls = {}, rust_analyzer = {}, verible = {}, vimls = {}, zls = {}, texlab = {}, hls = { settings = { haskell = { plugin = { semanticTokens = { globalOn = true } } } } }, pylsp = { settings = { pylsp = { plugins = { pycodestyle = { enabled = false } } } } }, } for name, overrides in pairs(servers) do vim.lsp.config(name, overrides) vim.lsp.enable(name) end vim.keymap.set('i', '', function() if vim.fn.pumvisible() == 1 then return '' end return '' end, { expr = true, desc = 'Accept completion or insert Tab' }) local fallbacks = { Pmenu = 'NormalFloat', PmenuSel = 'Visual', PmenuKind = 'Type', PmenuKindSel = 'Type', PmenuExtra = 'Comment', PmenuExtraSel = 'Comment', PmenuMatch = 'Identifier', PmenuMatchSel = 'Identifier', PmenuBorder = 'FloatBorder', } local function apply_fallbacks() for group, target in pairs(fallbacks) do local hl = vim.api.nvim_get_hl(0, { name = group, link = true }) if vim.tbl_isempty(hl) or hl.link == 'Pmenu' then vim.api.nvim_set_hl(0, group, { link = target }) end end end vim.api.nvim_create_autocmd('ColorScheme', { callback = apply_fallbacks, }) apply_fallbacks() vim.opt.pumheight = 12 vim.opt.pummaxwidth = 70 vim.opt.pumblend = 0