Skip to content

Commit 7568de9

Browse files
committed
feat: rework sources again
1 parent 37dbee4 commit 7568de9

File tree

12 files changed

+355
-219
lines changed

12 files changed

+355
-219
lines changed

lua/blink/cmp/accept.lua

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
local utils = {}
22

3+
-- todo: doesnt work when the item contains characters not included in the context regex
4+
35
local function accept(item)
46
local sources = require('blink.cmp.sources.lib')
57
local fuzzy = require('blink.cmp.fuzzy')

lua/blink/cmp/config.lua

+3-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
--- @field blocked_trigger_characters string[]
1616

1717
--- @class blink.cmp.SourceConfig
18-
--- @field providers blink.cmp.SourceProviderConfig[]
18+
--- @field providers blink.cmp.SourceProviderConfig[][]
1919
---
2020
--- @class blink.cmp.SourceProviderConfig
2121
--- @field [1] string
@@ -101,9 +101,8 @@ local config = {
101101
},
102102
sources = {
103103
providers = {
104-
{ 'blink.cmp.sources.lsp' },
105-
{ 'blink.cmp.sources.buffer', score_offset = -9 },
106-
{ 'blink.cmp.sources.snippets', score_offset = -3 },
104+
{ { 'blink.cmp.sources.lsp' }, { 'blink.cmp.sources.snippets', score_offset = -3 } },
105+
{ { 'blink.cmp.sources.buffer', score_offset = -9 } },
107106
},
108107
},
109108
windows = {

lua/blink/cmp/init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ cmp.setup = function(opts)
3434
cmp.fuzzy = require('blink.cmp.fuzzy')
3535
cmp.fuzzy.init_db(vim.fn.stdpath('data') .. '/blink/cmp/fuzzy.db')
3636

37-
cmp.trigger.listen_on_show(function(context) cmp.sources.completions(context) end)
37+
cmp.trigger.listen_on_show(function(context) cmp.sources.request_completions(context) end)
3838
cmp.trigger.listen_on_hide(function()
3939
cmp.sources.cancel_completions()
4040
cmp.windows.autocomplete.close()

lua/blink/cmp/sources/buffer.lua

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ local function words_to_items(words)
4040
kind = vim.lsp.protocol.CompletionItemKind.Text,
4141
insertTextFormat = vim.lsp.protocol.InsertTextFormat.Snippet,
4242
insertText = word,
43-
score_offset = -9,
4443
})
4544
end
4645
return items
@@ -69,7 +68,7 @@ function buffer.new(config) return setmetatable(config, { __index = buffer }) en
6968

7069
function buffer:get_completions(_, callback)
7170
local transformed_callback = function(items)
72-
callback({ is_incomplete_forward = false, is_incomplete_backward = false, items = items })
71+
callback({ is_incomplete_forward = false, is_incomplete_backward = false, context = context, items = items })
7372
end
7473

7574
local buf_text = get_buf_text()

lua/blink/cmp/sources/lib/async.lua

+137-64
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,182 @@
1+
--- Allows chaining of async operations without callback hell
2+
---
13
--- @class blink.cmp.Task
2-
--- @field status 1 | 2 | 3
3-
--- @field result any
4-
--- @field new fun(fn: fun(..., cb: fun(result: any, success: boolean | nil)), ...): blink.cmp.Task
5-
--- @field await fun(self: blink.cmp.Task, cb: fun(success: boolean, result: any))
4+
--- @field status 1 | 2 | 3 | 4
5+
--- @field result any | nil
6+
--- @field error any | nil
7+
--- @field new fun(fn: fun(resolve: fun(result: any), reject: fun(err: any))): blink.cmp.Task
8+
---
69
--- @field cancel fun(self: blink.cmp.Task)
10+
--- @field map fun(self: blink.cmp.Task, fn: fun(result: any): blink.cmp.Task | any)
11+
--- @field catch fun(self: blink.cmp.Task, fn: fun(err: any): blink.cmp.Task | any)
12+
---
13+
--- @field on_completion fun(self: blink.cmp.Task, cb: fun(result: any))
14+
--- @field on_failure fun(self: blink.cmp.Task, cb: fun(err: any))
15+
--- @field on_cancel fun(self: blink.cmp.Task, cb: fun())
716

817
local STATUS = {
918
RUNNING = 1,
1019
COMPLETED = 2,
1120
FAILED = 3,
21+
CANCELLED = 4,
1222
}
1323

14-
local task = {}
24+
local task = {
25+
__task = true,
26+
}
1527

16-
function task.new(fn, ...)
28+
function task.new(fn)
1729
local self = setmetatable({}, { __index = task })
1830
self.status = STATUS.RUNNING
19-
self._awaits = {}
31+
self._completion_cbs = {}
32+
self._failure_cbs = {}
33+
self._cancel_cbs = {}
2034
self.result = nil
35+
self.error = nil
2136

22-
local arg = { ... }
23-
24-
local success, cancel_or_err = pcall(function()
25-
local cb = function(result, success)
26-
if self.status ~= STATUS.RUNNING then return end
27-
if success == false then return self:cancel() end
37+
local resolve = function(result)
38+
if self.status ~= STATUS.RUNNING then return end
2839

29-
self.status = STATUS.COMPLETED
30-
self.result = result
40+
self.status = STATUS.COMPLETED
41+
self.result = result
3142

32-
for _, await_cb in ipairs(self._awaits) do
33-
await_cb(true, result)
34-
end
43+
for _, cb in ipairs(self._completion_cbs) do
44+
cb(result)
3545
end
46+
end
47+
48+
local reject = function(err)
49+
if self.status ~= STATUS.RUNNING then return end
3650

37-
-- todo: why doesnt unpack work?
38-
if #arg == 0 then
39-
return fn(cb)
40-
elseif #arg == 1 then
41-
return fn(arg[1], cb)
42-
elseif #arg == 2 then
43-
return fn(arg[1], arg[2], cb)
51+
self.status = STATUS.FAILED
52+
self.error = err
53+
54+
for _, cb in ipairs(self._failure_cbs) do
55+
cb(err)
4456
end
57+
end
4558

46-
return fn(unpack(arg), cb)
47-
end)
59+
local success, cancel_fn_or_err = pcall(function() return fn(resolve, reject) end)
4860

