1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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
|