local cmp = require("cmp") local nvim_lsp = require("lspconfig") local cmp_window = require("cmp.utils.window") vim.o.completeopt = "menuone,noselect" vim.o.shortmess = vim.o.shortmess .. "c" local function on_attach(client, bufn) local function map(...) vim.api.nvim_buf_set_keymap(bufn, ...) end local function buf_set_option(...) vim.api.nvim_buf_set_option(bufn, ...) end local opts = { noremap = true, silent = true } map("n", "gD", "lua vim.lsp.buf.declaration()", opts) map("n", "gd", "lua vim.lsp.buf.definition()", opts) map("n", "K", "lua vim.lsp.buf.hover()", opts) map("n", "gi", "lua vim.lsp.buf.implementation()", opts) map("n", "", "lua vim.lsp.buf.signature_help()", opts) map("n", "D", "lua vim.lsp.buf.type_definition()", opts) map("n", "gr", "lua vim.lsp.buf.references()", opts) map("n", "e", "lua vim.lsp.diagnostic.show_line_diagnostics()", opts) map("n", "[d", "lua vim.lsp.diagnostic.goto_prev()", opts) map("n", "]d", "lua vim.lsp.diagnostic.goto_next()", opts) map("n", "q", "lua vim.lsp.diagnostic.set_loclist()", opts) map("n", "ga", "lua vim.lsp.buf.code_action()", opts) end local function has_words_before() 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 function feedkey(key, mode) vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true) end local function border(hl_name) return { { "╭", hl_name }, { "─", hl_name }, { "╮", hl_name }, { "│", hl_name }, { "╯", hl_name }, { "─", hl_name }, { "╰", hl_name }, { "│", hl_name }, } end cmp_window.info_ = cmp_window.info cmp_window.info = function(self) local info = self:info_() info.scrollable = false return info end cmp.setup({ window = { completion = { border = border "CmpBorder", winhighlight = "Normal:CmpPmenu,CursorLine:PmenuSel,Search:None", }, documentation = { border = border "CmpDocBorder" }, }, snippet = { expand = function(args) vim.fn["vsnip#anonymous"](args.body) end, }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete(), [''] = cmp.mapping.abort(), [''] = cmp.mapping.confirm({select = true}), [""] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() elseif vim.fn["vsnip#available"](1) == 1 then feedkey("(vsnip-expand-or-jump)", "") elseif has_words_before() then cmp.complete() else fallback() end end, {"i", "s"}), ["(vsnip-jump-prev)", "") end end, {"i", "s"}), }), sources = cmp.config.sources({ { name = "nvim_lsp" }, { name = "vsnip" }, { name = "treesitter" }, { name = "path", option = { trailing_slash = true }}, { name = "buffer" } }), }) cmp.setup.cmdline(":", { mapping = cmp.mapping.preset.cmdline(), sources = cmp.config.sources({ { name = "path" }, }, { { name = "cmdline" }, }), }) vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( vim.lsp.diagnostic.on_publish_diagnostics, { virtual_text = true, signs = true, update_in_insert = true } ) local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()) local servers = { "ccls", "bashls", "rnix", "texlab", "lua_ls" } for _, lang in pairs(servers) do nvim_lsp[lang].setup({ root_dir = vim.loop.cwd, on_attach = on_attach, capabilities = capabilities }) end require("nvim-treesitter.configs").setup({ highlight = { enable = true, }, }) require("gitsigns").setup({})