4961
if not success then
50-
vim.print('Failed to create task :' .. cancel_or_err)
51-
self:cancel()
52-
elseif type(cancel_or_err) ~= 'function' then
53-
vim.print('Cancel is not a function')
54-
vim.print(cancel_or_err)
55-
self:cancel()
56-
else
57-
self._cancel = cancel_or_err
62+
reject(cancel_fn_or_err)
63+
elseif type(cancel_fn_or_err) == 'function' then
64+
self._cancel = cancel_fn_or_err
5865
end
5966

6067
return self
6168
end
6269

6370
function task:cancel()
6471
if self.status ~= STATUS.RUNNING then return end
65-
self.status = STATUS.FAILED
72+
self.status = STATUS.CANCELLED
73+
6674
if self._cancel ~= nil then self._cancel() end
75+
for _, cb in ipairs(self._cancel_cbs) do
76+
cb()
77+
end
78+
end
79+
80+
--- mappings
81+
82+
function task:map(fn)
83+
local chained_task
84+
chained_task = task.new(function(resolve, reject)
85+
self:on_completion(function(result)
86+
local mapped_result = fn(result)
87+
if type(mapped_result) == 'table' and mapped_result.__task then
88+
mapped_result:on_completion(resolve)
89+
mapped_result:on_failure(reject)
90+
mapped_result:on_cancel(function() chained_task:cancel() end)
91+
return
92+
end
93+
resolve(mapped_result)
94+
end)
95+
self:on_failure(reject)
96+
self:on_cancel(function() chained_task:cancel() end)
97+
return function() chained_task:cancel() end
98+
end)
99+
return chained_task
100+
end
101+
102+
function task:catch(fn)
103+
local chained_task
104+
chained_task = task.new(function(resolve, reject)
105+
self:on_completion(resolve)
106+
self:on_failure(function(err)
107+
local mapped_err = fn(err)
108+
if type(mapped_err) == 'table' and mapped_err.is_task then
109+
mapped_err:on_completion(resolve)
110+
mapped_err:on_failure(reject)
111+
mapped_err:on_cancel(function() chained_task:cancel() end)
112+
return
113+
end
114+
resolve(mapped_err)
115+
end)
116+
self:on_cancel(function() chained_task:cancel() end)
117+
return function() chained_task:cancel() end
118+
end)
119+
return chained_task
120+
end
121+
122+
--- events
67123

68-
for _, await_cb in ipairs(self._awaits) do
69-
await_cb(false)
124+
function task:on_completion(cb)
125+
if self.status == STATUS.COMPLETED then
126+
cb(self.result)
127+
elseif self.status == STATUS.RUNNING then
128+
table.insert(self._completion_cbs, cb)
70129
end
130+
return self
71131
end
72132

73-
function task:await(cb)
133+
function task:on_failure(cb)
74134
if self.status == STATUS.FAILED then
75-
cb(false)
76-
elseif self.status == STATUS.COMPLETED then
77-
cb(true, self.result)
78-
else
79-
table.insert(self._awaits, cb)
135+
cb(self.error)
136+
elseif self.status == STATUS.RUNNING then
137+
table.insert(self._failure_cbs, cb)
80138
end
81139
return self
82140
end
83141

84-
function task:map(f)
85-
return task.new(function(cb)
86-
self:await(function(success, result)
87-
if success then
88-
cb(f(result))
89-
else
90-
cb(nil, false)
91-
end
92-
end)
93-
return function() self:cancel() end
94-
end)
142+
function task:on_cancel(cb)
143+
if self.status == STATUS.CANCELLED then
144+
cb()
145+
elseif self.status == STATUS.RUNNING then
146+
table.insert(self._cancel_cbs, cb)
147+
end
148+
return self
95149
end
96150

97-
function task:map_error(f)
98-
return task.new(function(cb)
99-
self:await(function(success, result)
100-
if success then
101-
cb(result)
102-
else
103-
cb(f())
151+
--- utils
152+
153+
function task.await_all(tasks)
154+
return task.new(function(resolve)
155+
local results = {}
156+
157+
local function resolve_if_completed()
158+
-- we can't check #results directly because a table like
159+
-- { [2] = { ... } } has a length of 2
160+
for i = 1, #tasks do
161+
if results[i] == nil then return end
104162
end
105-
end)
106-
return function() self:cancel() end
163+
resolve(results)
164+
end
165+
166+
for idx, task in ipairs(tasks) do
167+
task:on_completion(function(result)
168+
results[idx] = { status = STATUS.COMPLETED, result = result }
169+
resolve_if_completed()
170+
end)
171+
task:on_failure(function(err)
172+
results[idx] = { status = STATUS.FAILED, err = err }
173+
resolve_if_completed()
174+
end)
175+
task:on_cancel(function()
176+
results[idx] = { status = STATUS.CANCELLED }
177+
resolve_if_completed()
178+
end)
179+
end
107180
end)
108181
end
109182

0 commit comments

Comments
 (0)