League of Legends Wiki
Advertisement
League of Legends Wiki

Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Translate/opis

local T, A, translate, back, arguments = {}, {}, {}, {}, {}

local getArgs = require('Dev:Arguments').getArgs
local checkType = require('libraryUtil').checkType

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
return T
-- [[Kategoria:Moduły]]
Advertisement