• 您还可以去尝试使用本站的安卓客户端,在手机上方便的浏览H萌娘!
  • 模块:Var-array/main

    From H萌娘
    Jump to: navigation, search
    Template-info.svg 模块文档  [创建] [刷新]
    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