hrsh7th / nvim-cmp

A completion plugin for neovim coded in Lua.
MIT License
8.04k stars 398 forks source link

customize completion menu with native CompletionItemKind instead of lspkind-nvim #39

Closed astier closed 3 years ago

astier commented 3 years ago

With nvim-compe I could customize the completion-menu-icons by simply defining the lsp-native CompletionItemKind:

require('vim.lsp.protocol').CompletionItemKind = {
    '', -- 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
}

nvim-cmp doesn't recognize it and your README suggests to use lspkind-nvim which itself uses CompletionItemKind in the background. Is it possible to define completion-menu by myself with CompletionItemKind without lspkind-nvim?

astier commented 3 years ago

Also calling it completion-kind would be probably more correct than completion-menu.

astier commented 3 years ago

I think it would be better if nvim-cmp would simply check for require('vim.lsp.protocol').CompletionItemKind internally by itself. This is the official way to customize it and the only thing lspkind-nvim does is to set require('vim.lsp.protocol').CompletionItemKind anyway. Making lspkind-nvim a dependency is really not necessary.

wimstefan commented 3 years ago

Putting

for index, value in ipairs(vim.lsp.protocol.CompletionItemKind) do
  cmp.lsp.CompletionItemKind[index] = value
end

into my nvim-cmp configuration does the job nicely for me ...

astier commented 3 years ago

Thanks. I think this should be the default. The use user should set it manually.

hrsh7th commented 3 years ago

No... I think the changing defined value to customize is bad idea.

You should return your favorite kind icon via formatting.format instead of modify cmp.lsp.CompletionItemKind

wimstefan commented 3 years ago

No... I think the changing defined value to customize is bad idea.

You should return your favorite kind icon via formatting.format instead of modify cmp.lsp.CompletionItemKind

Hmm I'm afraid I don't understand ... I could not find any help to formatting.format. Could you elaborate a bit more please?

ikalnytskyi commented 3 years ago

@wimstefan There's an example here: https://github.com/hrsh7th/nvim-cmp#formattingformat-type-funentry-cmpentry-vim_item-vimcompleteditem-vimcompleteditem

wimstefan commented 3 years ago

@wimstefan There's an example here: https://github.com/hrsh7th/nvim-cmp#formattingformat-type-funentry-cmpentry-vim_item-vimcompleteditem-vimcompleteditem

Thanks a lot @ikalnytskyi 🙏 Unfortunately my skills are too lousy that I could get that working :/

ikalnytskyi commented 3 years ago

@wimstefan You can take a peek at my configuration:

https://github.com/ikalnytskyi/dotfiles/blob/76e8528b9239a045075130f7c3c6437b19f6870f/nvim/.config/nvim/init.lua#L52-L78 https://github.com/ikalnytskyi/dotfiles/blob/76e8528b9239a045075130f7c3c6437b19f6870f/nvim/.config/nvim/init.lua#L254-L259

astier commented 3 years ago

@ikalnytskyi this might work but I have two objections with this solution.

  1. Isn't vim.lsp.protocol.CompletionItemKind already builtin into neovim-lsp or do I get it wrong? If so than why shouldn't it be used by default by nvim-cmp instead of creating a custom solution for it. nvim-compe recognizes vim.lsp.protocol.CompletionItemKind without any complicated interventions.
  2. I find your solution too complicated to be honest and not intuitive at all. It should be as easy as setting a few variables. Just as it worked with vim.lsp.protocol.CompletionItemKind in nvim-compe.
hrsh7th commented 3 years ago

I say again. the changing vim.lsp.protocol.CompletionItemKind is bad idea.

If some plugin checks vim.lsp.protocol.CompletionItemKind[item.kind] == 'Snippet', this will break with this customization.

ghost commented 3 years ago

Here's an example with codicons.nvim:

  local codicons = require "codicons"
  local codiconsCIK = require("codicons.extensions.completion_item_kind").symbols
  ...
  formatting = {
    format = function(_, vim_item)
      vim_item.kind = codicons.get(codiconsCIK[vim_item.kind].icon)
      return vim_item
    end,
  },
gegoune commented 3 years ago

@hrsh7th I did not realise implications setting vim.lsp.protocol.CompletionItemKind up has. I was then interested to see what lspkind does and it seems like it also modifies it https://github.com/onsails/lspkind-nvim/blob/9cc326504e566f467407bae2669a98963c5404d2/lua/lspkind/init.lua#L100.

Perhaps it should be removed from README if it is such a bad idea and replaced with some safer way?

astier commented 3 years ago

To be honest I still don't really understand why it's a bad thing to set CompletionItemKind. Maybe I just don't get what it purpose is if not defining completion-kind-icons but I trust @hrsh7th if he says so. I always assumed it to be correct because lspkind-nvim sets it internally and nvim-cmp recommends lspkind. Also nvim-compe seems to use CompletionItemKind for the icons. @hrsh7th you can close this issue if you want.

hrsh7th commented 3 years ago

At least, In nvim-cmp, I prefer all menu customixation realises by formatting.format. It's explicit way and super flexisible. For example, you can change icon per source.

hrsh7th commented 3 years ago

Anyway, Thank you for raising a question. It was a good point to me.

astier commented 3 years ago

Just wanted to share my final solution without using any plugins:

formatting = {
  format = function(entry, vim_item)
    vim_item.menu = ({
      nvim_lsp = '',
      buffer   = '',
    })[entry.source.name]
    vim_item.kind = ({
      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 = '',
    })[vim_item.kind]
    return vim_item
  end
},
windwp commented 3 years ago

@hrsh7th @astier i check and the format function run everytime a completion item display

do we need to do that?

hrsh7th commented 3 years ago

The formatting.format is always be cached.

David-Else commented 3 years ago

Regarding https://github.com/microsoft/vscode-codicons, I found the ttf file does not work (at least on Linux). If you download the npm version npm i @vscode/codicons that ttf file version installs fine by double clicking it in Gnome. Once that is done, this solution works great with no plugins:

-- install .ttf file from npm i @vscode/codicons
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 = "  ",
}

  formatting = {
    format = function(_, vim_item)
      vim_item.kind = (cmp_kinds[vim_item.kind] or "") .. vim_item.kind
      return vim_item
    end,
  },

Looking at the FAQ version, it is a little different, and does not define any entry.source.name. I don't really understand the lua (copied it from reddit), is that a problem?