feat!: plugins are now autmatically loaded on require. `module=` no longer needed!

This commit is contained in:
Folke Lemaitre 2022-12-02 09:22:15 +01:00
parent 0b6dec46e0
commit 575421b3fb
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
4 changed files with 84 additions and 52 deletions

View File

@ -6,7 +6,6 @@ local Config = require("lazy.core.config")
---@field event? string|string[] ---@field event? string|string[]
---@field cmd? string|string[] ---@field cmd? string|string[]
---@field ft? string|string[] ---@field ft? string|string[]
---@field module? string|string[]
---@field keys? string|string[] ---@field keys? string|string[]
local M = {} local M = {}
@ -116,36 +115,4 @@ function M.handlers.cmd(grouped)
end end
end end
function M.handlers.module(grouped)
---@param modname string
table.insert(package.loaders, 2, function(modname)
local idx = modname:find(".", 1, true) or #modname + 1
while idx do
local name = modname:sub(1, idx - 1)
---@diagnostic disable-next-line: redefined-local
local plugins = grouped[name]
if plugins then
grouped[name] = nil
local reason = { require = modname }
-- almost never happens, so this does not decrease performance
if #Loader.loading == 0 then
local f = 3
while not reason.source do
local info = debug.getinfo(f, "S")
if not info then
break
end
if info.what ~= "C" then
reason.source = info.source:sub(2)
end
f = f + 1
end
end
Loader.load(plugins, reason)
end
idx = modname:find(".", idx + 1, true)
end
end)
end
return M return M

View File

@ -5,6 +5,7 @@ local M = {}
---@type LazyPlugin[] ---@type LazyPlugin[]
M.loading = {} M.loading = {}
M.init_done = false
function M.setup() function M.setup()
-- install missing plugins -- install missing plugins
@ -25,6 +26,9 @@ function M.setup()
local Handler = require("lazy.core.handler") local Handler = require("lazy.core.handler")
Handler.setup() Handler.setup()
Util.track() Util.track()
-- autoload opt plugins
table.insert(package.loaders, M.autoload)
end end
function M.init_plugins() function M.init_plugins()
@ -42,6 +46,7 @@ function M.init_plugins()
end end
Util.track() Util.track()
Util.track() Util.track()
M.init_done = true
end end
---@class Loader ---@class Loader
@ -49,7 +54,7 @@ end
---@param reason {[string]:string} ---@param reason {[string]:string}
function M.load(plugins, reason) function M.load(plugins, reason)
---@diagnostic disable-next-line: cast-local-type ---@diagnostic disable-next-line: cast-local-type
plugins = type(plugins) == "string" or plugins.name and { plugins } or plugins plugins = (type(plugins) == "string" or plugins.name) and { plugins } or plugins
---@cast plugins (string|LazyPlugin)[] ---@cast plugins (string|LazyPlugin)[]
for _, plugin in ipairs(plugins) do for _, plugin in ipairs(plugins) do
@ -64,17 +69,21 @@ function M.load(plugins, reason)
end end
if #M.loading > 0 then if #M.loading > 0 then
plugin._.loaded.plugin = M.loading[#M.loading].name plugin._.loaded.plugin = M.loading[#M.loading].name
elseif reason.require then
plugin._.loaded.source = Util.get_source()
end end
table.insert(M.loading, plugin) table.insert(M.loading, plugin)
Util.track({ plugin = plugin.name, start = reason.start }) Util.track({ plugin = plugin.name, start = reason.start })
M.packadd(plugin)
vim.opt.runtimepath:prepend(plugin.dir)
if plugin.dependencies then if plugin.dependencies then
M.load(plugin.dependencies, {}) M.load(plugin.dependencies, {})
end end
M.packadd(plugin)
if plugin.config then if plugin.config then
Util.try(plugin.config, "Failed to run `config` for " .. plugin.name) Util.try(plugin.config, "Failed to run `config` for " .. plugin.name)
end end
@ -90,9 +99,17 @@ end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
function M.packadd(plugin) function M.packadd(plugin)
vim.cmd.packadd(plugin.name) -- FIXME: investigate further what else is needed
-- vim.cmd.packadd(plugin.name)
-- M.source_runtime(plugin, "/after/plugin")
if M.init_done then
M.source_runtime(plugin, "/plugin")
if vim.g.did_load_filetypes == 1 then
M.source_runtime(plugin, "/ftdetect")
end
M.source_runtime(plugin, "/after/plugin") M.source_runtime(plugin, "/after/plugin")
end end
end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
---@param dir? string ---@param dir? string
@ -105,4 +122,36 @@ function M.source_runtime(plugin, dir)
end) end)
end end
-- This loader is added as the very last one.
-- This only hits when the modname is not cached and
-- even then only once per plugin. So pretty much never.
--
-- lazy.module will call this when loading a cached file with modpath set.
---@param modname string
---@param modpath string?
function M.autoload(modname, modpath)
-- fast return when we know the modpath
if modpath then
local plugin = require("lazy.core.plugin").find(modpath)
if plugin and not plugin._.loaded then
M.load(plugin, { require = modname })
end
return
end
-- check if a lazy plugin should be loaded
for _, plugin in pairs(Config.plugins) do
if not plugin._.loaded then
for _, pattern in ipairs({ ".lua", "/init.lua" }) do
local path = plugin.dir .. "/lua/" .. modname:gsub("%.", "/") .. pattern
if vim.loop.fs_stat(path) then
M.load(plugin, { require = modname })
local chunk, err = loadfile(path)
return chunk or error(err)
end
end
end
end
return modname .. " not found in unloaded opt plugins"
end
return M return M

