local module = {} local getArgs = require("Module:Arguments").getArgs local varArray = require("Module:var-array") local var = require("Module:var") local frame = mw.getCurrentFrame() local _count = { get = function(array) return var.get(array .. ".count") end } _count.plus = function(array) return tonumber(var.set(array .. ".count", _count.get(array) + 1)) end _count.minus = function(array) return tonumber(var.set(array .. ".count", _count.get(array) - 1)) end local prefix = "@array-innerArrayIdentifier:" function _ifArrayIndex(val) return (tostring(val or ''):find("^@array%-innerArrayIdentifier:.+")) end function _getArrayIndex(args, askValueIndex) local arrayIndex = prefix .. args[2] if arrayIndex ~= var.getPlain(arrayIndex) then error("变量组名无效", 0) end local argsCount = 0 if askValueIndex then for i, v in ipairs(args) do argsCount = i end end for i, v in ipairs(args) do if i > 2 then if askValueIndex and i == argsCount then arrayIndex = arrayIndex .. v else if (v == "count") then v = ".count" end arrayIndex = var.getPlain(arrayIndex .. v) end end end return arrayIndex end function _new(args, isOmit) local id = args["id"] or args["name"] if id == nil then error("构造变量组时“name”或“id”不能为空", 0) end local name = prefix .. id var.set(name, name) -- 用ipairs遍历args在遇到空匿名参数时会中断 local count = 0 for i, v in pairs(args) do if tostring(i):find("^%d+$") then i = tonumber(i) if isOmit then var.set(name .. i, v) if i > count then count = i end elseif i > 1 then i = i - 1 var.set(name .. i, v) if i > count then count = i end end end end var.set(name .. ".count", count) var.set("array.savedNameUseForArrayId", id) return id end function _id() local savedName = var.get("array.savedNameUseForArrayId") or math.random() local idCount = (var.get("array.idCount") or 0) + 1 var.set("array.idCount", idCount) return prefix .. savedName .. "___" .. idCount .. "___" end function _in(args) local name = _id() local count = 0 var.set(name, name) for i, v in pairs(args) do if tostring(i):find("^%d+$") then i = tonumber(i) if i > 1 then i = i - 1 var.set(name .. i, v) if i > count then count = i end end end end var.set(name .. ".count", count) return name end function _get(args) local result = _getArrayIndex(args) if _ifArrayIndex(result) then error("不能获取变量组的索引值", 0) end return result end function _set(args) local index = _getArrayIndex(args, true) if _ifArrayIndex(var.get(index)) then error("不能对变量组索引进行赋值", 0) end return var.set(index, args["val"]) end function _push(val, array, count) var.set(array .. (count + 1), val) return _count.plus(array) end function _pop(array, count) if count == 0 then return end _count.minus(array) return var.remove(array .. count) end function _unshift(val, array, count) for i = count, 1, -1 do local val = var.getPlain(array .. i) var.set(array .. (i + 1), val) end var.set(array .. "1", val) return _count.plus(array) end function _shift(array, count) if count == 0 then return end local deletedVal = var.getPlain(array .. 1) for i = 2, count do local val = var.getPlain(array .. i) var.set(array .. (i - 1), val) end var.set(array..count, '') _count.minus(array) return deletedVal end function _splice(array, count, startIndex, howmany, args) local vals = {} for i, v in pairs(args) do if tostring(i):find("^%d+$") then i = tonumber(i) if i > 1 then vals[#vals + 1] = v end end end if howmany == #vals then for i=1, howmany do var.set(array..(startIndex + i - 1), vals[i]) end return count else local fragment = {} for i=startIndex + howmany, count do fragment[#fragment + 1] = var.remove(array..i) end for i=1, #vals do var.set(array..(startIndex + i - 1), vals[i]) end -- 删除操作起始点和尾部保存起始点之间的成员 local d_start = startIndex + #vals local d_end = count - #fragment local d_count = d_end - d_start + 2 if d_count > #vals then for i=d_start, d_end do var.set(i, '') end end count = startIndex - 1 + #vals for i=1, #fragment do var.set(array..(count + i), fragment[i]) end return var.set(array..'.count', count + #fragment) end end function module.main(frame) local args = getArgs(frame) function ifReturn(val) if args["r"] == "true" then return val end return "" end function getArray() local array = _getArrayIndex(args) if array == "" then error("变量组成员下标(序号)定位有误", 0) end local count = _count.get(array) return array, count end local switch = { new = function() return ifReturn(_new(args)) end, ["in"] = function() return _in(args) end, get = function() return _get(args) end, set = function() return ifReturn(_set(args)) end, push = function() local array, count = getArray() return ifReturn(_push(args["val"], array, count)) end, pop = function() local array, count = getArray() return ifReturn(_pop(array, count)) end, unshift = function() local array, count = getArray() return ifReturn(_unshift(args["val"], array, count)) end, shift = function() local array, count = getArray() return ifReturn(_shift(array, count)) end, getIndex = function() return _getArrayIndex(args) end, ifIndex = function() if _ifArrayIndex(args[2]) then return 1 end end, splice = function() local array = args['index'] local count = var.get(array..'.count') local start = tonumber(args['start'] or 1) local howmany = tonumber(args['howmany'] or 1) if start > count then error('start参数(操作起点)不能大于变量组的长度', 0) end if _ifArrayIndex(array) then return ifReturn(_splice(array, count, start, howmany, args)) else error('变量组索引无效', 0) end end, print = function() local content = mw.dumpObject(varArray.get((getArray()):gsub("^@array%-innerArrayIdentifier:", ""))) return frame:extensionTag("pre", content) end } local hasTargetMethod = false for k, v in pairs(switch) do if k == args[1] then hasTargetMethod = true break end end if hasTargetMethod then return switch[args[1]]() else return ifReturn(_new(args, true)) end end return module