Skip to content

Commit

Permalink
feat(util): Util.merge now support advanced merging strategies. Doc…
Browse files Browse the repository at this point in the history
…s coming soon
  • Loading branch information
folke committed Jan 10, 2023
1 parent e6ee0fa commit b28c6b9
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 14 deletions.
5 changes: 5 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# ✅ TODO

- [ ] better merging options?
- [ ] especially what to do with merging of handlers?
- [ ] overwriting keymaps probably doesn't work
- [ ] disabled deps?

- [x] fancy UI to manage all your Neovim plugins
- [x] auto lazy-loading of lua modules
- [x] lazy-loading on events, commands, filetypes and key mappings
Expand Down
16 changes: 3 additions & 13 deletions lua/lazy/core/plugin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -270,20 +270,10 @@ function Spec:merge(old, new)

for _, prop in ipairs(list_merge) do
if new[prop] and old[prop] then
---@type any[]
local props = {}
---@diagnostic disable-next-line: no-unknown
for _, value in ipairs(old[prop]) do
props[#props + 1] = value
if new[prop].__merge == nil then
new[prop].__merge = true
end
---@diagnostic disable-next-line: no-unknown
for _, value in ipairs(new[prop]) do
if not vim.tbl_contains(props, value) then
props[#props + 1] = value
end
end
---@diagnostic disable-next-line: no-unknown
new[prop] = props
new[prop] = Util.merge(old[prop], new[prop])
end
end
new._.super = old
Expand Down
31 changes: 30 additions & 1 deletion lua/lazy/core/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,27 @@ function M.debug(msg, level, opts)
end
end

local MERGE = "__merge"

local function can_merge(v)
return type(v) == "table" and (vim.tbl_isempty(v) or not M.is_list(v))
end

local function can_extend(v)
return type(v) == "table" and (vim.tbl_isempty(v) or M.is_list(v))
end

---@param v any|{__merge:boolean}
---@param merge? boolean
---@return boolean?
local function check_merge(v, merge)
if type(v) == "table" and v[MERGE] ~= nil then
merge = v[MERGE]
v[MERGE] = nil
end
return merge
end

--- Merges the values similar to vim.tbl_deep_extend with the **force** behavior,
--- but the values can be any type, in which case they override the values on the left.
--- Values will me merged in-place in the first left-most table. If you want the result to be in
Expand All @@ -301,12 +318,24 @@ end
function M.merge(...)
local values = { ... }
local ret = values[1]

if ret == vim.NIL then
ret = nil
end

local merge = check_merge(ret)

for i = 2, #values, 1 do
local value = values[i]
if can_merge(ret) and can_merge(value) then
merge = check_merge(value, merge)
if can_merge(ret) and can_merge(value) and merge ~= false then
for k, v in pairs(value) do
ret[k] = M.merge(ret[k], v)
end
elseif can_extend(ret) and can_extend(value) and merge then
for _, v in ipairs(value) do
ret[#ret + 1] = v
end
elseif value == vim.NIL then
ret = nil
else
Expand Down
41 changes: 41 additions & 0 deletions tests/core/util_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,45 @@ describe("util", function()
assert(root, "foobar root not found")
assert.same(Helpers.path("new/lua/foobar"), root)
end)

it("merges correctly", function()
local tests = {
{
input = { { a = 1 }, { b = 2 } },
output = { a = 1, b = 2 },
},
{
input = { { a = 1 }, { a = 2 } },
output = { a = 2 },
},
{
input = { { a = { 1, 2 } }, { a = { 3 } } },
output = { a = { 3 } },
},
{
input = { { b = { 1, 2 } }, { a = { 3 }, __merge = false } },
output = { a = { 3 } },
},
{
input = { { a = 1 }, { b = 2, __merge = false } },
output = { b = 2 },
},
{
input = { { a = { 1, 2 } }, { a = { 3, __merge = true } } },
output = { a = { 1, 2, 3 } },
},
{
input = { { a = { 1, 2, __merge = true } }, { a = { 3 } } },
output = { a = { 1, 2, 3 } },
},
{
input = { { a = { 1, 2, __merge = true } }, { a = { 3, __merge = false } } },
output = { a = { 3 } },
},
}

for _, test in ipairs(tests) do
assert.same(test.output, Util.merge(unpack(test.input)))
end
end)
end)

0 comments on commit b28c6b9

Please sign in to comment.