diff options
-rw-r--r-- | runtime/doc/lua.txt | 2 | ||||
-rw-r--r-- | runtime/doc/news.txt | 1 | ||||
-rw-r--r-- | runtime/lua/vim/hl.lua | 43 | ||||
-rw-r--r-- | test/functional/lua/hl_spec.lua | 24 |
4 files changed, 53 insertions, 17 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 6e5a77ff7a..0eca3286d0 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -685,6 +685,8 @@ vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) whether the range is end-inclusive • {priority}? (`integer`, default: `vim.hl.priorities.user`) Highlight priority + • {timeout}? (`integer`, default: -1 no timeout) Time in ms + before highlight is cleared ============================================================================== diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 0d5fa3ca18..0f1ec01d19 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -194,6 +194,7 @@ API highlight group IDs. • |nvim_open_win()| `relative` field can be set to "laststatus" and "tabline". • |nvim_buf_set_extmark()| `hl_group` field can be an array of layered groups +• |vim.hl.range()| now has a optional `timeout` field which allows for a timed highlight DEFAULTS diff --git a/runtime/lua/vim/hl.lua b/runtime/lua/vim/hl.lua index f5ace7fdc5..070748d31e 100644 --- a/runtime/lua/vim/hl.lua +++ b/runtime/lua/vim/hl.lua @@ -17,6 +17,9 @@ M.priorities = { user = 200, } +local range_timer --- @type uv.uv_timer_t? +local range_hl_clear --- @type fun()? + --- @class vim.hl.range.Opts --- @inlinedoc --- @@ -31,6 +34,10 @@ M.priorities = { --- Highlight priority --- (default: `vim.hl.priorities.user`) --- @field priority? integer +--- +--- Time in ms before highlight is cleared +--- (default: -1 no timeout) +--- @field timeout? integer --- Apply highlight group to range of text. --- @@ -45,6 +52,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts) local regtype = opts.regtype or 'v' local inclusive = opts.inclusive or false local priority = opts.priority or M.priorities.user + local timeout = opts.timeout or -1 local v_maxcol = vim.v.maxcol @@ -100,6 +108,19 @@ function M.range(bufnr, ns, higroup, start, finish, opts) end end + if range_timer and not range_timer:is_closing() then + range_timer:close() + assert(range_hl_clear) + range_hl_clear() + end + + range_hl_clear = function() + range_timer = nil + range_hl_clear = nil + pcall(vim.api.nvim_buf_clear_namespace, bufnr, ns, 0, -1) + pcall(vim.api.nvim__ns_set, { wins = {} }) + end + for _, res in ipairs(region) do local start_row = res[1][2] - 1 local start_col = res[1][3] - 1 @@ -113,11 +134,13 @@ function M.range(bufnr, ns, higroup, start, finish, opts) strict = false, }) end + + if timeout ~= -1 then + range_timer = vim.defer_fn(range_hl_clear, timeout) + end end local yank_ns = api.nvim_create_namespace('nvim.hlyank') -local yank_timer --- @type uv.uv_timer_t? -local yank_cancel --- @type fun()? --- Highlight the yanked text during a |TextYankPost| event. --- @@ -152,31 +175,17 @@ function M.on_yank(opts) end local higroup = opts.higroup or 'IncSearch' - local timeout = opts.timeout or 150 local bufnr = vim.api.nvim_get_current_buf() local winid = vim.api.nvim_get_current_win() - if yank_timer then - yank_timer:close() - assert(yank_cancel) - yank_cancel() - end vim.api.nvim__ns_set(yank_ns, { wins = { winid } }) M.range(bufnr, yank_ns, higroup, "'[", "']", { regtype = event.regtype, inclusive = event.inclusive, priority = opts.priority or M.priorities.user, + timeout = opts.timeout or 150, }) - - yank_cancel = function() - yank_timer = nil - yank_cancel = nil - pcall(vim.api.nvim_buf_clear_namespace, bufnr, yank_ns, 0, -1) - pcall(vim.api.nvim__ns_set, { wins = {} }) - end - - yank_timer = vim.defer_fn(yank_cancel, timeout) end return M diff --git a/test/functional/lua/hl_spec.lua b/test/functional/lua/hl_spec.lua index 3f903d43a9..aed37cc294 100644 --- a/test/functional/lua/hl_spec.lua +++ b/test/functional/lua/hl_spec.lua @@ -104,6 +104,30 @@ describe('vim.hl.range', function() | ]]) end) + + it('removes highlight after given `timeout`', function() + local timeout = 50 + exec_lua(function() + local ns = vim.api.nvim_create_namespace('') + vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { timeout = timeout }) + end) + screen:expect([[ + {10:^asdfghjkl}{100:$} | + {10:«口=口»}{100:$} | + {10:qwertyuiop}{100:$} | + {10:口口=口口}{1:$} | + zxcvbnm{1:$} | + | + ]]) + screen:expect([[ + ^asdfghjkl{1:$} | + «口=口»{1:$} | + qwertyuiop{1:$} | + 口口=口口{1:$} | + zxcvbnm{1:$} | + | + ]]) + end) end) describe('vim.hl.on_yank', function() |