From e4a2cec1539093a62856ec0ca4273acfbfaa6027 Mon Sep 17 00:00:00 2001 From: hrsh7th Date: Fri, 22 Oct 2021 18:23:49 +0900 Subject: [PATCH] Implement source group. Fixes #391 --- README.md | 51 ++++++++++++----------- lua/cmp/config/sources.lua | 10 +++++ lua/cmp/init.lua | 1 + lua/cmp/types/cmp.lua | 1 + lua/cmp/view.lua | 84 +++++++++++++++++++++++--------------- 5 files changed, 90 insertions(+), 57 deletions(-) create mode 100644 lua/cmp/config/sources.lua diff --git a/README.md b/README.md index f77a302..6e0e5b9 100644 --- a/README.md +++ b/README.md @@ -46,18 +46,22 @@ Plug 'hrsh7th/cmp-nvim-lsp' Plug 'hrsh7th/cmp-buffer' Plug 'hrsh7th/nvim-cmp' -" For vsnip user. +" For vsnip users. Plug 'hrsh7th/cmp-vsnip' Plug 'hrsh7th/vim-vsnip' -" For luasnip user. +" For luasnip users. " Plug 'L3MON4D3/LuaSnip' " Plug 'saadparwaiz1/cmp_luasnip' -" For ultisnips user. +" For ultisnips users. " Plug 'SirVer/ultisnips' " Plug 'quangnguyen30192/cmp-nvim-ultisnips' +" For snippy users. +" Plug 'dcampos/nvim-snippy' +" Plug 'dcampos/cmp-snippy' + call plug#end() set completeopt=menu,menuone,noselect @@ -69,14 +73,10 @@ lua <'] = cmp.mapping.close(), [''] = cmp.mapping.confirm({ select = true }), }, - sources = { + sources = cmp.config.sources({ { name = 'nvim_lsp' }, - - -- For vsnip user. - { name = 'vsnip' }, - - -- For luasnip user. - -- { name = 'luasnip' }, - - -- For ultisnips user. - -- { name = 'ultisnips' }, - + { name = 'vsnip' }, -- For vsnip users. + -- { name = 'luasnip' }, -- For luasnip users. + -- { name = 'ultisnips' }, -- For ultisnips users. + -- { name = 'snippy' }, -- For snippy users. + }, { { name = 'buffer' }, + }) } }) -- Setup lspconfig. + local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities()) require('lspconfig')[%YOUR_LSP_SERVER%].setup { - capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities()) + capabilities = capabilities } EOF ``` @@ -241,6 +238,14 @@ The source specific keyword_length for override. The source specific maximum item count. +#### sources[number].group (type: number) + +The source group index. + +This option must be sequential order. + +You can call built-in utility like `cmp.config.sources({ { name = 'a' } }, { { name = 'b' } })`. + #### preselect (type: cmp.PreselectMode) Specify preselect mode. The following modes are available. diff --git a/lua/cmp/config/sources.lua b/lua/cmp/config/sources.lua new file mode 100644 index 0000000..ed46921 --- /dev/null +++ b/lua/cmp/config/sources.lua @@ -0,0 +1,10 @@ +return function(...) + local sources = {} + for i, group in ipairs({ unpack(...) }) do + for _, source in ipairs(group) do + source.group = i + table.insert(sources, source); + end + end + return sources +end diff --git a/lua/cmp/init.lua b/lua/cmp/init.lua index bcada40..4c99b6c 100644 --- a/lua/cmp/init.lua +++ b/lua/cmp/init.lua @@ -18,6 +18,7 @@ cmp.vim = require('cmp.types.vim') ---Export default config presets. cmp.config = {} cmp.config.compare = require('cmp.config.compare') +cmp.config.sources = require('cmp.config.sources') ---Export mapping cmp.mapping = require('cmp.config.mapping') diff --git a/lua/cmp/types/cmp.lua b/lua/cmp/types/cmp.lua index 0778e5a..3d3f4f5 100644 --- a/lua/cmp/types/cmp.lua +++ b/lua/cmp/types/cmp.lua @@ -120,5 +120,6 @@ cmp.ItemField.Menu = 'menu' ---@field public keyword_pattern string ---@field public keyword_length number ---@field public max_item_count number +---@field public group number return cmp diff --git a/lua/cmp/view.lua b/lua/cmp/view.lua index 2e4b662..57d99fa 100644 --- a/lua/cmp/view.lua +++ b/lua/cmp/view.lua @@ -45,51 +45,67 @@ end ---@param ctx cmp.Context ---@param sources cmp.Source[] view.open = function(self, ctx, sources) + local group_index = -1 local entries = {} + while true do + group_index = group_index + 1 - -- check the source triggered by character - local has_triggered_by_symbol_source = false - for _, s in ipairs(sources) do - if #s:get_entries(ctx) > 0 then - if s.is_triggered_by_symbol then - has_triggered_by_symbol_source = true - break - end + local group = vim.tbl_filter(function(s) + return (s:get_config().group or 0) == group_index + end, sources) + + if #group == 0 then + break end - end - -- create filtered entries. - local offset = ctx.cursor.col - for i, s in ipairs(sources) do - if s.offset <= offset then - if not has_triggered_by_symbol_source or s.is_triggered_by_symbol then - -- source order priority bonus. - local priority = s:get_config().priority or ((#sources - (i - 1)) * config.get().sorting.priority_weight) - - for _, e in ipairs(s:get_entries(ctx)) do - e.score = e.score + priority - table.insert(entries, e) - offset = math.min(offset, e:get_offset()) + -- check the source triggered by character + local has_triggered_by_symbol_source = false + for _, s in ipairs(group) do + if #s:get_entries(ctx) > 0 then + if s.is_triggered_by_symbol then + has_triggered_by_symbol_source = true + break end end end - end - -- sort. - local comparetors = config.get().sorting.comparators - table.sort(entries, function(e1, e2) - for _, fn in ipairs(comparetors) do - local diff = fn(e1, e2) - if diff ~= nil then - return diff + -- create filtered entries. + local offset = ctx.cursor.col + for i, s in ipairs(group) do + if s.offset <= offset then + if not has_triggered_by_symbol_source or s.is_triggered_by_symbol then + -- source order priority bonus. + local priority = s:get_config().priority or ((#group - (i - 1)) * config.get().sorting.priority_weight) + + for _, e in ipairs(s:get_entries(ctx)) do + e.score = e.score + priority + table.insert(entries, e) + offset = math.min(offset, e:get_offset()) + end + end end end - end) - -- open - if #entries > 0 then - self:_get_entries_view():open(offset, entries) - else + -- sort. + local comparetors = config.get().sorting.comparators + table.sort(entries, function(e1, e2) + for _, fn in ipairs(comparetors) do + local diff = fn(e1, e2) + if diff ~= nil then + return diff + end + end + end) + + -- open + if #entries > 0 then + self:_get_entries_view():open(offset, entries) + break + end + end + + -- close. + if #entries == 0 then self:close() end end