From d31431306060e486eeec28fca3ded31baf4f6d45 Mon Sep 17 00:00:00 2001 From: hrsh7th Date: Mon, 16 Aug 2021 02:36:22 +0900 Subject: [PATCH] Improve menu customize API --- README.md | 18 ++++++++++ lua/cmp/config/default.lua | 48 ++----------------------- lua/cmp/entry.lua | 72 +++++++++++++++++++++++++++++++------- lua/cmp/types/cmp.lua | 2 +- 4 files changed, 81 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 2bf004c..2a39c3f 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,24 @@ vim's `completeopt` setting. Warning: Be careful when changing this value. Default: `menu,menuone,noselect` +### formatting.format (type: fun(entry: cmp.Entry, vim_item: vim.CompletedItem): vim.CompletedItem) + +A function to customize completion menu. + +You can display the fancy icons to completion-menu with [lspkind-nvim](https://github.com/onsails/lspkind-nvim). + +```lua +local lspkind = require('lspkind') +cmp.setup { + formatting = { + format = function(entry, vim_item) + vim_item.kind = lspkind.presets.default[vim_item.kind] + return vim_item + end + } +} +``` + ### sorting.priority_weight (type: number) When sorting completion items before displaying them, boost each item's score diff --git a/lua/cmp/config/default.lua b/lua/cmp/config/default.lua index 23261fb..8428752 100644 --- a/lua/cmp/config/default.lua +++ b/lua/cmp/config/default.lua @@ -53,52 +53,8 @@ return function() mapping = {}, formatting = { - format = function(e, suggest_offset) - local item = e:get_completion_item() - local word = e:get_word() - local abbr = str.trim(item.label) - - -- ~ indicator - if #(misc.safe(item.additionalTextEdits) or {}) > 0 then - abbr = abbr .. '~' - elseif item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then - local insert_text = e:get_insert_text() - if word ~= insert_text then - abbr = abbr .. '~' - end - end - - -- deprecated - if item.deprecated or vim.tbl_contains(item.tags or {}, types.lsp.CompletionItemTag.Deprecated) then - abbr = str.strikethrough(abbr) - end - - -- append delta text - if suggest_offset < e:get_offset() then - word = string.sub(e.context.cursor_before_line, suggest_offset, e:get_offset() - 1) .. word - end - - -- labelDetails. - local menu = nil - if misc.safe(item.labelDetails) then - menu = '' - if misc.safe(item.labelDetails.parameters) then - menu = menu .. item.labelDetails.parameters - end - if misc.safe(item.labelDetails.type) then - menu = menu .. item.labelDetails.type - end - if misc.safe(item.labelDetails.qualifier) then - menu = menu .. item.labelDetails.qualifier - end - end - - return { - word = word, - abbr = abbr, - kind = types.lsp.CompletionItemKind[e:get_kind()] or types.lsp.CompletionItemKind[1], - menu = menu, - } + format = function(_, vim_item) + return vim_item end }, diff --git a/lua/cmp/entry.lua b/lua/cmp/entry.lua index de5b58d..73535c6 100644 --- a/lua/cmp/entry.lua +++ b/lua/cmp/entry.lua @@ -186,24 +186,72 @@ entry.get_insert_text = function(self) end ---Make vim.CompletedItem ----@param suggeset_offset number +---@param suggest_offset number ---@return vim.CompletedItem -entry.get_vim_item = function(self, suggeset_offset) - return self.cache:ensure({ 'get_vim_item', suggeset_offset }, function() - local item = config.get().formatting.format(self, suggeset_offset) - item.equal = 1 - item.empty = 1 - item.dup = self.completion_item.dup or 1 - item.user_data = { cmp = self.id } +entry.get_vim_item = function(self, suggest_offset) + return self.cache:ensure({ 'get_vim_item', suggest_offset, self.resolved_completion_item and 1 or 0 }, function() + local completion_item = self:get_completion_item() + local word = self:get_word() + local abbr = str.trim(completion_item.label) - for i = 1, #item.word - 1 do - if str.has_prefix(self.context.cursor_after_line, string.sub(item.word, i, #item.word)) then - item.word = string.sub(item.word, 1, i - 1) + -- ~ indicator + if #(misc.safe(completion_item.additionalTextEdits) or {}) > 0 then + abbr = abbr .. '~' + elseif completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then + local insert_text = self:get_insert_text() + if word ~= insert_text then + abbr = abbr .. '~' + end + end + + -- deprecated + if completion_item.deprecated or vim.tbl_contains(completion_item.tags or {}, types.lsp.CompletionItemTag.Deprecated) then + abbr = str.strikethrough(abbr) + end + + -- append delta text + if suggest_offset < self:get_offset() then + word = string.sub(self.context.cursor_before_line, suggest_offset, self:get_offset() - 1) .. word + end + + -- labelDetails. + local menu = nil + if misc.safe(completion_item.labelDetails) then + menu = '' + if misc.safe(completion_item.labelDetails.parameters) then + menu = menu .. completion_item.labelDetails.parameters + end + if misc.safe(completion_item.labelDetails.type) then + menu = menu .. completion_item.labelDetails.type + end + if misc.safe(completion_item.labelDetails.qualifier) then + menu = menu .. completion_item.labelDetails.qualifier + end + end + + -- remove duplicated string. + for i = 1, #word - 1 do + if str.has_prefix(self.context.cursor_after_line, string.sub(word, i, #word)) then + word = string.sub(word, 1, i - 1) break end end - return item + local vim_item = { + word = word, + abbr = abbr, + kind = types.lsp.CompletionItemKind[self:get_kind()] or types.lsp.CompletionItemKind[1], + menu = menu, + } + if config.get().formatting.format then + vim_item = config.get().formatting.format(self, vim_item) + end + vim_item.equal = 1 + vim_item.empty = 1 + vim_item.dup = self.completion_item.dup or 1 + vim_item.user_data = { cmp = self.id } + + return vim_item end) end diff --git a/lua/cmp/types/cmp.lua b/lua/cmp/types/cmp.lua index 4e74e6b..d578d1f 100644 --- a/lua/cmp/types/cmp.lua +++ b/lua/cmp/types/cmp.lua @@ -75,7 +75,7 @@ cmp.ScrollDirection.Down = 'down' ---@field public comparators function[] ---@class cmp.FormattingConfig ----@field public format fun(entry: cmp.Entry, suggeset_offset: number): vim.CompletedItem +---@field public format fun(entry: cmp.Entry, vim_item: vim.CompletedItem): vim.CompletedItem ---@class cmp.SnippetConfig ---@field public expand fun(args: cmp.SnippetExpansionParams)