Skip to content

Commit b28c6b9

Browse files
committed
feat(util): Util.merge now support advanced merging strategies. Docs coming soon
1 parent e6ee0fa commit b28c6b9

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

TODO.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# ✅ TODO
22

3+
- [ ] better merging options?
4+
- [ ] especially what to do with merging of handlers?
5+
- [ ] overwriting keymaps probably doesn't work
6+
- [ ] disabled deps?
7+
38
- [x] fancy UI to manage all your Neovim plugins
49
- [x] auto lazy-loading of lua modules
510
- [x] lazy-loading on events, commands, filetypes and key mappings

lua/lazy/core/plugin.lua

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -270,20 +270,10 @@ function Spec:merge(old, new)
270270

271271
for _, prop in ipairs(list_merge) do
272272
if new[prop] and old[prop] then
273-
---@type any[]
274-
local props = {}
275-
---@diagnostic disable-next-line: no-unknown
276-
for _, value in ipairs(old[prop]) do
277-
props[#props + 1] = value
273+
if new[prop].__merge == nil then
274+
new[prop].__merge = true
278275
end
279-
---@diagnostic disable-next-line: no-unknown
280-
for _, value in ipairs(new[prop]) do
281-
if not vim.tbl_contains(props, value) then
282-
props[#props + 1] = value
283-
end
284-
end
285-
---@diagnostic disable-next-line: no-unknown
286-
new[prop] = props
276+
new[prop] = Util.merge(old[prop], new[prop])
287277
end
288278
end
289279
new._.super = old

lua/lazy/core/util.lua

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,27 @@ function M.debug(msg, level, opts)
286286
end
287287
end
288288

289+
local MERGE = "__merge"
290+
289291
local function can_merge(v)
290292
return type(v) == "table" and (vim.tbl_isempty(v) or not M.is_list(v))
291293
end
292294

295+
local function can_extend(v)
296+
return type(v) == "table" and (vim.tbl_isempty(v) or M.is_list(v))
297+
end
298+
299+
---@param v any|{__merge:boolean}
300+
---@param merge? boolean
301+
---@return boolean?
302+
local function check_merge(v, merge)
303+
if type(v) == "table" and v[MERGE] ~= nil then
304+
merge = v[MERGE]
305+
v[MERGE] = nil
306+
end
307+
return merge
308+
end
309+
293310
--- Merges the values similar to vim.tbl_deep_extend with the **force** behavior,
294311
--- but the values can be any type, in which case they override the values on the left.
295312
--- Values will me merged in-place in the first left-most table. If you want the result to be in
@@ -301,12 +318,24 @@ end
301318
function M.merge(...)
302319
local values = { ... }
303320
local ret = values[1]
321+
322+
if ret == vim.NIL then
323+
ret = nil
324+
end
325+
326+
local merge = check_merge(ret)
327+
304328
for i = 2, #values, 1 do
305329
local value = values[i]
306-
if can_merge(ret) and can_merge(value) then
330+
merge = check_merge(value, merge)
331+
if can_merge(ret) and can_merge(value) and merge ~= false then
307332
for k, v in pairs(value) do
308333
ret[k] = M.merge(ret[k], v)
309334
end
335+
elseif can_extend(ret) and can_extend(value) and merge then
336+
for _, v in ipairs(value) do
337+
ret[#ret + 1] = v
338+
end
310339
elseif value == vim.NIL then
311340
ret = nil
312341
else

tests/core/util_spec.lua

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,45 @@ describe("util", function()
132132
assert(root, "foobar root not found")
133133
assert.same(Helpers.path("new/lua/foobar"), root)
134134
end)
135+
136+
it("merges correctly", function()
137+
local tests = {
138+
{
139+
input = { { a = 1 }, { b = 2 } },
140+
output = { a = 1, b = 2 },
141+
},
142+
{
143+
input = { { a = 1 }, { a = 2 } },
144+
output = { a = 2 },
145+
},
146+
{
147+
input = { { a = { 1, 2 } }, { a = { 3 } } },
148+
output = { a = { 3 } },
149+
},
150+
{
151+
input = { { b = { 1, 2 } }, { a = { 3 }, __merge = false } },
152+
output = { a = { 3 } },
153+
},
154+
{
155+
input = { { a = 1 }, { b = 2, __merge = false } },
156+
output = { b = 2 },
157+
},
158+
{
159+
input = { { a = { 1, 2 } }, { a = { 3, __merge = true } } },
160+
output = { a = { 1, 2, 3 } },
161+
},
162+
{
163+
input = { { a = { 1, 2, __merge = true } }, { a = { 3 } } },
164+
output = { a = { 1, 2, 3 } },
165+
},
166+
{
167+
input = { { a = { 1, 2, __merge = true } }, { a = { 3, __merge = false } } },
168+
output = { a = { 3 } },
169+
},
170+
}
171+
172+
for _, test in ipairs(tests) do
173+
assert.same(test.output, Util.merge(unpack(test.input)))
174+
end
175+
end)
135176
end)

0 commit comments

Comments
 (0)