FANDOM


local T, A, translate, back, arguments = {}, {}, {}, {}, {}
 
local getArgs = require('Dev:Arguments').getArgs
local checkType = require('libraryUtil').checkType
local inspect = require('Dev:Inspect').inspect -- debug
 
local MD, MD_list, MD_count = {}, {}, 0
function MD.new(key, parent)
    local obj = setmetatable({_v={}}, MD)
    if parent then
        key = tonumber(key)
        rawset(obj, 'key', key)
        rawset(obj, 'parent', parent)
        rawset(obj, 'translate', parent:param(key))
    else
        key = tostring(key)
        if mw.ustring.find(translate[key], '##') then
            error(mw.ustring.format('Bad pattern: \'%s\' for \'%s\' key (#\'s have to be separated)', translate[key], key), 3)
        end
        rawset(obj, 'key', key)
        rawset(obj, 'translate', translate[key])
    end
    local pattern, depth = mw.ustring.gsub(obj.translate, '#', '(%%-?%%d-)')
    rawset(obj, 'pattern', '^' .. pattern .. '$')
    rawset(obj, 'depth', tonumber(depth))
    return obj
end
function MD.__index(self, key)
    if MD[key] then return MD[key] end
    local i = tonumber(key)
    if not i then error('Bad key given to ' .. MD.tostring(self) .. ' parameter (number expected, got ' .. type(key) .. ')', 2) end
 
    local param = self:param(i)
    if self._v[i] then
        if self._v[i] == true then return arguments[param] end
        return self._v[i]
    end
    if mw.ustring.find(param, '#') then
        self._v[i] = MD.new(i, self)
        return self._v[i]
    end
    self._v[i] = not not arguments[param]
    return arguments[param]
end
function MD.__newindex(self, key, val)
    local i = tonumber(key)
    if not i then error('Bad key given to ' .. MD.tostring(self) .. ' parameter (number expected, got ' .. type(key) .. ')', 2) end
 
    local param = self:param(i)
    if mw.ustring.find(param, '#') then
        error('Only top level keys can be set', 2)
    end
    arguments[param] = val
    self._v[i] = not not arguments[param]
end
local function md_next(invariant)
    local key = table.remove(invariant.order, 1)
    if key then return key, invariant.tab[key] end
    return nil
end
function MD.__pairs(self)
    return md_next, {tab=self, order=self:keys(true)}
end
local function mdi_next(self, i)
    i = i+1
    if self._v[i] then return i, self[i] end
    return nil
end
function MD.__ipairs(self)
    return mdi_next, self, 0
end
function MD:len(full)
    if not not full then return #self:keys() end
    local c = 1
    while self._v[c] do c = c+1 end
    return c-1
end
function MD.__len(self)
    return self:len(false)
end
function MD.tostring(obj)
    if type(obj) ~= 'table' then return tostring(obj) end
    if rawget(obj, 'parent') == nil then return 'table[\'' .. tostring(obj.key) .. '\']' end
    return MD.tostring(rawget(obj, 'parent')) .. '[' .. tostring(obj.key) .. ']'
end
function MD:param(...)
    local p = self.translate
    for i,v in ipairs(arg) do
        checkType(':param', i, v, 'number', false)
        p = mw.ustring.gsub(p, '#', tostring(v), 1)
    end
    return p
