欢迎大家来到沙石镇时光中文维基!本站编辑权限开放,欢迎加入中文维基 QQ 群「沙海时光」:372816689
目前正在进行全站数据更新,期间可能会存在显示异常的问题。
全站通知:
模块:Helper
刷
历
编
跳到导航
跳到搜索
此模块的文档可以在模块:Helper/doc创建
local VERSION = 'V4.1.2.4'
local REVISION = 0
local cache = require("mw.ext.LuaCache")
local KEY_PREFIX = "Module:Helper"
local EXP_TIME = 172800
-- ----------------------------------------
-- <pre> Module:Helper
-- Collection of small helper functions
-- ----------------------------------------
local Self = {} -- table of functions
local ustr = mw.ustring -- quick/short access to ustring table
-- ----------------------------------------
-- Variables
-- ----------------------------------------
local g_IsDesktop = true
-- ----------------------------------------
-- Helper Functions
-- ----------------------------------------
function Self.GetArgs(frame)
local f
for k, v in pairs(frame.args) do
return frame.args
end
return frame:getParent().args
end
function Self.EscapeMagicCharacters(item)
item = ustr.gsub(item, "&#(%d+);", function(n)
return ustr.char(n)
end)
item = ustr.gsub(item, "%%", "%%%%")
item = ustr.gsub(item, "^%^", "%%^")
item = ustr.gsub(item, "%$$", "%%$")
item = ustr.gsub(item, "%(", "%%(")
item = ustr.gsub(item, "%)", "%%)")
item = ustr.gsub(item, "%.", "%%.")
item = ustr.gsub(item, "%[", "%%[")
item = ustr.gsub(item, "%]", "%%]")
item = ustr.gsub(item, "%*", "%%*")
item = ustr.gsub(item, "%+", "%%+")
item = ustr.gsub(item, "%-", "%%-")
item = ustr.gsub(item, "%?", "%%?")
return item
end
function Self.IfDesktop(a, b)
if a ~= nil then
return a or (b or "")
else
return true
end
end
function Self.IfMobile(a, b)
if a ~= nil then
return not a or (b or "")
else
return not true
end
end
function Self.Exp(frame)
return Self.Explode(frame.args[1], frame, frame.args[2])
end
function Self.Explode(text, frame, skippre)
-- adds a middot between each letter to allow seeing what we are dealing with
frame = frame or mw.getCurrentFrame()
if not skippre then
text = frame:preprocess(text or "")
end
local str = ""
for l in ustr.gmatch(text, ".") do
str = str .. "·" .. l
end
return "Code: " .. str
end
function Self.Dump(o)
-- Dumps the contents of a variable into a <pre>
local str = ""
local serialize
serialize = function(o, s)
local t = type(o)
if o == nil then
str = str .. "nil"
elseif t == "number" then
str = str .. o
elseif t == "string" then
str = str .. ustr.format("%q", o)
elseif t == "boolean" then
str = str .. (o and "true" or "false")
elseif t == "table" then
str = str .. "{\n"
local l = s
s = s .. " "
for k, v in pairs(o) do
str = str .. s .. "["
serialize(k, s)
str = str .. "] = "
serialize(v, s)
str = str .. ",\n"
end
str = str .. l .. "}"
else
error("cannot serialize a " .. type(v))
end
end
serialize(o, "")
return "<pre>" .. str .. "</pre>"
end
function isSeq(obj)
if type(obj) ~= "table" then return false end
local max = 0
local count = 0
for k, v in pairs(obj) do
if type(k) ~= "number" or k < 1 then return false end
if max < k then max = k end
count = count + 1
end
return count == max
end
function Self.dumpPretty(obj, indent)
if type(obj) == "table" then
local entries = {}
local big = false
if isSeq(obj) then
for j, v in ipairs(obj) do
entries[j] = Self.dumpPretty(v, indent + 1)
if type(v) == "table" then big = true end
if string.match(entries[j], "\n") then big = true end
end
else
for k, v in pairs(obj) do
if k ~= "id" and k ~= "name" then
local kk = k
if type(k) ~= "string" or string.match(k, "[^%w_]") then
kk = "[" .. Self.dumpPretty(k, indent + 1) .. "]"
end
local vv = Self.dumpPretty(v, indent + 1)
table.insert(entries, kk .. " = " .. vv)
if string.match(vv, "\n") then big = true end
if type(v) == "table" then big = true end
end
end
table.sort(entries)
if obj.id then table.insert(entries, 1, "id = " .. Self.dumpPretty(obj.id, indent + 1)) end
if obj.name then table.insert(entries, 1, "name = " .. Self.dumpPretty(obj.name, indent + 1)) end
end
if big or #entries > 4 then
return "{\n" .. string.rep("\t", indent + 1) .. table.concat(entries, ",\n" .. string.rep("\t", indent + 1)) .. "\n" .. string.rep("\t", indent) .. "}"
elseif #entries == 0 then
return "{}"
else
return "{ " .. table.concat(entries, ", ") .. " }"
end
elseif type(obj) == "string" then
if not string.match(obj, "[%c\\\"]") then return '"' .. obj .. '"' else
return '"' .. string.gsub(obj, "[%c\\\"]", function(c)
if c == '"' or c == "\\" then return "\\" .. c
elseif c == "\t" then return "\\t"
elseif c == "\n" then return "\\n"
else return "\\" .. string.byte(c)
end
end) .. '"'
end
else
return tostring(obj)
end
end
function Self.HashArgs(...)
local a = {}
local Hash
Hash = function(key, value)
local t = type(value)
if t == "table" then
for k, v in pairs(value) do
Hash(key .. tostring(k) .. "=", v)
end
else
table.insert(a, tostring(key) .. tostring(value) .. t)
end
end
Hash("", {
...
})
table.sort(a)
return table.concat(a, ",")
end
function Self.Map(array, callbackFn)
local ret = {}
for i, x in ipairs(array) do
ret[i] = callbackFn(x)
end
return ret
end
function Self.Filter(array, callbackFn)
local ret = {}
for _, x in ipairs(array) do
if callbackFn(x) then
table.insert(ret, x)
end
end
return ret
end
function Self.Exists(array, func)
-- This cannot be implemented with Find
-- in case the matching element is itself nil
for _, x in ipairs(array) do
if func(x) then
return true
end
end
return false
end
function Self.Find(array, func)
-- There is no way for the caller to distinguish
-- "we found the nil" from "we didn't find anything"
for _, x in ipairs(array) do
if func(x) then
return x
end
end
return nil
end
function Self.Contains(array, value)
for _, x in ipairs(array) do
if value == x then
return true
end
end
return false
end
function Self.MapT(t, callbackFn)
local ret = {}
for i, x in pairs(t) do
ret[i] = callbackFn(x)
end
return ret
end
function Self.FilterT(t, callbackFn)
local ret = {}
for i, x in pairs(t) do
if callbackFn(x) then
ret[i] = x
end
end
return ret
end
function Self.Values(t)
local ret = {}
for _, x in pairs(t) do
table.insert(ret, x)
end
return ret
end
function Self.StartsWith(str, prefix)
if (str) then
return str:sub(1, prefix:len()) == prefix
else
end
end
function Self.ExpandTemplate(title, args)
return mw.getCurrentFrame():expandTemplate{
title = title,
args = args
}
end
function Self.ExpandTemplateDebug(title, args)
local ret = "{{" .. title
i = 1
while args[i] ~= nil do
ret = ret .. "|" .. args[i]
i = i + 1
end
for k, v in pairs(args) do
if type(k) ~= "number" or k > i then
ret = ret .. "|" .. k .. "=" .. tostring(v)
end
end
return ret .. "}}"
end
function Self.LazyLoad(moduleName)
local loaded = nil
local function doLoad()
if loaded == nil then
loaded = mw.loadData(moduleName)
if loaded.configList then
loaded = loaded.configList
end
end
return loaded
end
local meta = {}
meta.__index = function(_table, key)
return doLoad()[key]
end
meta.__pairs = function(_table)
return pairs(doLoad())
end
meta.__ipairs = function(_table)
return ipairs(doLoad())
end
local ret = {}
setmetatable(ret, meta)
return ret
end
function Self.LoadAsset(moduleName, purgeCache)
local cacheKey = KEY_PREFIX .. 'LoadAsset' .. moduleName
if true then
cache.delete(cacheKey)
end
--local cachedAsset = cache.get(cacheKey) or {}
--if cachedAsset.version == VERSION or cachedAsset.version == 'legacy' then
-- if cachedAsset.chunks then
-- -- metatable will not be cached
-- setupChunkedAssetMetatable(cachedAsset)
-- end
-- -- mw.log('Loaded cache', cacheKey)
-- return cachedAsset.configList
--end
local asset = mw.loadData(moduleName)
-- for backward compatibility
if asset.version == nil then
--cache.set(cacheKey, { version = 'legacy', configList = asset }, EXP_TIME)
return asset
end
-- AssetItemEnglish is obfuscated
--if asset.key == 'Text' then
-- for key, value in pairs(asset.configList) do
-- asset.configList[key] = Encoding.decode2(value)
-- end
--end
-- EXP_TIME here is only used to prevent leak
--cache.set(cacheKey, asset, EXP_TIME)
-- some modules are too large and are splitted into chunks
if asset.chunks then
local copy = { key = asset.key, chunks = asset.chunks, configList = {} }
for key, value in pairs(asset.configList) do
copy.configList[key] = value
end
setupChunkedAssetMetatable(copy)
asset = copy
end
return asset.configList
end
function setupChunkedAssetMetatable(asset)
local meta = {}
meta.__index = function(_table, key)
for _, chunk in ipairs(asset.chunks) do
if chunk.low <= key and key <= chunk.high then
local value = Self.LoadAsset('Module:' .. chunk.name)[key]
if asset.key == 'Text' then
-- do nothing
-- value = Encoding.decode2(value)
end
return value
end
end
end
setmetatable(asset.configList, meta)
end
-- Example:
--
-- local function foo(a, b, c)
-- return a + b
-- end
--
-- p.foo = cached(foo, 'ModuleName|foo', function(a, b, c) return { a, b } end)
--
-- argsKeyGenerator: function or nil.
-- When it is a function, it should return a string or an array.
-- When it is nil, the default generator concatenates all args with tostring().
-- revision: number, string, or nil.
-- Change the value will invalidate the cache.
--
-- TODO: Remember dependency and auto-invalidate accordingly?
Self.Cached = function(func, funcKey, argsKeyGenerator, revision)
if not argsKeyGenerator then
argsKeyGenerator = defaultArgsKeyGenerator
end
return function(...)
local args = {...}
local argsKey = argsKeyGenerator(unpack(args))
if type(argsKey) == 'table' then
argsKey = table.concat(argsKey, '|')
elseif type(argsKey) ~= 'string' then
error('VersionCache: function ' .. funcKey .. ' generated bad args key type: '
.. type(argsKey) .. ' ' .. tostring(argsKey))
end
local key = funcKey .. '|' .. argsKey
local data = cache.get(key)
if data ~= nil and data.r == revision then
return data.v
end
local value = func(unpack(args))
data = {
r = revision,
v = value,
}
cache.set(key, data, EXP_TIME)
return value
end
end
function defaultArgsKeyGenerator(...)
local n = select('#', ...)
if n == 0 then
return ''
end
local key = tostring(select(1, ...))
for i = 2, n do
key = key .. '|' .. tostring(select(i, ...))
end
return key
end
Self.debug = function()
local Text = Self.LoadAsset('Module:AssetItemChinese')
mw.log(Text[80008828])
mw.log(Text[1001])
if true then return end
function foo(a, b, c)
mw.log('a:', a, ' b:', b, 'c:', c)
return a + b
end
bar = Self.Cached(foo, 'foo', nil, 1)
mw.log(bar(1, 2, 3))
cache.delete('foo|1|2|3')
end
-- ----------------------------------------
-- Required for Modules to function
-- ----------------------------------------
return Self

沪公网安备 31011002002714 号