diff --git a/TODO.md b/TODO.md index 5ad36cb..59607a5 100644 --- a/TODO.md +++ b/TODO.md @@ -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 diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua index adaefae..8156240 100644 --- a/lua/lazy/core/plugin.lua +++ b/lua/lazy/core/plugin.lua @@ -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 diff --git a/lua/lazy/core/util.lua b/lua/lazy/core/util.lua index 213a217..981ad34 100644 --- a/lua/lazy/core/util.lua +++ b/lua/lazy/core/util.lua @@ -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 @@ -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 diff --git a/tests/core/util_spec.lua b/tests/core/util_spec.lua index 7349c68..7d16ca6 100644 --- a/tests/core/util_spec.lua +++ b/tests/core/util_spec.lua @@ -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)