View File

@ -1,6 +1,5 @@
local Config = require("lazy.core.config") local Config = require("lazy.core.config")
local Util = require("lazy.core.util") local Util = require("lazy.core.util")
local Module = require("lazy.core.module")
local Handler = require("lazy.core.handler") local Handler = require("lazy.core.handler")
local M = {} local M = {}
@ -38,7 +37,7 @@ local M = {}
---@field dependencies? string[] ---@field dependencies? string[]
---@field _ LazyPluginState ---@field _ LazyPluginState
---@alias LazySpec string|LazyPlugin|LazySpec[]|{dependencies:LazySpec} ---@alias LazySpec string|LazyPlugin|LazyPlugin[]|{dependencies:LazySpec}
---@class LazySpecLoader ---@class LazySpecLoader
---@field plugins table<string, LazyPlugin> ---@field plugins table<string, LazyPlugin>
@ -156,13 +155,7 @@ function M.update_state()
for _, plugin in pairs(Config.plugins) do for _, plugin in pairs(Config.plugins) do
plugin._ = plugin._ or {} plugin._ = plugin._ or {}
if plugin.lazy == nil then if plugin.lazy == nil then
local lazy = plugin.dep local lazy = plugin.dep or Config.options.defaults.lazy or plugin.event or plugin.keys or plugin.ft or plugin.cmd
or Config.options.defaults.lazy
or plugin.module
or plugin.event
or plugin.keys
or plugin.ft
or plugin.cmd
plugin.lazy = lazy and true or false plugin.lazy = lazy and true or false
end end
plugin.dir = Config.root .. "/" .. plugin.name plugin.dir = Config.root .. "/" .. plugin.name
@ -193,16 +186,15 @@ function M.spec()
if type(Config.spec) == "string" then if type(Config.spec) == "string" then
-- spec is a module -- spec is a module
local function _load(name, modpath) local function _load(name)
local modname = Config.spec .. (name and ("." .. name) or "") local modname = name and (Config.spec .. "." .. name) or Config.spec
Util.try(function() Util.try(function()
spec:normalize(Module.load(modname, modpath)) spec:normalize(require(modname))
end, "Failed to load **" .. modname .. "**") end, "Failed to load **" .. modname .. "**")
end end
local path_plugins = vim.fn.stdpath("config") .. "/lua/" .. Config.spec:gsub("%.", "/") local path_plugins = vim.fn.stdpath("config") .. "/lua/" .. Config.spec:gsub("%.", "/")
local path_main = path_plugins .. (vim.loop.fs_stat(path_plugins .. ".lua") and ".lua" or "/init.lua")
_load(nil, path_main) _load()
Util.lsmod(path_plugins, _load) Util.lsmod(path_plugins, _load)
else else
-- spec is a spec -- spec is a spec
@ -228,4 +220,14 @@ function M.load()
Util.track() Util.track()
end end
-- Finds the plugin that has this path
---@param path string
function M.find(path)
if path:find(Config.root, 1, true) == 1 then
local plugin = path:sub(#Config.root + 2)
local idx = plugin:find("/", 1, true)
return idx and Config.plugins[plugin:sub(1, idx - 1)] or nil
end
end
return M return M

View File

@ -38,7 +38,7 @@ function M.try(fn, msg)
if not info then if not info then
break break
end end
if info.what == "Lua" and not info.source:find("lazy.nvim") then if info.what ~= "C" and not info.source:find("lazy.nvim") then
local source = info.source:sub(2) local source = info.source:sub(2)
if source:find(Config.root, 1, true) == 1 then if source:find(Config.root, 1, true) == 1 then
source = source:sub(#Config.root + 1) source = source:sub(#Config.root + 1)
@ -67,6 +67,20 @@ function M.try(fn, msg)
return ok and result or nil return ok and result or nil
end end
function M.get_source()
local f = 2
while true do
local info = debug.getinfo(f, "S")
if not info then
break
end
if info.what ~= "C" and not info.source:find("lazy.nvim", 1, true) then
return info.source:sub(2)
end
f = f + 1
end
end
-- Fast implementation to check if a table is a list -- Fast implementation to check if a table is a list
---@param t table ---@param t table
function M.is_list(t) function M.is_list(t)