local on_attach = function(_, bufnr) local nmap = function(keys, func, desc) if desc then desc = 'LSP: ' .. desc end vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) end nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') nmap('gI', vim.lsp.buf.implementation, '[G]oto [I]mplementation') nmap('D', vim.lsp.buf.type_definition, 'Type [D]efinition') nmap('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') nmap('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') -- See `:help K` for why this keymap nmap('K', vim.lsp.buf.hover, 'Hover Documentation') nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') -- Lesser used LSP functionality nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') nmap('wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, '[W]orkspace [L]ist Folders') -- Create a command `:Format` local to the LSP buffer vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) vim.lsp.buf.format() end, { desc = 'Format current buffer with LSP' }) end local servers = { lua_ls = { Lua = { workspace = { checkThirdParty = false }, telemetry = { enable = false }, }, }, } -- Setup neovim lua configuration require('neodev').setup() -- nvim-cmp supports additional completion capabilities, so broadcast that to servers local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) -- Ensure the servers above are installed local mason_lspconfig = require 'mason-lspconfig' mason_lspconfig.setup { ensure_installed = vim.tbl_keys(servers), } mason_lspconfig.setup_handlers { function(server_name) require('lspconfig')[server_name].setup { capabilities = capabilities, on_attach = on_attach, settings = servers[server_name], } end, } local lsp = require('lspconfig') local configs = require('lspconfig.configs') configs.jails = { default_config = { cmd = {'jails.exe'}, filetypes = {'jai'}, root_dir = function(fname) return lsp.util.find_git_ancestor(fname) end, name = 'jails', settinsgs = {} } } lsp.jails.setup { capabilities = capabilities, on_attach = on_attach } local sign_cfg = { } require('lsp_signature').setup(sign_cfg); -- Diagnostic symbols in the sign column (gutter) local signs = { Error = " ", Warn = " ", Info = " ", Hint = " " } for type, icon in pairs(signs) do local hl = "DiagnosticSign" .. type vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" }) end vim.diagnostic.config({ virtual_text = { prefix = "●" }, signs = true, update_in_insert = true, underline = false, severity_sort = true, float = { border = "rounded", source = "always", header = "", prefix = "", }, }) vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( vim.lsp.diagnostic.on_publish_diagnostics, { underline = false, update_in_insert = false, virtual_text = { spacing = 4, prefix = "●" }, severity_sort = true, }) vim.lsp.handlers["textDocument/hover"] = vim.lsp.with( vim.lsp.handlers.hover, {border = "rounded"} ) vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with( vim.lsp.handlers.signature_help, {border = "rounded"} ) vim.cmd [[ " make hover window"s background transparent highlight! link FloatBorder Normal highlight! link NormalFloat Normal ]] -- nvim-cmp setup local cmp = require 'cmp' local luasnip = require 'luasnip' luasnip.config.setup {} 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 cmp_kinds = { 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 = "" } cmp.setup { snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, }, window = { completion = { winhighlight = "Normal:Pmenu,FloatBorder:Pmenu,Search:None", }, documentation = { border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, }, }, mapping = cmp.mapping.preset.insert { [''] = cmp.mapping.select_next_item(), [''] = cmp.mapping.select_prev_item(), [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete {}, [''] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false, }, [''] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump() 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' }), }, sources = { { name = 'nvim_lsp' }, { name = 'luasnip' }, { name = 'buffer' }, option = { get_bufnrs = function() local bufs = {} for _, win in ipairs(vim.api.nvim_list_wins()) do bufs[vim.api.nvim_win_get_buf(win)] = true end return vim.tbl_keys(bufs) end } }, formatting = { fields = { "kind", "abbr", "menu" }, format = function(entry, vim_item) vim_item.kind = cmp_kinds[vim_item.kind] or "" local lsp_icon = "🅻" if lsp ~= nil and lsp.ocamllsp ~= nil then lsp_icon = "🐫" end vim_item.menu = ({ buffer = "🅱", nvim_lsp = lsp_icon, luasnip = "㊊" })[entry.source.name] return vim_item end, } }