From a9db6ec6fa127b57912bc59e5d03f7e99d22607f Mon Sep 17 00:00:00 2001 From: Evgeni Chasnovski Date: Thu, 23 Oct 2025 17:50:03 +0300 Subject: [PATCH] feat(pack): add `active` field to `PackChanged` event data Problem: Inside `PackChanged[Pre]` callbacks it might be useful to tell if the affected plugin is active or not. It is already possible via extra `vim.pack.get({ 'plug-name' })[1].active`, but it is not quite user-friendly for something that might be needed frequently in real world use cases. Solution: Supply extra `active` event data field. --- runtime/doc/pack.txt | 1 + runtime/lua/vim/pack.lua | 16 ++++++++------ test/functional/plugin/pack_spec.lua | 32 ++++++++++++++-------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/runtime/doc/pack.txt b/runtime/doc/pack.txt index eaf4b0b4f9..4386770123 100644 --- a/runtime/doc/pack.txt +++ b/runtime/doc/pack.txt @@ -300,6 +300,7 @@ Available events to hook into ~ • *PackChanged* - after plugin's state has changed. Each event populates the following |event-data| fields: +• `active` - whether plugin was added via |vim.pack.add()| to current session. • `kind` - one of "install" (install on disk), "update" (update existing plugin), "delete" (delete from disk). • `spec` - plugin's specification with defaults made explicit. diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua index 1a0a3c4540..f17fce56a9 100644 --- a/runtime/lua/vim/pack.lua +++ b/runtime/lua/vim/pack.lua @@ -97,6 +97,7 @@ --- - [PackChanged]() - after plugin's state has changed. --- --- Each event populates the following |event-data| fields: +--- - `active` - whether plugin was added via |vim.pack.add()| to current session. --- - `kind` - one of "install" (install on disk), "update" (update existing --- plugin), "delete" (delete from disk). --- - `spec` - plugin's specification with defaults made explicit. @@ -408,11 +409,18 @@ local function plug_list_from_names(names) return plugs end +--- Map from plugin path to its data. +--- Use map and not array to avoid linear lookup during startup. +--- @type table +local active_plugins = {} +local n_active_plugins = 0 + --- @param p vim.pack.Plug --- @param event_name 'PackChangedPre'|'PackChanged' --- @param kind 'install'|'update'|'delete' local function trigger_event(p, event_name, kind) - local data = { kind = kind, spec = vim.deepcopy(p.spec), path = p.path } + local active = active_plugins[p.path] ~= nil + local data = { active = active, kind = kind, spec = vim.deepcopy(p.spec), path = p.path } api.nvim_exec_autocmds(event_name, { pattern = p.path, data = data }) end @@ -686,12 +694,6 @@ local function infer_update_details(p) p.info.update_details = table.concat(newer_semver_tags, '\n') end ---- Map from plugin path to its data. ---- Use map and not array to avoid linear lookup during startup. ---- @type table -local active_plugins = {} -local n_active_plugins = 0 - --- @param plug vim.pack.Plug --- @param load boolean|fun(plug_data: {spec: vim.pack.Spec, path: string}) local function pack_add(plug, load) diff --git a/test/functional/plugin/pack_spec.lua b/test/functional/plugin/pack_spec.lua index 7b40addcce..eeb1fe7be6 100644 --- a/test/functional/plugin/pack_spec.lua +++ b/test/functional/plugin/pack_spec.lua @@ -233,10 +233,10 @@ end --- @param log table[] local function make_find_packchanged(log) --- @param suffix string - return function(suffix, kind, repo_name, version) + return function(suffix, kind, repo_name, version, active) local path = pack_get_plug_path(repo_name) local spec = { name = repo_name, src = repos_src[repo_name], version = version } - local data = { kind = kind, path = path, spec = spec } + local data = { active = active, kind = kind, path = path, spec = spec } local entry = { event = 'PackChanged' .. suffix, match = vim.fs.abspath(path), data = data } local res = 0 @@ -672,14 +672,14 @@ describe('vim.pack', function() local log = exec_lua('return _G.event_log') local find_event = make_find_packchanged(log) - local installpre_basic = find_event('Pre', 'install', 'basic', 'feat-branch') - local installpre_defbranch = find_event('Pre', 'install', 'defbranch', nil) - local updatepre_basic = find_event('Pre', 'update', 'basic', 'feat-branch') - local updatepre_defbranch = find_event('Pre', 'update', 'defbranch', nil) - local update_basic = find_event('', 'update', 'basic', 'feat-branch') - local update_defbranch = find_event('', 'update', 'defbranch', nil) - local install_basic = find_event('', 'install', 'basic', 'feat-branch') - local install_defbranch = find_event('', 'install', 'defbranch', nil) + local installpre_basic = find_event('Pre', 'install', 'basic', 'feat-branch', false) + local installpre_defbranch = find_event('Pre', 'install', 'defbranch', nil, false) + local updatepre_basic = find_event('Pre', 'update', 'basic', 'feat-branch', false) + local updatepre_defbranch = find_event('Pre', 'update', 'defbranch', nil, false) + local update_basic = find_event('', 'update', 'basic', 'feat-branch', false) + local update_defbranch = find_event('', 'update', 'defbranch', nil, false) + local install_basic = find_event('', 'install', 'basic', 'feat-branch', false) + local install_defbranch = find_event('', 'install', 'defbranch', nil, false) eq(8, #log) -- NOTE: There is no guaranteed installation order among separate plugins (as it is async) @@ -1541,8 +1541,8 @@ describe('vim.pack', function() n.exec('write') local log = exec_lua('return _G.event_log') local find_event = make_find_packchanged(log) - eq(1, find_event('Pre', 'update', 'fetch', nil)) - eq(2, find_event('', 'update', 'fetch', nil)) + eq(1, find_event('Pre', 'update', 'fetch', nil, true)) + eq(2, find_event('', 'update', 'fetch', nil, true)) eq(2, #log) end) @@ -1756,10 +1756,10 @@ describe('vim.pack', function() -- Should trigger relevant events in order as specified in `vim.pack.add()` local log = exec_lua('return _G.event_log') local find_event = make_find_packchanged(log) - eq(1, find_event('Pre', 'delete', 'basic', 'feat-branch')) - eq(2, find_event('', 'delete', 'basic', 'feat-branch')) - eq(3, find_event('Pre', 'delete', 'plugindirs', nil)) - eq(4, find_event('', 'delete', 'plugindirs', nil)) + eq(1, find_event('Pre', 'delete', 'basic', 'feat-branch', true)) + eq(2, find_event('', 'delete', 'basic', 'feat-branch', false)) + eq(3, find_event('Pre', 'delete', 'plugindirs', nil, true)) + eq(4, find_event('', 'delete', 'plugindirs', nil, false)) eq(4, #log) -- Should update lockfile