-- stolen from https://github.com/glepnir/nvim with some modifications by me --- add char to list of triggerable chars ---@param list table list of chars ---@param char number|string char to add local function add_to_client(list, char) local c if type(char) == "string" then c = char elseif type(char) == "number" then c = string.char(char) end if not table.contains(list, c) then table.insert(list, c) end end local misc = require("core.misc") local auto = misc.auto local competion_group = misc.augroup("lsp.completion") -- configure the lsp completion menu auto("LspAttach", { group = competion_group, callback = function(ctx) local client = vim.lsp.get_client_by_id(ctx.data.client_id) if not client or not client:supports_method("textDocument/completion") then return end -- Make completion menu appear whenever you type something. local c = client.server_capabilities.completionProvider.triggerCharacters if c then for i = 32, 126 do add_to_client(c, string.char(i)) end end vim.lsp.completion.enable(true, client.id, ctx.buf, { autotrigger = true, convert = function(item) local kind = vim.lsp.protocol.CompletionItemKind[item.kind] or 'u' return { abbr = item.label:gsub('%b()', ''), kind = kind:sub(1, 1):lower(), menu = '' } end }) end }) -- attempt to style the completion documentation popup auto("CompleteChanged", { group = competion_group, callback = function() local info = vim.fn.complete_info({ "selected" }) if info.preview_bufnr and vim.bo[info.preview_bufnr].filetype == "" then vim.bo[info.preview_bufnr].filetype = "markdown" vim.wo[info.preview_winid].conceallevel = 2 vim.wo[info.preview_winid].concealcursor = "niv" end end }) -- Add snippet support to lsp clients who don't do it for us. Currently this -- only supports function calls. -- -- there's a very good chance this will give us problems for languages who do -- not follow the c-style function call style auto("CompleteDonePre", { group = competion_group, callback = function() local item = vim.tbl_get( vim.v.completed_item, "user_data", "nvim", "lsp", "completion_item" ) if not item then return end -- if the item isn't a snippet then we might want to create a snippet if item.label and item.kind and item.insertTextFormat then if item.insertTextFormat ~= 2 and item.kind == 3 then local n_complete_item = vim.v.completed_item -- attempt to modify the function args to create a snippet local paren1 = string.find(item.label, "%(") if not paren1 then return end -- try and create a snippet from a function call local i = 1 local text = "" local l_paren = paren1 local next, is_paren while not is_paren do -- find the next token next = string.find(item.label, "%,", l_paren + 1) if not next then next = string.find(item.label, "%)", l_paren + 1) if not next then return end is_paren = true end -- concat text if text == "" then -- start the snippet text = string.sub(item.label, 0, l_paren).."${"..i..":" else -- continue the snippet text = text.."}, ".."${"..i..":" end do -- add the content of the argument to the snippet -- we need to account for cases in which the developer uses spaces -- between their commas and code local is_space = string.sub(item.label, l_paren + 1, l_paren + 1) local plus = is_space == " " and 2 or 1 text = text..string.sub(item.label, l_paren + plus, next - 1) end -- increment l_paren = next i = i + 1 end -- end the snippet text = text.."})" n_complete_item.user_data.nvim.lsp.completion_item.insertText = text n_complete_item.user_data.nvim.lsp.completion_item.insertTextFormat = 2 vim.v.completed_item = n_complete_item end end end }) -- show the signature help when inside a function call auto("CompleteDone", { group = competion_group, callback = function(ctx) -- make sure there's an lsp client, and make sure the lsp client supports -- textDocument/signatureHelp local client = vim.lsp.get_clients({ bufnr = ctx.buf })[0] if not client or not client[0]:supports_method("textDocument/signatureHelp") then return end -- show the signature help local item = vim.tbl_get( vim.v.completed_item, "user_data", "nvim", "lsp", "completion_item" ) if not item then return end -- show signature help when the completion is a function if item.kind == 3 and (item.textEdit ~= nil or item.insertText ~= nil) then vim.schedule(function() vim.lsp.buf.signature_help() end) end end, desc = "Auto show signature help when completion is done" })