end
local function getKeys(tab, sorted)
    local list = {}
    local k = next(tab)
    while k do
        list[#list+1] = k
        k = next(tab, k)
    end
    if sorted then table.sort(list) end
    return list
end
function MD:keys(sorted)
    return getKeys(self._v, sorted)
end
 
function T.getArgs(frame, options)
    options = options or {}
    translate = options.translate or {}
    for key,val in pairs(translate) do
        if mw.ustring.find(tostring(val), '#') then
            MD_list[key] = MD.new(key)
            MD_count = MD_count + 1
        else
            back[val] = key
        end
    end
    if MD_count == 0 then
        mw.log('No multi-dimensional parameters found. Returning regular Module:Arguments output. Consider using it instead.')
        return getArgs(frame, options)
    end
    options.translate = nil
    options.backtranslate = nil
    arguments = getArgs(frame, options)
 
    local meta = {}
    local A = setmetatable({}, meta)
    function meta.__index(self, key)
        if meta[key] then return meta[key] end
        if MD_list[key] then return MD_list[key] end
        if translate[key] then key = translate[key] end
        return arguments[key]
    end
    function meta.__newindex(self, key, val)
        if MD_list[key] then MD_list[key] = val end
        if translate[key] then key = translate[key] end
        arguments[key] = val
    end
 
    local rawArgs = select(2, pairs(arguments)).t
    local function t_next(invariant)
        local key, val = invariant.k or true, nil
        while key do
            key, val = next(invariant.t, invariant.k)
            invariant.k = key
            if key == nil then
                meta.scanDone = true
                invariant.n = invariant.n or {}
                if #invariant.n > 0 then
                    invariant.t = table.remove(invariant.n, 1)
                    invariant.k = nil
                    key = true
                else
                    return nil
                end
            elseif type(key) ~= 'string' or MD_count == 0 then
                return key, val
            else
                if back[key] and key == translate[back[key]] then
                    return back[key], val
                end
                for k,v in pairs(invariant.check or MD_list) do
                    local m = {mw.ustring.match(key, v.pattern)}
                    if #m > 0 then
                        local dummy, i = v, table.remove(m, 1)
                        while i do
                            dummy = dummy[i]
                            i = table.remove(m, 1)
                        end
                        val = nil
                        break
                    end
                end
                if val then return key, val end
            end
        end
    end
    function meta.__pairs()
        return t_next, {t=rawArgs,n={MD_list}}
    end
 
    local function i_next(self, i)
        local v = self[i+1]
        if v ~= nil then return i+1, v end
    end
    function meta.__ipairs(self) return i_next, self, 0 end
 
    function meta:scan(...)
        if not meta.scanDone then
            for k,v in pairs(self) do end
            meta.scanDone = true
        end
        return self
    end
 
    local function merge(first, second, overwrite)
        overwrite = not not overwrite
        for k,v in pairs(second) do
            if type(first[k]) == 'table' and type(v) == 'table' then
                first[k] = merge(first[k], v, overwrite)
            elseif overwrite or first[k] == nil then
                first[k] = v
            end
        end
        return first
    end
    local function flip(md, key, depth)
        local res = {}
        for k,v in pairs(md) do
            if depth > 1 and type(v) == 'table' then
                res[k] = flip(v, key, depth-1)
            else
                res[k] = res[k] or {}
                res[k][key] = v
            end
        end
        return res
    end
    local function tConcat(t1, ...)
        for _,tab in ipairs(arg) do
            for i,v in ipairs(tab) do
                t1[#t1+1] = v
            end
        end
        return t1
    end
    local function optionals(tab, opt, depth, keys)
        keys = keys or {}
        for k,v in pairs(tab) do
            local keys = tConcat({}, keys, {k})
            if depth > 1 then
                optionals(v, opt, depth-1, keys)
            else
                for _,k in ipairs(opt) do
                    local val, i = MD_list[k], 1
                    while keys[i] do
                        val = val[keys[i]]
                        i = i+1
                    end
                    v[k] = val
                end
            end
        end
    end
 
    function meta:group(req, opt, depth)
        self:scan()
        if type(req) ~= 'table' then req = {req} end
        if type(opt) ~= 'table' then opt = {opt} end
        depth = tonumber(depth)
 
        local reqMDs, optMDs = {}, {}
        for i,key in ipairs(req) do
            if MD_list[key] then
                reqMDs[#reqMDs+1] = key
                if not depth then
                    depth = MD_list[key].depth
                elseif MD_list[key].depth < depth then
                    depth = MD_list[key].depth
                end
            end
        end
        for i,key in ipairs(opt) do
            if MD_list[key] then
                optMDs[#optMDs+1] = key
                if not depth then
                    depth = MD_list[key].depth
                elseif MD_list[key].depth < depth then
                    depth = MD_list[key].depth
                end
            end
        end
        local res = {}
        for i,key in ipairs(reqMDs) do
            merge(res, flip(self[key], key, depth))
        end
        optionals(res, opt, depth)
        return res
    end
    return A, MD_list
end
 
T.args = {
    [1] = "1",
    [2] = "2",
    [3] = "3",
    [4] = "4",
    [5] = "5",
    [6] = "6",
    [7] = "7",
    [8] = "8",
    [10] = "10",
    [11] = "11",
    ['Bohater'] = "Lorem",
    ['Opis 1'] = "Ipsum",
    ['Opis 2'] = "Dolor",
    ['Opis 3'] = "Sit",
    ['Opis 4'] = "Amet",
    ['Opis 6'] = "Consectetur",
    ['Ikona 1'] = "Ipsum",
    ['Ikona 2'] = "Dolor",
    ['Poziomy 3'] = "Sit",
    ['Poziomy 5'] = "Amet",
    ['Poziomy 2'] = "Consectetur",
 
    ['Test 1.1'] = "Adipiscing",
    ['Test 1.2'] = "Elit",
    ['Test 1.3'] = "In",
    ['Test 2.1'] = "Non",
    ['Test 2.2'] = "Odio",
    ['Test 2.3'] = "Rutrum",
    ['Test 3.1'] = "Tristique",
    ['Test 3.2'] = "Elit",
    ['Test 3.3'] = "Eu",
 
    ['Testy 1.1'] = "xxAdipiscing",
    ['Testy 1.2'] = "xxElit",
    ['Testy 1.3'] = "xxIn",
    ['Testy 3.1'] = "xxTristique",
    ['Testy 3.2'] = "xxElit",
    ['Testy 3.3'] = "xxEu",
 
    ['Tests 1.1.1'] = "Eros",
    ['Tests 1.1.2'] = "Nulla",
    --['Tests 1.2.1'] = "Nibh",
    --['Tests 1.2.2'] = "Turpis",
    --['Tests 2.1.1'] = "Varius",
    --['Tests 2.1.2'] = "In",
    --['Tests 2.2.1'] = "Velit",
    --['Tests 2.2.2'] = "Ut",
    --['Tests -1.2.2'] = "Ut",
    --['Tests 0.2.2'] = "Ut",
 
    ['Tests 3.1.1'] = "a",
    ['Tests 3.2.1'] = "b",
    ['Tests 3.3.1'] = "c",
}
function dump(tab, indent, func)
    if type(tab) ~= 'table' then return end
    func = func or pairs
    indent = indent or ''
    for k,v in func(tab) do
        mw.log(indent..'['..tostring(k)..'] = '..tostring(v))
        dump(v, indent..'['..tostring(k)..'] ', func)
    end
end
function T.test(a)
    local s, res = pcall(function()
        local targs, args = T.getArgs(T.args, {
            translate = {
                champ = 'Bohater',
                one = 'Opis #',
                lvls = 'Poziomy #',
                icon = 'Ikona #',
                two = 'Test #.#',
                two2 = 'Testy #.#',
                three = 'Tests #.#.#'
            }
        })
        if a == 1 then
            dump(targs:group({'two'}, {'icon', 'one', 'lvls', 'three'}))
        elseif a == 2 then
            dump(targs)
        else
            dump(targs:group({'two'}, {'two2', 'three', 'icon'}))
        end
    end)
    mw.log('\n-------------------------------\n' .. tostring(res or 'OK'))
end
 
return T

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.