Skip to content

Commit

Permalink
feat!: plugins are now autmatically loaded on require. module= no l…
Browse files Browse the repository at this point in the history
…onger needed!
  • Loading branch information
folke committed Dec 2, 2022
1 parent 0b6dec4 commit 575421b
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 52 deletions.
33 changes: 0 additions & 33 deletions lua/lazy/core/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ local Config = require("lazy.core.config")
---@field event? string|string[]
---@field cmd? string|string[]
---@field ft? string|string[]
---@field module? string|string[]
---@field keys? string|string[]

local M = {}
Expand Down Expand Up @@ -116,36 +115,4 @@ function M.handlers.cmd(grouped)
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
57 changes: 53 additions & 4 deletions lua/lazy/core/loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local M = {}

---@type LazyPlugin[]
M.loading = {}
M.init_done = false

function M.setup()
-- install missing plugins
Expand All @@ -25,6 +26,9 @@ function M.setup()
local Handler = require("lazy.core.handler")
Handler.setup()
Util.track()

-- autoload opt plugins
table.insert(package.loaders, M.autoload)
end

function M.init_plugins()
Expand All @@ -42,14 +46,15 @@ function M.init_plugins()
end
Util.track()
Util.track()
M.init_done = true
end

---@class Loader
---@param plugins string|LazyPlugin|string[]|LazyPlugin[]
---@param reason {[string]:string}
function M.load(plugins, reason)
---@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)[]

for _, plugin in ipairs(plugins) do
Expand All @@ -64,17 +69,21 @@ function M.load(plugins, reason)
end
if #M.loading > 0 then
plugin._.loaded.plugin = M.loading[#M.loading].name
elseif reason.require then
plugin._.loaded.source = Util.get_source()
end

table.insert(M.loading, plugin)

Util.track({ plugin = plugin.name, start = reason.start })
M.packadd(plugin)

vim.opt.runtimepath:prepend(plugin.dir)

if plugin.dependencies then
M.load(plugin.dependencies, {})
end

M.packadd(plugin)
if plugin.config then
Util.try(plugin.config, "Failed to run `config` for " .. plugin.name)
end
Expand All @@ -90,8 +99,16 @@ end

---@param plugin LazyPlugin
function M.packadd(plugin)
vim.cmd.packadd(plugin.name)
M.source_runtime(plugin, "/after/plugin")
-- 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")
end
end

---@param plugin LazyPlugin
Expand All @@ -105,4 +122,36 @@ function M.source_runtime(plugin, dir)
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
30 changes: 16 additions & 14 deletions lua/lazy/core/plugin.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
local Config = require("lazy.core.config")
local Util = require("lazy.core.util")
local Module = require("lazy.core.module")
local Handler = require("lazy.core.handler")

local M = {}
Expand Down Expand Up @@ -38,7 +37,7 @@ local M = {}
---@field dependencies? string[]
---@field _ LazyPluginState

---@alias LazySpec string|LazyPlugin|LazySpec[]|{dependencies:LazySpec}
---@alias LazySpec string|LazyPlugin|LazyPlugin[]|{dependencies:LazySpec}

---@class LazySpecLoader
---@field plugins table<string, LazyPlugin>
Expand Down Expand Up @@ -156,13 +155,7 @@ function M.update_state()
for _, plugin in pairs(Config.plugins) do
plugin._ = plugin._ or {}
if plugin.lazy == nil then
local lazy = plugin.dep
or Config.options.defaults.lazy
or plugin.module
or plugin.event
or plugin.keys
or plugin.ft
or plugin.cmd
local lazy = plugin.dep or Config.options.defaults.lazy or plugin.event or plugin.keys or plugin.ft or plugin.cmd
plugin.lazy = lazy and true or false
end
plugin.dir = Config.root .. "/" .. plugin.name
Expand Down Expand Up @@ -193,16 +186,15 @@ function M.spec()

if type(Config.spec) == "string" then
-- spec is a module
local function _load(name, modpath)
local modname = Config.spec .. (name and ("." .. name) or "")
local function _load(name)
local modname = name and (Config.spec .. "." .. name) or Config.spec
Util.try(function()
spec:normalize(Module.load(modname, modpath))
spec:normalize(require(modname))
end, "Failed to load **" .. modname .. "**")
end
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)
else
-- spec is a spec
Expand All @@ -228,4 +220,14 @@ function M.load()
Util.track()
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
16 changes: 15 additions & 1 deletion lua/lazy/core/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function M.try(fn, msg)
if not info then
break
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)
if source:find(Config.root, 1, true) == 1 then
source = source:sub(#Config.root + 1)
Expand Down Expand Up @@ -67,6 +67,20 @@ function M.try(fn, msg)
return ok and result or nil
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
---@param t table
function M.is_list(t)
Expand Down

0 comments on commit 575421b

Please sign in to comment.