Skip to content

Commit c10645f

Browse files
committed
...
1 parent d7c05ff commit c10645f

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

lua/dotvim/core/package.lua

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---@class dotvim.core.package
2+
local M = {}
3+
4+
---@class dotvim.core.package.PackageOption
5+
---@field name string
6+
---@field deps? string[]
7+
---@field setup? fun():any
8+
---@field plugins? dotvim.core.plugin.PluginOption[]
9+
10+
---@class dotvim.core.package.Package
11+
---@field private _ dotvim.core.package.PackageOption
12+
local Package = {}
13+
14+
function Package:name()
15+
return self._.name
16+
end
17+
18+
---@return string[]
19+
function Package:deps()
20+
return self._.deps or {}
21+
end
22+
23+
---@return dotvim.core.plugin.PluginOption[]
24+
function Package:plugins()
25+
return self._.plugins or {}
26+
end
27+
28+
function Package:setup()
29+
if self._.setup then
30+
self._.setup()
31+
end
32+
end
33+
34+
local loaded_packages = {}
35+
36+
---@param opts dotvim.core.package.PackageOption
37+
---@return dotvim.core.package.Package
38+
local function create_package(opts)
39+
local p = { _ = opts }
40+
local pkg = setmetatable(p, { __index = Package })
41+
loaded_packages[pkg:name()] = pkg
42+
return pkg
43+
end
44+
45+
---@param packages table<string, dotvim.core.package.Package>
46+
---@return dotvim.core.package.Package[]
47+
function M.sort_packages(packages)
48+
---@type table<string, string[]>
49+
local outgoing_edges = {}
50+
---@type table<string, number>
51+
local incoming_counts = {}
52+
53+
local num_of_packages = 0
54+
55+
for _, pkg in pairs(packages) do
56+
for _, dep in ipairs(pkg:deps()) do
57+
if outgoing_edges[dep] == nil then
58+
outgoing_edges[dep] = {}
59+
end
60+
table.insert(outgoing_edges[dep], pkg:name())
61+
incoming_counts[pkg:name()] = (incoming_counts[pkg:name()] or 0) + 1
62+
end
63+
num_of_packages = num_of_packages + 1
64+
end
65+
for name, _ in pairs(packages) do
66+
if incoming_counts[name] == nil then
67+
incoming_counts[name] = 0
68+
end
69+
end
70+
71+
local queue = {}
72+
for name, count in pairs(incoming_counts) do
73+
if count == 0 then
74+
table.insert(queue, name)
75+
end
76+
end
77+
78+
if #queue == 0 then
79+
vim.print(outgoing_edges)
80+
error("No packages as first")
81+
end
82+
83+
---@type string[]
84+
local sorted = {}
85+
86+
while #queue > 0 do
87+
local name = table.remove(queue, 1)
88+
table.insert(sorted, name)
89+
90+
if outgoing_edges[name] then
91+
for _, outgoing in ipairs(outgoing_edges[name]) do
92+
incoming_counts[outgoing] = incoming_counts[outgoing] - 1
93+
if incoming_counts[outgoing] == 0 then
94+
table.insert(queue, outgoing)
95+
end
96+
end
97+
end
98+
end
99+
100+
if #sorted ~= num_of_packages then
101+
error("Not all packages are sorted")
102+
end
103+
104+
local res = {}
105+
for _, name in ipairs(sorted) do
106+
res[#res + 1] = packages[name]
107+
end
108+
return res
109+
end
110+
111+
---@param name string
112+
---@return dotvim.core.package.Package?
113+
function M.load_package(name)
114+
if loaded_packages[name] then
115+
return loaded_packages[name]
116+
end
117+
118+
local module = require(name)
119+
if module == nil then
120+
vim.notify("Failed to load package module: " .. name, vim.log.levels.WARN)
121+
return nil
122+
end
123+
124+
local pkg = create_package(module)
125+
126+
-- load dependencies
127+
for _, dep in ipairs(pkg:deps()) do
128+
M.load_package(dep)
129+
end
130+
end
131+
132+
function M.sort_loaded_packages()
133+
return M.sort_packages(loaded_packages)
134+
end
135+
136+
return M

0 commit comments

Comments
 (0)