Skip to content

Commit 98b4a84

Browse files
committed
(mini.deps) Update add() to source 'after/plugin' when needed.
Details: - As `:packadd` only puts '/after' directory to 'runtimepath' but not executes scripts from there, make sure that they are sourced. This makes difference when `add()` is called not during startup (for example, lazy loaded with `later()`). Looks like plugins should not be using 'after/plugin' directory, though, in favor of just 'plugin' (but they might).
1 parent 78a4d45 commit 98b4a84

File tree

12 files changed

+91
-4
lines changed

12 files changed

+91
-4
lines changed

doc/mini-deps.txt

+1
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ Add plugin to current session
424424
- Execute `opts.hooks.post_install`.
425425
- Register spec(s) in current session.
426426
- Make sure plugin(s) can be used in current session (see |:packadd|).
427+
- If not during startup and is needed, source all "after/plugin/" scripts.
427428

428429
Notes:
429430
- Presence of plugin is checked by its name which is the same as the name

lua/mini/deps.lua

+18
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ MiniDeps.config = {
440440
--- - Execute `opts.hooks.post_install`.
441441
--- - Register spec(s) in current session.
442442
--- - Make sure plugin(s) can be used in current session (see |:packadd|).
443+
--- - If not during startup and is needed, source all "after/plugin/" scripts.
443444
---
444445
--- Notes:
445446
--- - Presence of plugin is checked by its name which is the same as the name
@@ -490,6 +491,19 @@ MiniDeps.add = function(spec, opts)
490491
-- Add to 'runtimepath'
491492
vim.cmd(cmd .. p.name)
492493
end
494+
495+
-- Execute 'after/' scripts if not during startup (when they will be sourced
496+
-- automatically), as `:packadd` only sources plain 'plugin/' files.
497+
-- See https://github.com/vim/vim/issues/1994.
498+
-- Deliberately do so after executing all currently known 'plugin/' files.
499+
local should_load_after_dir = vim.v.vim_did_enter == 1 and not opts.bang and vim.o.loadplugins
500+
if not should_load_after_dir then return end
501+
for _, p in ipairs(plugs) do
502+
-- NOTE: This sources first lua and then vim, not how it is done during
503+
-- startup (`:h loadplugins`) for speed (one `glob()` instead of two).
504+
local after_paths = vim.fn.glob(p.path .. '/after/plugin/**/*.{vim,lua}', false, true)
505+
vim.tbl_map(H.source, after_paths)
506+
end
493507
end
494508

495509
--- Update plugins
@@ -1512,6 +1526,10 @@ H.readdir = function(path)
15121526
return vim.tbl_map(function(x) return path .. '/' .. x end, vim.fn.readdir(path))
15131527
end
15141528

1529+
H.source = function(path)
1530+
pcall(function() vim.cmd('source ' .. vim.fn.fnameescape(path)) end)
1531+
end
1532+
15151533
H.buf_set_name = function(buf_id, name)
15161534
local n = (H.buf_name_counts[name] or 0) + 1
15171535
H.buf_name_counts[name] = n
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_G.plugin_log = _G.plugin_log or {}
2+
table.insert(_G.plugin_log, 'after/plugin/plug_1.lua')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
error()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
lua <<EOF
2+
_G.plugin_log = _G.plugin_log or {}
3+
table.insert(_G.plugin_log, 'after/plugin/plug_1.vim')
4+
EOF
5+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_G.plugin_log = _G.plugin_log or {}
2+
table.insert(_G.plugin_log, 'after/plugin/subdir/plug_1_sub.lua')
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
_G.plugin_1_plugin_dir_was_sourced = true
1+
_G.plugin_log = _G.plugin_log or {}
2+
table.insert(_G.plugin_log, 'plugin/plug_1.lua')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
lua <<EOF
2+
_G.plugin_log = _G.plugin_log or {}
3+
table.insert(_G.plugin_log, 'plugin/plug_1.vim')
4+
EOF
5+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_G.plugin_log = _G.plugin_log or {}
2+
table.insert(_G.plugin_log, 'plugin/subdir/plug_1_sub.lua')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_G.plugin_log = _G.plugin_log or {}
2+
table.insert(_G.plugin_log, 'after/plugin/plug_2.lua')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_G.plugin_log = _G.plugin_log or {}
2+
table.insert(_G.plugin_log, 'plugin/plug_2.lua')

tests/test_deps.lua

+49-3
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,13 @@ T['add()']['works for present plugins'] = new_set({ parametrize = { { 'plugin_1'
289289
-- No CLI process should be run as plugin is already present
290290
eq(get_spawn_log(), {})
291291

292-
-- Should use `:packadd`, i.e. load 'plugin/', 'ftdetect/', etc.
293-
eq(child.lua_get('_G.plugin_1_plugin_dir_was_sourced'), true)
292+
-- Should add plugin to 'runtimepath'
293+
local rtp = vim.split(child.o.runtimepath, ',')
294+
eq(vim.tbl_contains(rtp, ref_path), true)
295+
eq(vim.tbl_contains(rtp, ref_path .. '/after'), true)
296+
297+
-- Should load 'plugin/', 'after/plugin/', etc.
298+
eq(child.lua_get('type(_G.plugin_log)'), 'table')
294299
end,
295300
})
296301

@@ -313,6 +318,47 @@ T['add()']['infers name from source'] = new_set({
313318
end,
314319
})
315320

321+
T['add()']["properly sources 'plugin/' and 'after/plugin/'"] = function()
322+
add({ name = 'plugin_1', depends = { 'plugin_2' } })
323+
local after_paths = { 'after/plugin/plug_1.lua', 'after/plugin/plug_1.vim', 'after/plugin/subdir/plug_1_sub.lua' }
324+
if child.fn.has('nvim-0.9') == 0 then
325+
after_paths = { 'after/plugin/plug_1.vim', 'after/plugin/plug_1.lua', 'after/plugin/subdir/plug_1_sub.lua' }
326+
end
327+
--stylua: ignore
328+
local ref_plugin_log = {
329+
'plugin/plug_2.lua',
330+
'plugin/plug_1.vim', 'plugin/plug_1.lua', 'plugin/subdir/plug_1_sub.lua',
331+
'after/plugin/plug_2.lua',
332+
unpack(after_paths)
333+
}
334+
eq(child.lua_get('_G.plugin_log'), ref_plugin_log)
335+
end
336+
337+
T['add()']["does not source 'after/plugin/' when not needed"] = function()
338+
-- During startup
339+
local setup_cmd =
340+
string.format("lua require('mini.deps').setup({ path = { package = %s } })", vim.inspect(test_dir_absolute))
341+
child.restart({ '-u', 'NONE', '--cmd', 'set rtp+=.', '--cmd', setup_cmd, '--cmd', "lua MiniDeps.add('plugin_1')" })
342+
343+
--stylua: ignore
344+
eq(child.lua_get('_G.plugin_log'), {
345+
-- 'plugin/' directory gets sourced both as part of startup and `:packadd`
346+
'plugin/plug_1.vim', 'plugin/plug_1.lua', 'plugin/subdir/plug_1_sub.lua',
347+
'plugin/plug_1.vim', 'plugin/plug_1.lua', 'plugin/subdir/plug_1_sub.lua',
348+
-- But sourcing 'after/plugin/' in 'mini.deps' should not duplicate startup
349+
'after/plugin/plug_1.vim', 'after/plugin/plug_1.lua', 'after/plugin/subdir/plug_1_sub.lua',
350+
})
351+
352+
-- When 'loadplugins = false'
353+
child.restart({ '-u', 'NONE', '--cmd', 'set rtp+=.', '--cmd', setup_cmd })
354+
child.o.loadplugins = false
355+
add('plugin_1')
356+
357+
-- - `:packadd` does not recognize 'loadplugins' and thus sources them
358+
-- But 'after/plugin/' should not be sourced
359+
eq(child.lua_get('_G.plugin_log'), { 'plugin/plug_1.vim', 'plugin/plug_1.lua', 'plugin/subdir/plug_1_sub.lua' })
360+
end
361+
316362
T['add()']['can update session data'] = function()
317363
add('plugin_1')
318364
add('plugin_2')
@@ -440,7 +486,7 @@ end
440486

441487
T['add()']['respects `opts.bang`'] = function()
442488
add('plugin_1', { bang = true })
443-
eq(child.lua_get('_G.plugin_1_plugin_dir_was_sourced'), vim.NIL)
489+
eq(child.lua_get('_G.plugin_log'), vim.NIL)
444490
end
445491

446492
T['add()']['does not modify input'] = function()

0 commit comments

Comments
 (0)