refactor: introduce nvim_on internally #39883

Problem:
`nvim_create_autocmd` is too verbose and its `callback` requires extra
"nesting".

Solution:
Introduce `nvim_on`. Start using it internally. Then we can get a feel
for how it should look before making it public.
This commit is contained in:
Justin M. Keyes
2026-05-20 17:33:01 -04:00
committed by GitHub
parent 799cbfff85
commit 9aa4608401
32 changed files with 842 additions and 1040 deletions

View File

@@ -1,4 +1,5 @@
local api = vim.api
local nvim_on = require('vim._core.util').nvim_on
local Range = require('vim.treesitter._range')
@@ -469,107 +470,83 @@ function M.inspect_tree(opts)
local group = api.nvim_create_augroup('nvim.treesitter.dev', {})
api.nvim_create_autocmd('CursorMoved', {
group = group,
buf = b,
callback = function()
if not api.nvim_buf_is_loaded(buf) then
return true
end
w = api.nvim_get_current_win()
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
local row = api.nvim_win_get_cursor(w)[1]
local lnum, col, end_lnum, end_col = treeview:get(row).node:range()
api.nvim_buf_set_extmark(buf, treeview.ns, lnum, col, {
end_row = end_lnum,
end_col = math.max(0, end_col),
hl_group = 'Visual',
})
-- update source window if original was closed
if not api.nvim_win_is_valid(win) then
win = assert(vim.fn.win_findbuf(buf)[1])
end
local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win)
-- Move the cursor if highlighted range is completely out of view
if lnum < topline and end_lnum < topline then
api.nvim_win_set_cursor(win, { end_lnum + 1, 0 })
elseif lnum > botline and end_lnum > botline then
api.nvim_win_set_cursor(win, { lnum + 1, 0 })
end
end,
})
api.nvim_create_autocmd('CursorMoved', {
group = group,
buf = buf,
callback = function()
if not api.nvim_buf_is_loaded(b) then
return true
end
set_inspector_cursor(treeview, opts.lang, buf, b, w)
end,
})
api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave' }, {
group = group,
buf = buf,
callback = function()
if not api.nvim_buf_is_loaded(b) then
return true
end
local treeview_opts = treeview.opts
treeview = assert(TSTreeView:new(buf, opts.lang))
treeview.opts = treeview_opts
treeview:draw(b)
end,
})
api.nvim_create_autocmd('BufLeave', {
group = group,
buf = b,
callback = function()
if not api.nvim_buf_is_loaded(buf) then
return true
end
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
end,
})
api.nvim_create_autocmd('BufLeave', {
group = group,
buf = buf,
callback = function()
if not api.nvim_buf_is_loaded(b) then
return true
end
api.nvim_buf_clear_namespace(b, treeview.ns, 0, -1)
end,
})
api.nvim_create_autocmd({ 'BufHidden', 'BufUnload', 'QuitPre' }, {
group = group,
buf = buf,
callback = function()
-- don't close inpector window if source buffer
-- has more than one open window
if #vim.fn.win_findbuf(buf) > 1 then
return
end
-- close all tree windows
for _, window in pairs(vim.fn.win_findbuf(b)) do
close_win(window)
end
nvim_on('CursorMoved', group, { buf = b }, function()
if not api.nvim_buf_is_loaded(buf) then
return true
end,
})
end
w = api.nvim_get_current_win()
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
local row = api.nvim_win_get_cursor(w)[1]
local lnum, col, end_lnum, end_col = treeview:get(row).node:range()
api.nvim_buf_set_extmark(buf, treeview.ns, lnum, col, {
end_row = end_lnum,
end_col = math.max(0, end_col),
hl_group = 'Visual',
})
-- update source window if original was closed
if not api.nvim_win_is_valid(win) then
win = assert(vim.fn.win_findbuf(buf)[1])
end
local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win)
-- Move the cursor if highlighted range is completely out of view
if lnum < topline and end_lnum < topline then
api.nvim_win_set_cursor(win, { end_lnum + 1, 0 })
elseif lnum > botline and end_lnum > botline then
api.nvim_win_set_cursor(win, { lnum + 1, 0 })
end
end)
nvim_on('CursorMoved', group, { buf = buf }, function()
if not api.nvim_buf_is_loaded(b) then
return true
end
set_inspector_cursor(treeview, opts.lang, buf, b, w)
end)
nvim_on({ 'TextChanged', 'InsertLeave' }, group, { buf = buf }, function()
if not api.nvim_buf_is_loaded(b) then
return true
end
local treeview_opts = treeview.opts
treeview = assert(TSTreeView:new(buf, opts.lang))
treeview.opts = treeview_opts
treeview:draw(b)
end)
nvim_on('BufLeave', group, { buf = b }, function()
if not api.nvim_buf_is_loaded(buf) then
return true
end
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
end)
nvim_on('BufLeave', group, { buf = buf }, function()
if not api.nvim_buf_is_loaded(b) then
return true
end
api.nvim_buf_clear_namespace(b, treeview.ns, 0, -1)
end)
nvim_on({ 'BufHidden', 'BufUnload', 'QuitPre' }, group, { buf = buf }, function()
-- don't close inpector window if source buffer
-- has more than one open window
if #vim.fn.win_findbuf(buf) > 1 then
return
end
-- close all tree windows
for _, window in pairs(vim.fn.win_findbuf(b)) do
close_win(window)
end
return true
end)
end
local edit_ns = api.nvim_create_namespace('nvim.treesitter.dev_edit')
@@ -671,53 +648,43 @@ function M.edit_query(lang)
api.nvim_buf_set_name(query_buf, string.format('%s/query_editor.scm', lang))
local group = api.nvim_create_augroup('nvim.treesitter.dev_edit', {})
api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave' }, {
group = group,
nvim_on({ 'TextChanged', 'InsertLeave' }, group, {
buf = query_buf,
desc = 'Update query editor diagnostics when the query changes',
callback = function()
vim.treesitter.query.lint(query_buf, { langs = lang, clear = false })
end,
})
api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave', 'CursorMoved', 'BufEnter' }, {
group = group,
}, function()
vim.treesitter.query.lint(query_buf, { langs = lang, clear = false })
end)
nvim_on({ 'TextChanged', 'InsertLeave', 'CursorMoved', 'BufEnter' }, group, {
buf = query_buf,
desc = 'Update query editor highlights when the cursor moves',
callback = function()
if api.nvim_win_is_valid(win) then
update_editor_highlights(query_win, win, lang)
end
end,
})
api.nvim_create_autocmd('BufLeave', {
group = group,
}, function()
if api.nvim_win_is_valid(win) then
update_editor_highlights(query_win, win, lang)
end
end)
nvim_on('BufLeave', group, {
buf = query_buf,
desc = 'Clear highlights when leaving the query editor',
callback = function()
api.nvim_buf_clear_namespace(buf, edit_ns, 0, -1)
end,
})
api.nvim_create_autocmd('BufLeave', {
group = group,
}, function()
api.nvim_buf_clear_namespace(buf, edit_ns, 0, -1)
end)
nvim_on('BufLeave', group, {
buf = buf,
desc = 'Clear the query editor highlights when leaving the source buffer',
callback = function()
if not api.nvim_buf_is_loaded(query_buf) then
return true
end
}, function()
if not api.nvim_buf_is_loaded(query_buf) then
return true
end
api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1)
end,
})
api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, {
group = group,
api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1)
end)
nvim_on({ 'BufHidden', 'BufUnload' }, group, {
buf = buf,
desc = 'Close the editor window when the source buffer is hidden or unloaded',
once = true,
callback = function()
close_win(query_win)
end,
})
}, function()
close_win(query_win)
end)
api.nvim_buf_set_lines(query_buf, 0, -1, false, {
';; Write queries here (see $VIMRUNTIME/queries/ for examples).',