lazy.nvim/lua/lazy/core/module.lua

134 lines
3.2 KiB
Lua

local Cache = require("lazy.core.cache")
local M = {}
---@type table<string, {file: string, hash?:string}>
M.modules = {}
function M.add(modname, file)
if not M.modules[modname] then
M.modules[modname] = { file = file }
end
end
---@param modname string
function M.load(modname)
if type(package.loaded[modname]) == "table" then
return package.loaded[modname]
end
local info = M.modules[modname]
if info then
local err
---@type string|fun()|nil
local chunk = Cache.get(modname)
if not chunk then
vim.schedule(function()
vim.notify("loading " .. modname)
end)
chunk, err = loadfile(info.file)
if chunk then
Cache.set(modname, string.dump(chunk))
info.hash = info.hash or Cache.hash(info.file)
end
end
if type(chunk) == "string" then
chunk, err = loadstring(chunk --[[@as string]], "@" .. info.file)
end
if not chunk then
error(err)
end
---@type table
local mod = chunk()
package.loaded[modname] = mod
return mod
end
end
local function _add_module(dir, modname)
local d = vim.loop.fs_opendir(dir, nil, 100)
if d then
---@type {name: string, type: "file"|"directory"|"link"}[]
local entries = vim.loop.fs_readdir(d)
while entries do
for _, entry in ipairs(entries) do
local path = dir .. "/" .. entry.name
if entry.type == "directory" then
_add_module(path, modname and (modname .. "." .. entry.name) or entry.name)
else
local childname = entry.name:match("^(.*)%.lua$")
if childname then
local child = entry.name == "init.lua" and modname or modname and (modname .. "." .. childname) or childname
if child then
M.add(child, path)
end
end
end
end
entries = vim.loop.fs_readdir(d)
end
vim.loop.fs_closedir(d)
end
end
function M.add_module(path)
if path:find("/lua/?$") then
return _add_module(path)
end
---@type string
local modname = path:match("/lua/(.*)/?")
assert(modname)
modname = modname:gsub("/", ".")
if vim.loop.fs_stat(path .. ".lua") then
M.add(modname, path .. ".lua")
end
_add_module(path, modname)
end
function M.setup()
-- load cache
local value = Cache.get("cache.modules")
if value then
M.modules = vim.json.decode(value)
for k, v in pairs(M.modules) do
if Cache.hash(v.file) ~= v.hash then
Cache.del(k)
M.changed = true
M.modules[k] = nil
end
end
end
-- preload core modules
local root = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":p:h:h")
for _, name in ipairs({ "util", "config", "loader", "state" }) do
local modname = "lazy.core." .. name
M.add(modname, root .. "/core/" .. name:gsub("%.", "/") .. ".lua")
end
table.insert(package.loaders, 2, function(modname)
if M.modules[modname] then
return function()
return M.load(modname)
end
end
end)
return M
end
function M.save()
local value = {}
for k, v in pairs(M.modules) do
if v.hash then
value[k] = v
end
end
Cache.set("cache.modules", vim.json.encode(value))
end
return M