summaryrefslogtreecommitdiff
path: root/lua/blink/cmp/config/sources.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/blink/cmp/config/sources.lua')
-rw-r--r--lua/blink/cmp/config/sources.lua149
1 files changed, 149 insertions, 0 deletions
diff --git a/lua/blink/cmp/config/sources.lua b/lua/blink/cmp/config/sources.lua
new file mode 100644
index 0000000..ab06b5f
--- /dev/null
+++ b/lua/blink/cmp/config/sources.lua
@@ -0,0 +1,149 @@
+--- @class blink.cmp.SourceConfig
+--- Static list of providers to enable, or a function to dynamically enable/disable providers based on the context
+---
+--- Example dynamically picking providers based on the filetype and treesitter node:
+--- ```lua
+--- function(ctx)
+--- local node = vim.treesitter.get_node()
+--- if vim.bo.filetype == 'lua' then
+--- return { 'lsp', 'path' }
+--- elseif node and vim.tbl_contains({ 'comment', 'line_comment', 'block_comment' }), node:type())
+--- return { 'buffer' }
+--- else
+--- return { 'lsp', 'path', 'snippets', 'buffer' }
+--- end
+--- end
+--- ```
+--- @field default string[] | fun(): string[]
+--- @field per_filetype table<string, string[] | fun(): string[]>
+--- @field cmdline string[] | fun(): string[]
+---
+--- @field transform_items fun(ctx: blink.cmp.Context, items: blink.cmp.CompletionItem[]): blink.cmp.CompletionItem[] Function to transform the items before they're returned
+--- @field min_keyword_length number | fun(ctx: blink.cmp.Context): number Minimum number of characters in the keyword to trigger
+---
+--- @field providers table<string, blink.cmp.SourceProviderConfig>
+
+--- @class blink.cmp.SourceProviderConfig
+--- @field name string
+--- @field module string
+--- @field enabled? boolean | fun(): boolean Whether or not to enable the provider
+--- @field opts? table
+--- @field async? boolean | fun(ctx: blink.cmp.Context): boolean Whether blink should wait for the source to return before showing the completions
+--- @field timeout_ms? number | fun(ctx: blink.cmp.Context): number How long to wait for the provider to return before showing completions and treating it as asynchronous
+--- @field transform_items? fun(ctx: blink.cmp.Context, items: blink.cmp.CompletionItem[]): blink.cmp.CompletionItem[] Function to transform the items before they're returned
+--- @field should_show_items? boolean | fun(ctx: blink.cmp.Context, items: blink.cmp.CompletionItem[]): boolean Whether or not to show the items
+--- @field max_items? number | fun(ctx: blink.cmp.Context, items: blink.cmp.CompletionItem[]): number Maximum number of items to display in the menu
+--- @field min_keyword_length? number | fun(ctx: blink.cmp.Context): number Minimum number of characters in the keyword to trigger the provider
+--- @field fallbacks? string[] | fun(ctx: blink.cmp.Context, enabled_sources: string[]): string[] If this provider returns 0 items, it will fallback to these providers
+--- @field score_offset? number | fun(ctx: blink.cmp.Context, enabled_sources: string[]): number Boost/penalize the score of the items
+--- @field deduplicate? blink.cmp.DeduplicateConfig TODO: implement
+--- @field override? blink.cmp.SourceOverride Override the source's functions
+
+local validate = require('blink.cmp.config.utils').validate
+local sources = {
+ --- @type blink.cmp.SourceConfig
+ default = {
+ default = { 'lsp', 'path', 'snippets', 'buffer' },
+ per_filetype = {},
+ cmdline = function()
+ local type = vim.fn.getcmdtype()
+ -- Search forward and backward
+ if type == '/' or type == '?' then return { 'buffer' } end
+ -- Commands
+ if type == ':' or type == '@' then return { 'cmdline' } end
+ return {}
+ end,
+
+ transform_items = function(_, items) return items end,
+ min_keyword_length = 0,
+
+ providers = {
+ lsp = {
+ name = 'LSP',
+ module = 'blink.cmp.sources.lsp',
+ fallbacks = { 'buffer' },
+ transform_items = function(_, items)
+ -- demote snippets
+ for _, item in ipairs(items) do
+ if item.kind == require('blink.cmp.types').CompletionItemKind.Snippet then
+ item.score_offset = item.score_offset - 3
+ end
+ end
+
+ -- filter out text items, since we have the buffer source
+ return vim.tbl_filter(
+ function(item) return item.kind ~= require('blink.cmp.types').CompletionItemKind.Text end,
+ items
+ )
+ end,
+ },
+ path = {
+ name = 'Path',
+ module = 'blink.cmp.sources.path',
+ score_offset = 3,
+ fallbacks = { 'buffer' },
+ },
+ snippets = {
+ name = 'Snippets',
+ module = 'blink.cmp.sources.snippets',
+ score_offset = -3,
+ },
+ buffer = {
+ name = 'Buffer',
+ module = 'blink.cmp.sources.buffer',
+ score_offset = -3,
+ },
+ cmdline = {
+ name = 'cmdline',
+ module = 'blink.cmp.sources.cmdline',
+ },
+ },
+ },
+}
+
+function sources.validate(config)
+ assert(
+ config.completion == nil,
+ '`sources.completion.enabled_providers` has been replaced with `sources.default`. !!Note!! Be sure to update `opts_extend` as well if you have it set'
+ )
+
+ validate('sources', {
+ default = { config.default, { 'function', 'table' } },
+ per_filetype = { config.per_filetype, 'table' },
+ cmdline = { config.cmdline, { 'function', 'table' } },
+
+ transform_items = { config.transform_items, 'function' },
+ min_keyword_length = { config.min_keyword_length, { 'number', 'function' } },
+
+ providers = { config.providers, 'table' },
+ }, config)
+ for id, provider in pairs(config.providers) do
+ sources.validate_provider(id, provider)
+ end
+end
+
+function sources.validate_provider(id, provider)
+ assert(
+ provider.fallback_for == nil,
+ '`fallback_for` has been replaced with `fallbacks` which work in the opposite direction. For example, fallback_for = { "lsp" } on "buffer" would now be "fallbacks" = { "buffer" } on "lsp"'
+ )
+
+ validate('sources.providers.' .. id, {
+ name = { provider.name, 'string' },
+ module = { provider.module, 'string' },
+ enabled = { provider.enabled, { 'boolean', 'function' }, true },
+ opts = { provider.opts, 'table', true },
+ async = { provider.async, { 'boolean', 'function' }, true },
+ timeout_ms = { provider.timeout_ms, { 'number', 'function' }, true },
+ transform_items = { provider.transform_items, 'function', true },
+ should_show_items = { provider.should_show_items, { 'boolean', 'function' }, true },
+ max_items = { provider.max_items, { 'number', 'function' }, true },
+ min_keyword_length = { provider.min_keyword_length, { 'number', 'function' }, true },
+ fallbacks = { provider.fallback_for, { 'table', 'function' }, true },
+ score_offset = { provider.score_offset, { 'number', 'function' }, true },
+ deduplicate = { provider.deduplicate, 'table', true },
+ override = { provider.override, 'table', true },
+ }, provider)
+end
+
+return sources