From 98eaab239d5e5bfcf7449086f8d840a0a5f320e3 Mon Sep 17 00:00:00 2001 From: wongxy Date: Fri, 15 Apr 2022 12:09:19 +0800 Subject: [PATCH] improve: remove unnecessary caches, use timer for TextChanged --- plugin/virt-column.lua | 80 ++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/plugin/virt-column.lua b/plugin/virt-column.lua index f478495..1b4d539 100644 --- a/plugin/virt-column.lua +++ b/plugin/virt-column.lua @@ -1,7 +1,6 @@ --- vim.g.virtcolumn_char: ▕ by default local api = vim.api -local fn = vim.fn local ffi = require "ffi" 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 function _refresh() - local bufnr = api.nvim_get_current_buf() - if not api.nvim_buf_is_loaded(bufnr) then - return - 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 - +---@param cc string +---@return number[] +local function parse_items(cc) + local textwidth = vim.o.textwidth ---@type number[] local items = {} - - local textwidth = vim.opt.textwidth:get() - for _, c in ipairs(vim.split(virtcolumn, ",")) do + for _, c in ipairs(vim.split(cc, ",")) do local item if c and c ~= "" then if vim.startswith(c, "+") then if textwidth ~= 0 then item = textwidth + tonumber(c:sub(2)) end - elseif vim.startswith(virtcolumn, "-") then + elseif vim.startswith(cc, "-") then if textwidth ~= 0 then item = textwidth - tonumber(c:sub(2)) end @@ -53,21 +37,38 @@ local function _refresh() table.sort(items, function(a, b) return a > b 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 return 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" -- 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 - -- ↓↓↓↓↓↓↓↓↓↓↓ - local lines = api.nvim_buf_get_lines(bufnr, offset - 1, vim.fn.line "w$" + win_lines, false) + -- Avoid flickering caused by winscrolled_timer + -- ↓↓↓↓↓↓↓↓↓↓↓ + 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 tabstop = vim.opt.tabstop:get() local char = vim.g.virtcolumn_char or "▕" @@ -76,7 +77,7 @@ local function _refresh() for _, item in ipairs(items) do local line = lines[i]:gsub("\t", string.rep(" ", tabstop)) 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_pos = "overlay", hl_mode = "combine", @@ -88,8 +89,9 @@ local function _refresh() end end --- Avoid unnecessary refreshing as much as possible +-- Avoid unnecessary refreshing as much as possible lcoallfdafffadf local winscrolled_timer +local textchanged_timer local function refresh(args) ---@type string local event = args.event or "" @@ -98,14 +100,13 @@ local function refresh(args) winscrolled_timer:stop() winscrolled_timer:close() end - winscrolled_timer = vim.defer_fn(_refresh, 100) + winscrolled_timer = vim.defer_fn(_refresh, 150) elseif event:match "TextChanged" then - local lines_count = fn.line "$" - local need_refresh = vim.b.virtcolumn_lines_count ~= lines_count - vim.b.virtcolumn_lines_count = lines_count - if need_refresh then - _refresh() + if textchanged_timer and textchanged_timer:is_active() then + textchanged_timer:stop() + textchanged_timer:close() end + textchanged_timer = vim.defer_fn(_refresh, 500) else _refresh() end @@ -119,7 +120,6 @@ local function set_hl() vim.cmd [[hi default link VirtColumn NonText]] end end -set_hl() local group = api.nvim_create_augroup("virtcolumn", {}) api.nvim_create_autocmd({ @@ -130,11 +130,9 @@ api.nvim_create_autocmd({ "InsertLeave", "InsertEnter", "FileChangedShellPost", -}, { - group = group, - callback = refresh, -}) +}, { group = group, callback = refresh }) api.nvim_create_autocmd("OptionSet", { group = group, callback = refresh, pattern = "colorcolumn" }) api.nvim_create_autocmd("ColorScheme", { group = group, callback = set_hl }) +pcall(set_hl) pcall(_refresh)