hrsh7th / nvim-cmp

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

prioritizing snippet over variables/symbols #381

Open kkharji opened 3 years ago

kkharji commented 3 years ago

Hello @hrsh7th, hope your doing great and thanks so muuuch for keeping maintaining this awesome creation ❤️

I'm trying to use lsp snippets more often because how they save a lot of key strokes.

I wonder if nvim-cmp somehow support prioritizing lsp-kinds as well as remove redundant duplications.

Screen Shot 2021-10-20 at 3 11 12 AM

hrsh7th commented 3 years ago

You can add or remove the comparators by yourself.

cmp.setup {

  sorting =  {
    comparators = {
      cmp.config.compare.offset,
      cmp.config.compare.exact,
      cmp.config.compare.score,
      cmp.config.compare.kind,
      cmp.config.compare.sort_text,
      cmp.config.compare.length,
      cmp.config.compare.order,
    }
  }

}

The function accepts entry1, entry2 and you should return true/false/nil.

kkharji commented 3 years ago

🤔 so I need to provide custom fn to replace compare.kind then check if kind == snippet? also does this include ignore duplicates ?

hrsh7th commented 3 years ago

The behavior of removing duplicate entries is not that smart. LSPs and Snippets entries are not specified to remove duplicate entries.

The removing duplicate entries is specified per source (e.g. buffer source will be removed).

kkharji commented 3 years ago

hmm I tried this

    sorting = {
      comparators = {
        cmp.config.compare.offset,
        cmp.config.compare.exact,
        cmp.config.compare.score,
        function(a1, a2)
          if a1 == "Snippet" and a2 == "Variable" or a2 == "Function" then
            return true
          end
          return false
        end,
        cmp.config.compare.sort_text,
        cmp.config.compare.length,
        cmp.config.compare.order,
      },
    },

But doesn't seem to have any influence.

kkharji commented 3 years ago

Yes, clojure-lsp seems to have a lot of duplicates Screen Shot 2021-10-20 at 8 46 35 PM

tzachar commented 3 years ago

hmm I tried this

    sorting = {
      comparators = {
        cmp.config.compare.offset,
        cmp.config.compare.exact,
        cmp.config.compare.score,
        function(a1, a2)
          if a1 == "Snippet" and a2 == "Variable" or a2 == "Function" then
            return true
          end
          return false
        end,
        cmp.config.compare.sort_text,
        cmp.config.compare.length,
        cmp.config.compare.order,
      },
    },

But doesn't seem to have any influence.

The comparator functions get a completion menu item. You need to check the relevant fields (like kind).

kkharji commented 3 years ago

interesting I need to check completion menu item shape. now in rust the situation worse as it shows irreverent snippets when trying to complete a method
Screen Shot 2021-10-25 at 1 14 30 AM

tjdevries commented 3 years ago

Hi, I'm tami and I'm super cool. I program rust & clojure :laughing:

(you can probably turn your comparator function off for rust if you want by checking the filetype)

((btw, me and tami are friends, this is just friendly jokes :smile:))

captainko commented 3 years ago

@tami5 you know you can limit your luasnip source right? For me set luasnip max_item_count to 4 solved the problem.

kkharji commented 3 years ago

Hi, I'm tami and I'm super cool. I program rust & clojure :laughing:

(you can probably turn your comparator function off for rust if you want by checking the filetype)

((btw, me and tami are friends, this is just friendly jokes :smile:))

Oh wow I'm flattered, @tjdevries thinks I'm cool 😜. Though, I always thought it's weird combination 😅. I love them both equally.

I'll try to disable or change it on rust filetype and see. But just to confirm you don't have this behavior right?

@captainko hmmm i don't use luasnip, all these from rust_analyzer server

snaggen commented 2 years ago

I used the default but with the snippet prio reversed to get them at the bottom of the completions, but I really think this should be some simple option, to show Snippets before or after other completions.

     sorting = {
       comparators = {
         cmp.config.compare.offset,
         cmp.config.compare.exact,
         cmp.config.compare.score,
         function(entry1, entry2)
             local kind1 = entry1:get_kind()
             kind1 = kind1 == types.lsp.CompletionItemKind.Text and 100 or kind1
             local kind2 = entry2:get_kind()
             kind2 = kind2 == types.lsp.CompletionItemKind.Text and 100 or kind2
             if kind1 ~= kind2 then
                 if kind1 == types.lsp.CompletionItemKind.Snippet then
                     return false
                 end
                 if kind2 == types.lsp.CompletionItemKind.Snippet then
                     return true
                 end
                 local diff = kind1 - kind2
                 if diff < 0 then
                     return true
                 elseif diff > 0 then
                     return false
                 end
             end
         end,
         cmp.config.compare.sort_text,
         cmp.config.compare.length,
         cmp.config.compare.order,
       },
     },

This also need you to define types before you setup cmp

 local types = require('cmp.types')
hrsh7th commented 2 years ago

Sorry. I can't agree with the opinion that "that the option should be easy to configure".

I think the core should only have primitive configuration way. Otherwise, the public api will not be easily changeable and the project will be difficult to maintain.

For example, the user already can create the following plugins.

local like_vscode = require('cmp-like-vscode')
local cmp = require('cmp')

cmp.setup {
  sorting = {
    comparators = like_vscode.sorting({
      ...
    }),
    formatting = like_vscode.formatting({
      ...
    }),
  }
}
tjdevries commented 2 years ago

There are free GitHub stars to be made by someone doing this. Don't thumbs down our fearless maintainer @hrsh7th . Take it into your own hands and become your own open source legend!

yyy33 commented 2 years ago

You can add or remove the comparators by yourself.

cmp.setup {

  sorting =  {
    comparators = {
      cmp.config.compare.offset,
      cmp.config.compare.exact,
      cmp.config.compare.score,
      cmp.config.compare.kind,
      cmp.config.compare.sort_text,
      cmp.config.compare.length,
      cmp.config.compare.order,
    }
  }

}

The function accepts entry1, entry2 and you should return true/false/nil.

Hello hrsh7th ,cmp.config.compare.recently_used is valid for the current session, the frequency will be recalculated after exiting neovim, do you have a plan to persist it?

hrsh7th commented 2 years ago

No. I hope someone create it as a separated plugin.

trevarj commented 1 year ago

The easiest way to do this for Rust seems to be letting rust-analyzer do the ordering for you:

sorting = {
    priority_weight = 2,
    comparators = {
      compare.order,
      ... -- other comparisons, if you want
    },
  },
ur4ltz commented 1 year ago

I suggest pinning this issues.

zjp-CN commented 7 months ago

For example, the user already can create the following plugins.

I've created one for Rust Analyzer 😃 nvim-cmp-lsp-rs

It also utilizes entry_filter to filter out unwanted prefixes for import methods, and provides dynamic settings like combo to switch between comparators via a key binding.