Skip to content

Timer inside FocusLost autocmd never stops after FocusGained and consider making that timer a one-shot instead of repeating #17

@canova

Description

@canova

Hey, thanks for the plugin! I just came across it and I wanted to use it. I was looking into the code before adding it to my plugins and came across 2 things. The issue title essentially mentions 2 issues, but they are intertwined, that's why I think it's good to talk about them together in a single issue.

1. FocusLost timer never stops in some cases:

First thing I noticed is that we add a timer in the FocusLost autocmd function here:

timer:start(1000, 1000, vim.schedule_wrap(function()
-- Update timer state
current_time = os.time()
elapsed_time = current_time - start_time
grace_period_exceeded = elapsed_time >= config.grace_period
-- Grace period exceeded? Stop LSP
if grace_period_exceeded and not lsp_has_been_stopped then
timer:stop()
utils.stop_lsp()
if config.notifications then utils.notify("lsp_has_stopped") end
lsp_has_been_stopped = true
end
end))

We only stop it here, once the timeout is exceeded and when we want to stop the LSP:

But we need need to think about the case where we gain the focus and run the FocusGained autocmd before LSP gets stopped. In that case we run this:

vim.api.nvim_create_autocmd("FocusGained", {
callback = function()
local config = vim.g.garbage_day_config
wakeup_delay_counting = true
vim.defer_fn(function()
-- if the mouse leave nvim before wakeup_delay ends, don't awake.
if wakeup_delay_counting then
-- Start LSP
if lsp_has_been_stopped then
utils.start_lsp()
if config.notifications then utils.notify("lsp_has_started") end
end
-- Reset state
start_time = os.time()
current_time = 0
elapsed_time = 0
grace_period_exceeded = false
lsp_has_been_stopped = false
end
end, config.wakeup_delay)
end
})

But it never actually calls timer:stop(), so that's why the initial timer keeps running while neovim has focus. I think this is not intended, and we should just stop the timer for that case. Since FocusLost already has timer:start call, it will successfully start it again once the focus is lost.

2. This timer should probably be a one-shot timer instead of repeating every 1 second

Second thing I noticed is that this timer is a repeating timer with timer:start(1000, 1000, vim.schedule_wrap(function() .... But as far as I can see, there is no reason to make it a repeating timer. We just check if elapsed_time is larger than config.grace_period and stop the LSP in that case.

I believe this can be done by changing this timer to something like this: timer:start(config.grace_period * 1000, 0, vim.schedule_wrap(function() ... And that way we can remove the grace_period_exceeded check inside. When this gets fired we know that it's exceeded.

But I might be missing something with the limited knowledge of the plugin just by reading for a bit. Please let me know what you think and if my assumptions are not correct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions