Module:Loops

--

-- Lua module implementing features similar to mw:Extension:Loops. -- -- @module lööps -- @alias loops -- @author User:ExE Boss -- @require Module:TableTools

local libraryUtil = require("libraryUtil"); local tableTools = require("Module:TableTools");

local checkType = libraryUtil.checkType; local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg;

local ustring = mw.ustring; local loops = {};

local function userError(message) return ' ' .. message .. ' '; end

local function escapePattern(pattern) return ustring.gsub(pattern, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1") end

local function isFrame(frame) return type(frame) == "table" and type(frame.args) == "table" and type(frame.getParent) == "function"; end

-- Preprocesses text escaped using the Extension:DynamicPageList3 method. -- -- @function loops._preprocess -- @param {Frame} frame -- @param {string} msg -- @return {string}

local function preprocess(frame, msg) msg = ustring.gsub(msg, "«", "<"); msg = ustring.gsub(msg, "»", ">"); msg = ustring.gsub(msg, "¦", "|"); msg = ustring.gsub(msg, "²{", "{{"); msg = ustring.gsub(msg, "}²", "}}"); return frame:preprocess(msg); end loops._preprocess = preprocess;

-- @param {Frame|table} args -- @return {number} -- @usage

function loops.numArgs(frame) checkType("numArgs", 1, frame, "table"); local args; if (isFrame(frame)) then args = (frame:getParent or frame).args; else args = frame; end return tableTools.length(args); end

-- @param {Frame} args -- @return {string} -- -- @usage -- @usage -- @usage -- @usage -- -- @usage -- -- @usage -- -- @usage --

function loops.forNumArgs(frame) local frameArgs, parentArgs; checkType("numArgs", 1, frame, "table"); if (isFrame(frame)) then frameArgs = frame.args; parentArgs = frame:getParent.args; else return error("forNumArgs only supports invocation"); end

local kPattern, vPattern, template; local frameNumArgs = tableTools.length(frameArgs); if (frameNumArgs >= 3) then kPattern = frameArgs[1]; vPattern = frameArgs[2]; template = frameArgs[3]; elseif (frameNumArgs >= 2) then vPattern = frameArgs[1]; template = frameArgs[2]; else template = frameArgs[1]; end

kPattern = frameArgs.key     or kPattern; vPattern = frameArgs.value   or vPattern; template = frameArgs.template or template;

checkTypeForNamedArg("forNumArgs", "key",     kPattern, "string", true); checkTypeForNamedArg("forNumArgs", "value",   vPattern, "string", true); checkTypeForNamedArg("forNumArgs", "template", template, "string", true);

if (template == nil) then return userError("Must supply template parameter to forNumArgs"); end

vPattern = vPattern or "$1"; if (kPattern ~= nil) then if (#kPattern > 0) then if (kPattern == vPattern) then return userError("key pattern must be different from value pattern"); end kPattern = escapePattern(kPattern); else kPattern = nil; end elseif (vPattern ~= "$2") then kPattern = "%$2"; end if (#vPattern == 0) then vPattern = nil; else vPattern = escapePattern(vPattern); end

local result = {}; local v, msg; for k = 1, tableTools.length(parentArgs) do		v = parentArgs[k]; if (v ~= nil) then msg = template; if (kPattern) then msg = ustring.gsub(msg, kPattern, (ustring.gsub(tostring(k), "%%", "%%%%"))); end if (vPattern) then msg = ustring.gsub(msg, vPattern, (ustring.gsub(tostring(v), "%%", "%%%%"))); end result[#result + 1] = preprocess(frame, msg); end end

return table.concat(result); end

return loops;