improve: remove unnecessary caches, use timer for TextChanged

This commit is contained in:
wongxy
2022-04-15 12:09:19 +08:00
parent aaf3163199
commit 98eaab239d
+39 -41
View File
@@ -1,7 +1,6 @@
--- vim.g.virtcolumn_char: ▕ by default --- vim.g.virtcolumn_char: ▕ by default
local api = vim.api local api = vim.api
local fn = vim.fn
local ffi = require "ffi" local ffi = require "ffi"
ffi.cdef "int curwin_col_off(void);" ffi.cdef "int curwin_col_off(void);"
@@ -10,35 +9,20 @@ local curwin_col_off = ffi.C.curwin_col_off
local NS = api.nvim_create_namespace "virt-column" local NS = api.nvim_create_namespace "virt-column"
local function _refresh() ---@param cc string
local bufnr = api.nvim_get_current_buf() ---@return number[]
if not api.nvim_buf_is_loaded(bufnr) then local function parse_items(cc)
return local textwidth = vim.o.textwidth
end
local virtcolumn = vim.b.virtcolumn or vim.w.virtcolumn
local local_cc = vim.wo.cc
if not virtcolumn or local_cc ~= "" then
virtcolumn = local_cc
vim.wo.cc = ""
end
vim.b.virtcolumn = virtcolumn
vim.w.virtcolumn = virtcolumn
---@type number[] ---@type number[]
local items = {} local items = {}
for _, c in ipairs(vim.split(cc, ",")) do
local textwidth = vim.opt.textwidth:get()
for _, c in ipairs(vim.split(virtcolumn, ",")) do
local item local item
if c and c ~= "" then if c and c ~= "" then
if vim.startswith(c, "+") then if vim.startswith(c, "+") then
if textwidth ~= 0 then if textwidth ~= 0 then
item = textwidth + tonumber(c:sub(2)) item = textwidth + tonumber(c:sub(2))
end end
elseif vim.startswith(virtcolumn, "-") then elseif vim.startswith(cc, "-") then
if textwidth ~= 0 then if textwidth ~= 0 then
item = textwidth - tonumber(c:sub(2)) item = textwidth - tonumber(c:sub(2))
end end
@@ -53,21 +37,38 @@ local function _refresh()
table.sort(items, function(a, b) table.sort(items, function(a, b)
return a > b return a > b
end) end)
return items
end
api.nvim_buf_clear_namespace(bufnr, NS, 0, -1) local function _refresh()
local curbuf = api.nvim_get_current_buf()
if not api.nvim_buf_is_loaded(curbuf) then
return
end
local items = vim.b.virtcolumn_items or vim.w.virtcolumn_items
local local_cc = vim.wo.cc
if not items or local_cc ~= "" then
items = parse_items(local_cc)
vim.wo.cc = ""
end
vim.b.virtcolumn_items = items
vim.w.virtcolumn_items = items
api.nvim_buf_clear_namespace(curbuf, NS, 0, -1)
if #items == 0 then if #items == 0 then
return return
end end
local win_lines = vim.o.lines local debounce = math.floor(api.nvim_win_get_height(0) * 0.6)
local offset = vim.fn.line "w0" local offset = vim.fn.line "w0"
-- Avoid flickering caused by winscrolled_timer -- Avoid flickering caused by winscrolled_timer
offset = offset <= win_lines and 1 or offset - win_lines offset = (offset <= debounce and 1 or offset - debounce) - 1 -- convert to 0-based
-- Avoid flickering caused by winscrolled_timer -- Avoid flickering caused by winscrolled_timer
-- ↓↓↓↓↓↓↓↓↓↓↓ -- ↓↓↓↓↓↓↓↓↓↓↓
local lines = api.nvim_buf_get_lines(bufnr, offset - 1, vim.fn.line "w$" + win_lines, false) local lines = api.nvim_buf_get_lines(curbuf, offset, vim.fn.line "w$" + debounce, false)
local width = api.nvim_win_get_width(0) - curwin_col_off() local width = api.nvim_win_get_width(0) - curwin_col_off()
local tabstop = vim.opt.tabstop:get() local tabstop = vim.opt.tabstop:get()
local char = vim.g.virtcolumn_char or "▕" local char = vim.g.virtcolumn_char or "▕"
@@ -76,7 +77,7 @@ local function _refresh()
for _, item in ipairs(items) do for _, item in ipairs(items) do
local line = lines[i]:gsub("\t", string.rep(" ", tabstop)) local line = lines[i]:gsub("\t", string.rep(" ", tabstop))
if width > item and api.nvim_strwidth(line) < item then if width > item and api.nvim_strwidth(line) < item then
api.nvim_buf_set_extmark(bufnr, NS, i + offset - 2, 0, { api.nvim_buf_set_extmark(curbuf, NS, i + offset - 1, 0, {
virt_text = { { char, "VirtColumn" } }, virt_text = { { char, "VirtColumn" } },
virt_text_pos = "overlay", virt_text_pos = "overlay",
hl_mode = "combine", hl_mode = "combine",
@@ -88,8 +89,9 @@ local function _refresh()
end end
end end
-- Avoid unnecessary refreshing as much as possible -- Avoid unnecessary refreshing as much as possible lcoallfdafffadf
local winscrolled_timer local winscrolled_timer
local textchanged_timer
local function refresh(args) local function refresh(args)
---@type string ---@type string
local event = args.event or "" local event = args.event or ""
@@ -98,14 +100,13 @@ local function refresh(args)
winscrolled_timer:stop() winscrolled_timer:stop()
winscrolled_timer:close() winscrolled_timer:close()
end end
winscrolled_timer = vim.defer_fn(_refresh, 100) winscrolled_timer = vim.defer_fn(_refresh, 150)
elseif event:match "TextChanged" then elseif event:match "TextChanged" then
local lines_count = fn.line "$" if textchanged_timer and textchanged_timer:is_active() then
local need_refresh = vim.b.virtcolumn_lines_count ~= lines_count textchanged_timer:stop()
vim.b.virtcolumn_lines_count = lines_count textchanged_timer:close()
if need_refresh then
_refresh()
end end
textchanged_timer = vim.defer_fn(_refresh, 500)
else else
_refresh() _refresh()
end end
@@ -119,7 +120,6 @@ local function set_hl()
vim.cmd [[hi default link VirtColumn NonText]] vim.cmd [[hi default link VirtColumn NonText]]
end end
end end
set_hl()
local group = api.nvim_create_augroup("virtcolumn", {}) local group = api.nvim_create_augroup("virtcolumn", {})
api.nvim_create_autocmd({ api.nvim_create_autocmd({
@@ -130,11 +130,9 @@ api.nvim_create_autocmd({
"InsertLeave", "InsertLeave",
"InsertEnter", "InsertEnter",
"FileChangedShellPost", "FileChangedShellPost",
}, { }, { group = group, callback = refresh })
group = group,
callback = refresh,
})
api.nvim_create_autocmd("OptionSet", { group = group, callback = refresh, pattern = "colorcolumn" }) api.nvim_create_autocmd("OptionSet", { group = group, callback = refresh, pattern = "colorcolumn" })
api.nvim_create_autocmd("ColorScheme", { group = group, callback = set_hl }) api.nvim_create_autocmd("ColorScheme", { group = group, callback = set_hl })
pcall(set_hl)
pcall(_refresh) pcall(_refresh)