Skip to content

Commit 127f518

Browse files
authored
feat: add basic event trigger API (#31)
* Add basic event trigger API * Update to check cmp.windows.autocomplete for if the menu is open or closed. * Revert trigger changes
1 parent dd5094a commit 127f518

File tree

6 files changed

+55
-7
lines changed

6 files changed

+55
-7
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,9 @@ The plugin use a 4 stage pipeline: trigger -> sources -> fuzzy -> render
348348

349349
    **Filtering:** The fuzzy matching uses smith-waterman, same as FZF, but implemented in SIMD for ~6x the performance of FZF (todo: add benchmarks). Due to the SIMD's performance, the prefiltering phase on FZF was dropped to allow for typos. Similar to fzy/fzf, additional points are given to prefix matches, characters with capitals (to promote camelCase/PascalCase first char matching) and matches after delimiters (to promote snake_case first char matching)
350350

351-
    **Sorting:** Combines fuzzy matching score with frecency and proximity bonus. Each completion item may also include a `score_offset` which will be added to this score to demote certain sources. The `snippets` source takes advantage of this to avoid taking presedence over the LSP source. The paramaters here still need to be tuned, so please let me know if you find some magical parameters!
351+
    **Sorting:** Combines fuzzy matching score with frecency and proximity bonus. Each completion item may also include a `score_offset` which will be added to this score to demote certain sources. The `snippets` source takes advantage of this to avoid taking precedence over the LSP source. The parameters here still need to be tuned, so please let me know if you find some magical parameters!
352352

353-
**Windows:** Responsible for placing the autocomplete, documentation and function parameters windows. All of the rendering can be overriden following a syntax similar to incline.nvim. It uses the neovim window decoration provider to provide next to no overhead from highlighting.
353+
**Windows:** Responsible for placing the autocomplete, documentation and function parameters windows. All of the rendering can be overridden following a syntax similar to incline.nvim. It uses the neovim window decoration provider to provide next to no overhead from highlighting.
354354

355355
## Compared to nvim-cmp
356356

lua/blink/cmp/fuzzy/init.lua

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
local config = require('blink.cmp.config').fuzzy
22

33
local fuzzy = {
4+
---@type blink.cmp.Context?
5+
last_context = nil,
6+
---@type blink.cmp.CompletionItem[]?
7+
last_items = nil,
48
rust = require('blink.cmp.fuzzy.ffi'),
59
}
610

11+
---@param db_path string
712
function fuzzy.init_db(db_path)
813
fuzzy.rust.init_db(db_path)
914

1015
vim.api.nvim_create_autocmd('VimLeavePre', {
11-
callback = function() fuzzy.rust.destroy_db() end,
16+
callback = fuzzy.rust.destroy_db,
1217
})
1318

1419
return fuzzy
1520
end
1621

22+
---@param item blink.cmp.CompletionItem
1723
function fuzzy.access(item) fuzzy.rust.access(item) end
1824

25+
---@param lines string
1926
function fuzzy.get_words(lines) return fuzzy.rust.get_words(lines) end
2027

28+
---@param needle string
29+
---@param items blink.cmp.CompletionItem[]?
30+
---@return blink.cmp.CompletionItem[]
2131
function fuzzy.filter_items(needle, items)
2232
-- convert to table of strings
2333
local haystack_labels = {}
2434
local haystack_score_offsets = {}
2535
local haystack_kinds = {}
2636
local haystack_sources = {}
37+
38+
items = items or {}
39+
2740
for _, item in ipairs(items) do
2841
table.insert(haystack_labels, item.label)
2942
table.insert(haystack_score_offsets, item.score_offset or 0)
@@ -60,6 +73,9 @@ function fuzzy.filter_items(needle, items)
6073
return filtered_items
6174
end
6275

76+
---@param needle string
77+
---@param context blink.cmp.Context
78+
---@param items blink.cmp.CompletionItem[]?
6379
function fuzzy.filter_items_with_cache(needle, context, items)
6480
if items == nil then
6581
if fuzzy.last_context == nil or fuzzy.last_context.id ~= context.id then return {} end

lua/blink/cmp/init.lua

+6
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ cmp.hide = function()
129129
return true
130130
end
131131

132+
--- @param callback fun(context: blink.cmp.Context)
133+
cmp.on_open = function(callback) cmp.windows.autocomplete.listen_on_open(callback) end
134+
135+
--- @param callback fun()
136+
cmp.on_close = function(callback) cmp.windows.autocomplete.listen_on_close(callback) end
137+
132138
cmp.accept = function()
133139
local item = cmp.windows.autocomplete.get_selected_item()
134140
if item == nil then return end

lua/blink/cmp/sources/buffer.lua

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
local uv = vim.uv
66

7+
---@return string
78
local function get_buf_text()
89
local bufnr = vim.api.nvim_get_current_buf()
910
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
@@ -45,6 +46,8 @@ local function words_to_items(words)
4546
return items
4647
end
4748

49+
--- @param buf_text string
50+
--- @param callback fun(items: blink.cmp.CompletionItem[])
4851
local function run_sync(buf_text, callback) callback(words_to_items(require('blink.cmp.fuzzy').get_words(buf_text))) end
4952

5053
local function run_async(buf_text, callback)

lua/blink/cmp/trigger/completion.lua

+1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ function trigger.hide()
154154
if not trigger.context then return end
155155

156156
trigger.context = nil
157+
157158
trigger.event_targets.on_hide()
158159
end
159160

lua/blink/cmp/windows/autocomplete.lua

+26-4
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@ local config = require('blink.cmp.config')
99
local renderer = require('blink.cmp.windows.lib.render')
1010
local autocmp_config = config.windows.autocomplete
1111
local autocomplete = {
12+
---@type blink.cmp.CompletionItem[]
1213
items = {},
1314
has_selected = nil,
15+
---@type blink.cmp.Context?
1416
context = nil,
1517
event_targets = {
1618
on_position_update = {},
19+
--- @type fun(item: blink.cmp.CompletionItem?, context: blink.cmp.Context)
1720
on_select = function() end,
18-
on_close = function() end,
21+
--- @type table<fun()>
22+
on_close = {},
23+
--- @type table<fun()>
24+
on_open = {},
1925
},
2026
}
2127

@@ -55,11 +61,15 @@ end
5561

5662
---------- Visibility ----------
5763

64+
--- @param context blink.cmp.Context
65+
--- @param items blink.cmp.CompletionItem[]
5866
function autocomplete.open_with_items(context, items)
5967
autocomplete.context = context
6068
autocomplete.items = items
6169
autocomplete.draw()
6270

71+
vim.iter(autocomplete.event_targets.on_open):each(function(callback) callback() end)
72+
6373
autocomplete.win:open()
6474

6575
autocomplete.context = context
@@ -73,6 +83,7 @@ end
7383

7484
function autocomplete.open()
7585
if autocomplete.win:is_open() then return end
86+
vim.iter(autocomplete.event_targets.on_open):each(function(callback) callback() end)
7687
autocomplete.win:open()
7788
autocomplete.set_has_selected(autocmp_config.preselect)
7889
end
@@ -81,9 +92,19 @@ function autocomplete.close()
8192
if not autocomplete.win:is_open() then return end
8293
autocomplete.win:close()
8394
autocomplete.has_selected = autocmp_config.preselect
84-
autocomplete.event_targets.on_close()
95+
96+
vim.iter(autocomplete.event_targets.on_close):each(function(callback) callback() end)
8597
end
86-
function autocomplete.listen_on_close(callback) autocomplete.event_targets.on_close = callback end
98+
99+
--- Add a listener for when the autocomplete window closes
100+
--- @param callback fun()
101+
function autocomplete.listen_on_close(callback) table.insert(autocomplete.event_targets.on_close, callback) end
102+
103+
--- Add a listener for when the autocomplete window opens
104+
--- This is useful for hiding GitHub Copilot ghost text and similar functionality.
105+
---
106+
--- @param callback fun()
107+
function autocomplete.listen_on_open(callback) table.insert(autocomplete.event_targets.on_open, callback) end
87108

88109
--- @param context blink.cmp.Context
89110
--- TODO: Don't switch directions if the context is the same
@@ -203,7 +224,7 @@ function autocomplete.draw()
203224
kind = kind,
204225
kind_icon = kind_icon,
205226
icon_gap = icon_gap,
206-
deprecated = item.deprecated or (item.tags and vim.tbl_contains(item.tags, 1)),
227+
deprecated = item.deprecated or (item.tags and vim.tbl_contains(item.tags, 1)) or false,
207228
})
208229
)
209230
end
@@ -264,6 +285,7 @@ function autocomplete.render_item_reversed(ctx)
264285
}
265286
end
266287

288+
---@return blink.cmp.CompletionItem?
267289
function autocomplete.get_selected_item()
268290
if not autocomplete.win:is_open() then return end
269291
if not autocomplete.has_selected then return end

0 commit comments

Comments
 (0)