diff options
Diffstat (limited to '')
| -rw-r--r-- | dot_config/nvim/lua/transformer.lua | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/dot_config/nvim/lua/transformer.lua b/dot_config/nvim/lua/transformer.lua new file mode 100644 index 0000000..a479826 --- /dev/null +++ b/dot_config/nvim/lua/transformer.lua @@ -0,0 +1,80 @@ +--[[ + Transformer.lua + A transforming meta-flow originally built for packer. + + TL;DR you have a function to which you want to eventually pass a table. + With this, you can construct the table piece by piece. + It will finally call out once you pass () or a string. + The string will *prepend* itself to the object. + + Merging rules are a bit complicated: + For tables, we merge the ipairs in order (left to right). + The final '' is an exception. + Then we merge the map-like keys recursively. + If the target is a table but the merged key isn't, we append it. + Otherwise we always overwrite. +]]-- + +---@diagnostic disable-next-line: unused-vararg +local function tables(...) + for i=1,select('#') do + if type(select(i)) ~= 'table' then return false end + end + return true +end + +local function imerge(t1, t2) -- mutates t1 + for _, v in ipairs(t2) do table.insert(t1, v) end +end + +local bigmerge -- forward declaration + +local function kmerge(t1, t2) -- mutates t2 + for k, v in pairs(t2) do + if type(k) == 'number' and k >= 1 and k <= #t1 then + -- skip, we did this in imerge + else + if t1[k] and type(t1[k]) == 'table' then + if type(v) == 'table' then + t1[k] = bigmerge(t1[k], v) + else + table.insert(t1[k], v) + end + else + t1[k] = v + end + end + end +end + +bigmerge = function(t1, t2) + assert(tables(t1, t2)) + local out = {} + imerge(out, t1) + imerge(out, t2) + kmerge(out, t1) + kmerge(out, t2) + return out +end + +local function tgen(use) return function (self, obj) + if obj == nil then return use(self) end + + if type(obj) == 'string' then + local out = { obj } + imerge(out, self) + kmerge(out, self) + return setmetatable(out, getmetatable(self))() + elseif type(obj) == 'table' then + local out = bigmerge(self, obj) + return setmetatable(out, getmetatable(self)) + + else + error 'Invalid argument.' + end + +end end + +return function(use) + return setmetatable({}, { __call = tgen(use) }) +end |
