Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions lua/blink/cmp/lib/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,53 @@ function utils.slice(arr, start, finish)
return sliced
end

--- Generates a random string of length n
--- @param n number
--- @return string
function utils.random_string(n)
n = n or 10
local str = ''
for _ = 1, n do
str = str .. string.char(math.random(97, 122))
end
return str
end

--- Runs a function on an interval until it returns false or the timeout is reached
--- @param fn fun(): false?
--- @param opts { interval_ms: number, timeout_ms: number }
--- @return fun() Cancels the timer
function utils.run_on_interval(fn, opts)
local start_time = vim.uv.now()
local timer = vim.uv.new_timer()

local function check()
-- Check if we've exceeded the timeout
if (vim.uv.now() - start_time) >= opts.timeout_ms then
timer:stop()
timer:close()
return
end

-- Run the function and check its result
local result = fn()
if result == false then
timer:stop()
timer:close()
return
end
end

-- Run immediately first
check()

-- Then set up the interval
timer:start(0, opts.interval_ms, vim.schedule_wrap(check))

return function()
timer:stop()
timer:close()
end
end

return utils
11 changes: 9 additions & 2 deletions lua/blink/cmp/sources/lib/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ function sources.resolve(item)
break
end
end
if item_source == nil then return async.task.new(function(resolve) resolve(item) end) end
if item_source == nil then
return async.task.new(function(resolve) resolve(item) end)
end

return item_source:resolve(item):catch(function(err) vim.print('failed to resolve item with error: ' .. err) end)
end
Expand All @@ -183,7 +185,9 @@ function sources.execute(context, item)
break
end
end
if item_source == nil then return async.task.new(function(resolve) resolve() end) end
if item_source == nil then
return async.task.new(function(resolve) resolve() end)
end

return item_source
:execute(context, item)
Expand Down Expand Up @@ -247,6 +251,9 @@ end

function sources.get_lsp_capabilities(override, include_nvim_defaults)
return vim.tbl_deep_extend('force', include_nvim_defaults and vim.lsp.protocol.make_client_capabilities() or {}, {
window = {
workDoneProgress = true,
},
textDocument = {
completion = {
completionItem = {
Expand Down
18 changes: 17 additions & 1 deletion lua/blink/cmp/sources/lsp.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local utils = require('blink.cmp.lib.utils')
local known_defaults = {
'commitCharacters',
'editRange',
Expand Down Expand Up @@ -79,6 +80,7 @@ function lsp:get_completions(context, callback)
if context.trigger.kind == CompletionTriggerKind.TriggerCharacter then
params.context.triggerCharacter = context.trigger.character
end
params.partialResultToken = utils.random_string(32)

local _, request_id = client.request('textDocument/completion', params, function(err, result)
if err or result == nil then return end
Expand Down Expand Up @@ -106,6 +108,18 @@ function lsp:get_completions(context, callback)
is_incomplete_backward = true,
items = items,
})

vim.print(client.server_capabilities.completionProvider.workDoneProgress)
if client.server_capabilities.completionProvider.workDoneProgress then
utils.run_on_interval(function()
local latest_progress = client.progress:peek()
if latest_progress ~= nil then vim.print(latest_progress) end
if latest_progress == nil or latest_progress.params.token ~= params.partialResultToken then return end

client.progress:pop()
vim.print('got progress')
end, { interval_ms = 5, timeout_ms = 15000 })
end
end)
if request_id ~= nil then cancel_fns[#cancel_fns + 1] = function() client.cancel_request(request_id) end end
end
Expand Down Expand Up @@ -134,7 +148,9 @@ function lsp:resolve(item, callback)
callback(resolved_item)
end)
if not success then callback(item) end
if request_id ~= nil then return function() client.cancel_request(request_id) end end
if request_id ~= nil then
return function() client.cancel_request(request_id) end
end
end

--- Signature help ---
Expand Down
Loading