perf: async cache initialization and remove deepcopy (#8)

* perf: async cache initialization and remove deepcopy

Problem: first completion request blocked the UI with a synchronous
vim.system():wait() call, and every subsequent key completion
unnecessarily deep-copied the entire cache.

Solution: use vim.system with an async callback to initialize the cache
without blocking. Queue pending completion requests during loading and
serve them once parsing finishes. Return cached keys directly instead
of deep-copying.

* fix: revert blanket diagnostics.disable and selene comments

Problem: .luarc.json blanket-disabled four diagnostic categories
project-wide, and selene inline directives were added to suppress
warnings on io.open monkey-patching in tests.

Solution: revert .luarc.json to match main and remove selene comments.
This commit is contained in:
Barrett Ruth 2026-02-20 21:01:21 -05:00 committed by GitHub
parent b5b18520d7
commit 072859ce04
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 56 additions and 15 deletions

View file

@ -5,6 +5,9 @@ local M = {}
local keys_cache = nil
---@type table<string, string[]>?
local enums_cache = nil
local loading = false
---@type {ctx: blink.cmp.Context, callback: fun(response: blink.cmp.CompletionResponse)}[]
local pending = {}
function M.new()
return setmetatable({}, { __index = M })
@ -37,14 +40,14 @@ function M.enabled()
return false
end
---@param stdout string
---@return blink.cmp.CompletionItem[]
local function parse_keys()
local function parse_keys(stdout)
local Kind = require('blink.cmp.types').CompletionItemKind
local result = vim.system({ 'ghostty', '+show-config', '--docs' }):wait()
local items = {}
local doc_lines = {}
for line in ((result.stdout or '') .. '\n'):gmatch('(.-)\n') do
for line in (stdout .. '\n'):gmatch('(.-)\n') do
if line:match('^#') then
local stripped = line:gsub('^# ?', '')
doc_lines[#doc_lines + 1] = stripped
@ -101,13 +104,10 @@ end
---@param ctx blink.cmp.Context
---@param callback fun(response: blink.cmp.CompletionResponse)
---@return fun()
function M:get_completions(ctx, callback)
local function respond(ctx, callback)
if not keys_cache or not enums_cache then
keys_cache = parse_keys()
enums_cache = parse_enums()
return
end
local line = ctx.line
local col = ctx.cursor[2]
local eq_pos = line:find('=')
@ -130,16 +130,42 @@ function M:get_completions(ctx, callback)
is_incomplete_backward = false,
items = items,
})
return function() end
return
end
callback({ items = {} })
else
callback({
is_incomplete_forward = false,
is_incomplete_backward = false,
items = vim.deepcopy(keys_cache),
items = keys_cache,
})
end
end
---@param ctx blink.cmp.Context
---@param callback fun(response: blink.cmp.CompletionResponse)
---@return fun()
function M:get_completions(ctx, callback)
if keys_cache then
respond(ctx, callback)
return function() end
end
pending[#pending + 1] = { ctx = ctx, callback = callback }
if not loading then
loading = true
vim.system({ 'ghostty', '+show-config', '--docs' }, {}, function(result)
vim.schedule(function()
keys_cache = parse_keys(result.stdout or '')
enums_cache = parse_enums()
loading = false
for _, p in ipairs(pending) do
respond(p.ctx, p.callback)
end
pending = {}
end)
end)
end
return function() end
end