Skip to content

Commit af0ef2a

Browse files
authored
feat(lua): vim.hl.range() "timeout" neovim#32012
Problem: `vim.hl.on_yank()` has a "timeout" behavior but this is not available for `vim.hl.range()`. Solution: Add `timeout` arg to `vim.hl.range()`.
1 parent 34344b9 commit af0ef2a

File tree

4 files changed

+53
-17
lines changed

4 files changed

+53
-17
lines changed

runtime/doc/lua.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
685685
whether the range is end-inclusive
686686
{priority}? (`integer`, default:
687687
`vim.hl.priorities.user`) Highlight priority
688+
{timeout}? (`integer`, default: -1 no timeout) Time in ms
689+
before highlight is cleared
688690

689691

690692
==============================================================================

runtime/doc/news.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ API
194194
highlight group IDs.
195195
|nvim_open_win()| `relative` field can be set to "laststatus" and "tabline".
196196
|nvim_buf_set_extmark()| `hl_group` field can be an array of layered groups
197+
|vim.hl.range()| now has a optional `timeout` field which allows for a timed highlight
197198

198199
DEFAULTS
199200

runtime/lua/vim/hl.lua

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ M.priorities = {
1717
user = 200,
1818
}
1919

20+
local range_timer --- @type uv.uv_timer_t?
21+
local range_hl_clear --- @type fun()?
22+
2023
--- @class vim.hl.range.Opts
2124
--- @inlinedoc
2225
---
@@ -31,6 +34,10 @@ M.priorities = {
3134
--- Highlight priority
3235
--- (default: `vim.hl.priorities.user`)
3336
--- @field priority? integer
37+
---
38+
--- Time in ms before highlight is cleared
39+
--- (default: -1 no timeout)
40+
--- @field timeout? integer
3441

3542
--- Apply highlight group to range of text.
3643
---
@@ -45,6 +52,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
4552
local regtype = opts.regtype or 'v'
4653
local inclusive = opts.inclusive or false
4754
local priority = opts.priority or M.priorities.user
55+
local timeout = opts.timeout or -1
4856

4957
local v_maxcol = vim.v.maxcol
5058

@@ -100,6 +108,19 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
100108
end
101109
end
102110

111+
if range_timer and not range_timer:is_closing() then
112+
range_timer:close()
113+
assert(range_hl_clear)
114+
range_hl_clear()
115+
end
116+
117+
range_hl_clear = function()
118+
range_timer = nil
119+
range_hl_clear = nil
120+
pcall(vim.api.nvim_buf_clear_namespace, bufnr, ns, 0, -1)
121+
pcall(vim.api.nvim__ns_set, { wins = {} })
122+
end
123+
103124
for _, res in ipairs(region) do
104125
local start_row = res[1][2] - 1
105126
local start_col = res[1][3] - 1
@@ -113,11 +134,13 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
113134
strict = false,
114135
})
115136
end
137+
138+
if timeout ~= -1 then
139+
range_timer = vim.defer_fn(range_hl_clear, timeout)
140+
end
116141
end
117142

118143
local yank_ns = api.nvim_create_namespace('nvim.hlyank')
119-
local yank_timer --- @type uv.uv_timer_t?
120-
local yank_cancel --- @type fun()?
121144

122145
--- Highlight the yanked text during a |TextYankPost| event.
123146
---
@@ -152,31 +175,17 @@ function M.on_yank(opts)
152175
end
153176

154177
local higroup = opts.higroup or 'IncSearch'
155-
local timeout = opts.timeout or 150
156178

157179
local bufnr = vim.api.nvim_get_current_buf()
158180
local winid = vim.api.nvim_get_current_win()
159-
if yank_timer then
160-
yank_timer:close()
161-
assert(yank_cancel)
162-
yank_cancel()
163-
end
164181

165182
vim.api.nvim__ns_set(yank_ns, { wins = { winid } })
166183
M.range(bufnr, yank_ns, higroup, "'[", "']", {
167184
regtype = event.regtype,
168185
inclusive = event.inclusive,
169186
priority = opts.priority or M.priorities.user,
187+
timeout = opts.timeout or 150,
170188
})
171-
172-
yank_cancel = function()
173-
yank_timer = nil
174-
yank_cancel = nil
175-
pcall(vim.api.nvim_buf_clear_namespace, bufnr, yank_ns, 0, -1)
176-
pcall(vim.api.nvim__ns_set, { wins = {} })
177-
end
178-
179-
yank_timer = vim.defer_fn(yank_cancel, timeout)
180189
end
181190

182191
return M

test/functional/lua/hl_spec.lua

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,30 @@ describe('vim.hl.range', function()
104104
|
105105
]])
106106
end)
107+
108+
it('removes highlight after given `timeout`', function()
109+
local timeout = 50
110+
exec_lua(function()
111+
local ns = vim.api.nvim_create_namespace('')
112+
vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { timeout = timeout })
113+
end)
114+
screen:expect([[
115+
{10:^asdfghjkl}{100:$} |
116+
{10:«口=口»}{100:$} |
117+
{10:qwertyuiop}{100:$} |
118+
{10:口口=口口}{1:$} |
119+
zxcvbnm{1:$} |
120+
|
121+
]])
122+
screen:expect([[
123+
^asdfghjkl{1:$} |
124+
«口=口»{1:$} |
125+
qwertyuiop{1:$} |
126+
口口=口口{1:$} |
127+
zxcvbnm{1:$} |
128+
|
129+
]])
130+
end)
107131
end)
108132

109133
describe('vim.hl.on_yank', function()

0 commit comments

Comments
 (0)