Skip to content

Commit

Permalink
fix(async): properly trigger callbacks when canceling and fix delays …
Browse files Browse the repository at this point in the history
…in `throttle.sync` (#1611)
  • Loading branch information
folke committed Jun 9, 2023
1 parent b5a636d commit 6f11816
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
3 changes: 1 addition & 2 deletions lua/cmp/entry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,11 @@ entry.match = function(self, input, matching_config)
score, matches = matcher.match(input, filter_text, option)

-- Support the language server that doesn't respect VSCode's behaviors.
local prefix = ''
if score == 0 then
if self:get_completion_item().textEdit and not misc.empty(self:get_completion_item().textEdit.newText) then
local diff = self.source_offset - self:get_offset()
if diff > 0 then
prefix = string.sub(self.context.cursor_line, self:get_offset(), self:get_offset() + diff)
local prefix = string.sub(self.context.cursor_line, self:get_offset(), self:get_offset() + diff)
local accept = nil
accept = accept or string.match(prefix, '^[^%a]+$')
accept = accept or string.find(self:get_completion_item().textEdit.newText, prefix, 1, true)
Expand Down
31 changes: 22 additions & 9 deletions lua/cmp/utils/async.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@ async.throttle = function(fn, timeout)
local timer = assert(vim.loop.new_timer())
local _async = nil ---@type Async?
timers[#timers + 1] = timer
return setmetatable({
local throttle
throttle = setmetatable({
running = false,
timeout = timeout,
sync = function(self, timeout_)
if not self.running then
return
end
vim.wait(timeout_ or 1000, function()
return not self.running
end)
end, 10)
end,
stop = function(reset_time)
if reset_time ~= false then
time = nil
end
-- can't use self here unfortunately
throttle.running = false
timer:stop()
if _async then
_async:cancel()
Expand All @@ -57,9 +63,8 @@ async.throttle = function(fn, timeout)
if time == nil then
time = vim.loop.now()
end

self.running = true
self.stop(false)
self.running = true
timer:start(math.max(1, self.timeout - (vim.loop.now() - time)), 0, function()
vim.schedule(function()
time = nil
Expand All @@ -68,6 +73,7 @@ async.throttle = function(fn, timeout)
---@cast ret Async
_async = ret
_async:await(function(_, error)
_async = nil
self.running = false
if error and error ~= 'abort' then
vim.notify(error, vim.log.levels.ERROR)
Expand All @@ -80,6 +86,7 @@ async.throttle = function(fn, timeout)
end)
end,
})
return throttle
end

---Control async tasks.
Expand Down Expand Up @@ -217,12 +224,18 @@ end
---@param result? any
---@param error? string
function Async:_done(result, error)
self.running = false
self.result = result
self.error = error
if self.running then
self.running = false
self.result = result
self.error = error
end
for _, callback in ipairs(self.callbacks) do
callback(result, error)
end
-- only run each callback once.
-- _done can possibly be called multiple times.
-- so we need to clear callbacks after executing them.
self.callbacks = {}
end

function Async:_step()
Expand All @@ -237,7 +250,7 @@ function Async:_step()
end

function Async:cancel()
self.running = false
self:_done(nil, 'abort')
end

---@param cb AsyncCallback
Expand Down Expand Up @@ -276,7 +289,7 @@ end

-- This will yield when called from a coroutine
function async.yield(...)
if not coroutine.isyieldable() then
if coroutine.running() == nil then
error('Trying to yield from a non-yieldable context')
return ...
end
Expand Down

0 comments on commit 6f11816

Please sign in to comment.