local lsp = require("lsp-zero") vim.diagnostic.config { virtual_text = true } vim.fn.sign_define("DiagnosticSignError", { text = "✘", texthl = "DiagnosticSignError" }) vim.fn.sign_define("DiagnosticSignWarn", { text = "", texthl = "DiagnosticSignWarn" }) vim.fn.sign_define("DiagnosticSignInfo", { text = "", texthl = "DiagnosticSignInfo" }) vim.fn.sign_define("DiagnosticSignHint", { text = "", texthl = "DiagnosticSignHint" }) lsp.ensure_installed({ 'arduino_language_server', 'bashls', 'beancount', 'clangd', 'dockerls', 'docker_compose_language_service', 'lua_ls', 'pyright', 'ruff_lsp', 'taplo', 'yamlls', }) lsp.preset({ name = "recommended", set_lsp_keymaps = false }) lsp.on_attach(function(client, bufnr) require("lsp-format").on_attach(client, bufnr) local map = vim.keymap.set map('n', '[d', 'lua vim.diagnostic.goto_prev()', { buffer = bufnr, desc = 'Previous diagnostic' }) map('n', ']d', 'lua vim.diagnostic.goto_next()', { buffer = bufnr, desc = 'Next diagnostic' }) map('n', '[e', 'lua vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR})', { buffer = bufnr, desc = 'Previous error' }) map('n', ']e', 'lua vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR})', { buffer = bufnr, desc = 'Next error' }) local prefix = require('which-key').register prefix({ ['l'] = { name = "+lsp" } }) map('n', 'li', 'LspInfo', { buffer = bufnr, desc = 'Lsp Info' }) map('n', 'ld', 'lua vim.diagnostic.open_float()', { buffer = bufnr, desc = 'Line diagnostics' }) map('n', 'la', 'lua vim.lsp.buf.code_action()', { buffer = bufnr, desc = 'Codeactions' }) map('n', 'ln', 'lua vim.lsp.buf.rename()', { buffer = bufnr, desc = 'Rename element' }) if vim.fn.exists(':Telescope') then map('n', 'lr', 'Telescope lsp_references()', { buffer = bufnr, desc = 'References' }) map('n', 'lf', 'Telescope lsp_definitions', { buffer = bufnr, desc = 'Definition' }) map('n', 'lt', 'Telescope lsp_type_definitions', { buffer = bufnr, desc = 'Type definition' }) map('n', 'lm', 'Telescope lsp_implementations', { buffer = bufnr, desc = 'Implementation' }) else map('n', 'lr', 'lua vim.lsp.buf.references()', { buffer = bufnr, desc = 'References' }) map('n', 'lf', 'lua vim.lsp.buf.definition()', { buffer = bufnr, desc = 'Definition' }) map('n', 'lt', 'lua vim.lsp.buf.type_definition()', { buffer = bufnr, desc = 'Type definition' }) map('n', 'lm', 'lua vim.lsp.buf.implementation()', { buffer = bufnr, desc = 'Implementation' }) end if client.server_capabilities.document_formatting then map('n', 'lf', "lua vim.lsp.buf.formatting()", { buffer = bufnr, desc = 'Format document' }) end map('n', 'K', 'lua vim.lsp.buf.hover()', { buffer = bufnr, desc = 'Hover definition' }) map('n', 'lc', 'lua vim.lsp.buf.declaration()', { buffer = bufnr, desc = 'Declaration' }) map('n', 'ls', 'lua vim.lsp.buf.signature_help()', { buffer = bufnr, desc = 'Signature help' }) end) lsp.nvim_workspace() -- ensure python virtualenv is determined automatically on lsp start lsp.configure("pyright", { on_attach = function(client, _) local python_path, msg = require('util.pyenv').get_path(client.config .root_dir) vim.notify(string.format('%s\n%s', msg, python_path)) client.config.settings.python.pythonPath = python_path end }) -- set up arduino with the help of arduino.nvim plugin require('lspconfig').arduino_language_server.setup({ on_new_config = require('arduino').on_new_config }) require('lspconfig').lua_ls.setup(lsp.nvim_lua_ls()) lsp.setup() local luasnip = require("luasnip") local has_words_before = function() local line, col = unpack(vim.api.nvim_win_get_cursor(0)) return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil end local kind_icons = { Text = "", Method = "", Function = "", Constructor = "", Field = "", Variable = "", Class = "ﴯ", Interface = "", Module = "", Property = "ﰠ", Unit = "", Value = "", Enum = "", Keyword = "", Snippet = "", Color = "", File = "", Reference = "", Folder = "", EnumMember = "", Constant = "", Struct = "", Event = "", Operator = "", TypeParameter = "" } local cmp = require 'cmp' cmp.setup({ window = { documentation = cmp.config.window.bordered() }, snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end }, sources = { { name = 'nvim_lsp' }, { name = 'otter' }, { name = 'luasnip', keyword_length = 2 }, { name = 'pandoc_references' }, { name = 'nvim_lua' }, { name = 'beancount', option = { account = vim.env["HOME"] .. '/documents/records/budget/main.beancount' -- TODO implement dynamically } }, { name = 'calc' }, { name = 'path' }, { name = 'buffer', keyword_length = 3 }, { name = 'digraphs' }, { name = 'latex_symbols' }, { name = 'spell', keyword_length = 3 }, { name = 'tmux' }, --{ name = 'rg', keyword_length = 5 }, { name = 'vCard' }, }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [""] = cmp.mapping({ i = function(fallback) if cmp.visible() and cmp.get_active_entry() then cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }) else fallback() end end, s = cmp.mapping.confirm({ select = true }), c = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }), -- disable selection in cmd mode }), [""] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() -- You could replace the expand_or_jumpable() calls with expand_or_locally_jumpable() -- they way you will only jump inside the snippet region elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump() elseif has_words_before() then cmp.complete() else fallback() end end, { "i", "s" }), [""] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_prev_item() elseif luasnip.jumpable(-1) then luasnip.jump(-1) else fallback() end end, { "i", "s" }), }), formatting = { fields = { "kind", "abbr", "menu" }, format = function(entry, vim_item) -- Kind icons, removing kind text leaving only icon -- vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) vim_item.kind = string.format('%s', kind_icons[vim_item.kind]) -- Source vim_item.menu = ({ buffer = "[Buf]", calc = "[Cal]", digraphs = "[Dig]", latex_symbols = "[LaTeX]", luasnip = "[Snip]", nvim_lsp = "[Lsp]", nvim_lua = "[Lua]", pandoc_references = "[Bib]", spell = "[Spl]", vCard = "[vCrd]", })[entry.source.name] return vim_item end }, }) -- `/` cmdline setup. cmp.setup.cmdline('/', { mapping = cmp.mapping.preset.cmdline(), sources = { { name = 'buffer' } } }) -- `:` cmdline setup. cmp.setup.cmdline(':', { mapping = cmp.mapping.preset.cmdline(), sources = cmp.config.sources({ { name = 'path' } }, { { name = 'cmdline', option = { ignore_cmds = { 'Man', '!' } } } }) })