Skip to content

Commit

Permalink
fix: reduce flicker of extmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
saecki committed Sep 2, 2024
1 parent 7762778 commit b3b9ac6
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 63 deletions.
25 changes: 17 additions & 8 deletions lua/crates/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ M.load_crate = async.wrap(function(crate_name)
end

if c:package() == crate_name and vim.api.nvim_buf_is_loaded(buf) then
local info, c_diagnostics = diagnostic.process_api_crate(c, crate)
local c_diagnostics = {}
local info = diagnostic.process_api_crate(c, crate, c_diagnostics)
cache.info[k] = info
vim.list_extend(cache.diagnostics, c_diagnostics)

ui.display_crate_info(buf, info, c_diagnostics)
ui.display_crate_info(buf, { info })
ui.display_diagnostics(buf, {}, c_diagnostics)
end

::continue::
Expand Down Expand Up @@ -71,8 +73,9 @@ local function update(buf, reload)
}
state.buf_cache[buf] = cache

ui.clear(buf)
ui.display_diagnostics(buf, diagnostics)
local crates_info = {}
local crates_loading = {}
local custom_diagnostics = {}
for k, c in pairs(crate_cache) do
-- Don't try to fetch info from crates.io if it's a local or git crate,
-- or from a registry other than crates.io
Expand All @@ -83,14 +86,13 @@ local function update(buf, reload)

local api_crate = state.api_cache[c:package()]
if not reload and api_crate then
local info, c_diagnostics = diagnostic.process_api_crate(c, api_crate)
local info = diagnostic.process_api_crate(c, api_crate, custom_diagnostics)
cache.info[k] = info
vim.list_extend(cache.diagnostics, c_diagnostics)

ui.display_crate_info(buf, info, c_diagnostics)
table.insert(crates_info, info)
else
if state.cfg.loading_indicator then
ui.display_loading(buf, c)
table.insert(crates_loading, c)
end

M.load_crate(c:package())
Expand All @@ -99,6 +101,13 @@ local function update(buf, reload)
::continue::
end

ui.clear(buf)
ui.display_crate_info(buf, crates_info)
ui.display_loading(buf, crates_loading)
ui.display_diagnostics(buf, diagnostics, custom_diagnostics)

vim.list_extend(cache.diagnostics, custom_diagnostics)

local callbacks = M.throttled_updates[buf]
if callbacks then
for _, callback in ipairs(callbacks) do
Expand Down
8 changes: 4 additions & 4 deletions lua/crates/diagnostic.lua
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,10 @@ end

---@param crate TomlCrate
---@param api_crate ApiCrate?
---out parameter, diagnostics are appended
---@param diagnostics CratesDiagnostic[]
---@return CrateInfo
---@return CratesDiagnostic[]
function M.process_api_crate(crate, api_crate)
function M.process_api_crate(crate, api_crate, diagnostics)
local versions = api_crate and api_crate.versions
local newest, newest_pre, newest_yanked = util.get_newest(versions, nil)
newest = newest or newest_pre or newest_yanked
Expand All @@ -252,7 +253,6 @@ function M.process_api_crate(crate, api_crate)
vers_line = crate.vers and crate.vers.line or crate.lines.s,
match_kind = MatchKind.NOMATCH,
}
local diagnostics = {}

if crate.dep_kind == DepKind.REGISTRY then
if api_crate then
Expand Down Expand Up @@ -366,7 +366,7 @@ function M.process_api_crate(crate, api_crate)
end
end

return info, diagnostics
return info
end

return M
104 changes: 53 additions & 51 deletions lua/crates/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ end
---comment
---@param buf integer
---@param diagnostics CratesDiagnostic[]
function M.display_diagnostics(buf, diagnostics)
---@param custom_diagnostics CratesDiagnostic[]
function M.display_diagnostics(buf, diagnostics, custom_diagnostics)
if not state.visible then
return
end
Expand All @@ -70,77 +71,78 @@ function M.display_diagnostics(buf, diagnostics)
local vim_diagnostic = to_vim_diagnostic(d)
table.insert(buf_state.diagnostics, vim_diagnostic)
end
for _, d in ipairs(custom_diagnostics) do
local vim_diagnostic = to_vim_diagnostic(d)
table.insert(buf_state.custom_diagnostics, vim_diagnostic)
end

vim.diagnostic.set(DIAGNOSTIC_NS, buf, buf_state.diagnostics)
vim.diagnostic.set(DIAGNOSTIC_NS, buf, buf_state.diagnostics, {})
vim.diagnostic.set(CUSTOM_NS, buf, buf_state.custom_diagnostics, { virtual_text = false })
end

---@param buf integer
---@param info CrateInfo
---@param diagnostics CratesDiagnostic[]
function M.display_crate_info(buf, info, diagnostics)
---@param infos CrateInfo[]
function M.display_crate_info(buf, infos)
if not state.visible then
return
end

local buf_state = M.get_or_init(buf)
for _, d in ipairs(diagnostics) do
local vim_diagnostic = to_vim_diagnostic(d)
table.insert(buf_state.custom_diagnostics, vim_diagnostic)
end
for _, info in ipairs(infos) do
local virt_text = {}
if info.vers_match then
table.insert(virt_text, {
string.format(state.cfg.text[info.match_kind], info.vers_match.num),
state.cfg.highlight[info.match_kind],
})
elseif info.match_kind == MatchKind.NOMATCH then
table.insert(virt_text, {
state.cfg.text.nomatch,
state.cfg.highlight.nomatch,
})
end
if info.vers_upgrade then
table.insert(virt_text, {
string.format(state.cfg.text.upgrade, info.vers_upgrade.num),
state.cfg.highlight.upgrade,
})
end

local virt_text = {}
if info.vers_match then
table.insert(virt_text, {
string.format(state.cfg.text[info.match_kind], info.vers_match.num),
state.cfg.highlight[info.match_kind],
})
elseif info.match_kind == MatchKind.NOMATCH then
table.insert(virt_text, {
state.cfg.text.nomatch,
state.cfg.highlight.nomatch,
})
end
if info.vers_upgrade then
table.insert(virt_text, {
string.format(state.cfg.text.upgrade, info.vers_upgrade.num),
state.cfg.highlight.upgrade,
})
end
if not (info.vers_match or info.vers_upgrade) then
table.insert(virt_text, {
state.cfg.text.error,
state.cfg.highlight.error,
})
end

if not (info.vers_match or info.vers_upgrade) then
table.insert(virt_text, {
state.cfg.text.error,
state.cfg.highlight.error,
vim.api.nvim_buf_clear_namespace(buf, CUSTOM_NS, info.lines.s, info.lines.e)
vim.api.nvim_buf_set_extmark(buf, CUSTOM_NS, info.vers_line, -1, {
virt_text = virt_text,
virt_text_pos = "eol",
hl_mode = "combine",
})
end

vim.diagnostic.set(CUSTOM_NS, buf, buf_state.custom_diagnostics, { virtual_text = false })
vim.api.nvim_buf_clear_namespace(buf, CUSTOM_NS, info.lines.s, info.lines.e)
vim.api.nvim_buf_set_extmark(buf, CUSTOM_NS, info.vers_line, -1, {
virt_text = virt_text,
virt_text_pos = "eol",
hl_mode = "combine",
})
end

---@param buf integer
---@param crate TomlCrate
function M.display_loading(buf, crate)
---@param crates TomlCrate[]
function M.display_loading(buf, crates)
if not state.visible then
return
end

local buf_state = M.get_or_init(buf)
local vers_line = crate.vers and crate.vers.line or crate.lines.s
buf_state.line_state[vers_line] = LineState.LOADING

local virt_text = { { state.cfg.text.loading, state.cfg.highlight.loading } }
vim.api.nvim_buf_clear_namespace(buf, CUSTOM_NS, vers_line, vers_line + 1)
vim.api.nvim_buf_set_extmark(buf, CUSTOM_NS, vers_line, -1, {
virt_text = virt_text,
virt_text_pos = "eol",
hl_mode = "combine",
})
for _, crate in ipairs(crates) do
local vers_line = crate.vers and crate.vers.line or crate.lines.s
buf_state.line_state[vers_line] = LineState.LOADING

local virt_text = { { state.cfg.text.loading, state.cfg.highlight.loading } }
vim.api.nvim_buf_set_extmark(buf, CUSTOM_NS, vers_line, -1, {
virt_text = virt_text,
virt_text_pos = "eol",
hl_mode = "combine",
})
end
end

---@param buf integer
Expand Down

0 comments on commit b3b9ac6

Please sign in to comment.