Anonymous
×
Create a new article
Write your page title here:
We currently have 15 articles on TwistedFates Database. Type your article name above or click on one of the titles below and start writing!



    TwistedFates Database
    15Articles

    Documentation for this module may be created at Module:Loops/doc

    -- <nowiki>
    --------------------------------------------------------------------------------
    -- 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 '<strong class="error">' .. message .. '</strong>';
    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 [[mw: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 {{#invoke:Loops|numArgs}}
    --------------------------------------------------------------------------------
    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 {{#invoke:Loops|forNumArgs|template string}}
    -- @usage {{#invoke:Loops|forNumArgs|value pattern|template string}}
    -- @usage {{#invoke:Loops|forNumArgs|key pattern|value pattern|template string}}
    -- @usage
    --  {{#invoke:Loops|forNumArgs
    --  | template = template string
    --  }}
    -- @usage
    --  {{#invoke:Loops|forNumArgs
    --  | value    = value pattern
    --  | template = template string
    --  }}
    -- @usage
    --  {{#invoke:Loops|forNumArgs
    --  | key      = key pattern
    --  | template = template string
    --  }}
    -- @usage
    --  {{#invoke:Loops|forNumArgs
    --  | key      = key pattern
    --  | value    = value pattern
    --  | template = template string
    --  }}
    --------------------------------------------------------------------------------
    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
    
    --------------------------------------------------------------------------------
    -- Parses and prints wikitext markup N times
    --
    -- @param {Frame} args
    -- @param[opt] {string} args[1] Pattern. `$1` by default
    -- @param {number} args[2] Starting value
    -- @param {number} args[3] Number loops to be performed
    -- @param {string} args[4] Wikitext markup
    -- @return {string}
    --------------------------------------------------------------------------------
    function loops.loop(frame)
    	local frameArgs
    	checkType("numArgs", 1, frame, "table")
    	if (isFrame(frame)) then
    		frameArgs = (frame:getParent() or frame).args
    	else
    		return userError("loop only supports invocation")
    	end
    	
    	local pattern = frame.args[1] or "$1"
    	
    	local start = tonumber(frame.args[2])
    	local loopsPerformed = tonumber(frame.args[3])
    	-- {{#loop}} supports negative values for loopsPerformed
    	local fin = loopsPerformed < 0 and start + (loopsPerformed + 1) or (start - 1) + loopsPerformed
    	local step = loopsPerformed < 0 and -1 or 1
    	
    	local template = frame.args[4]
    	
    	local result = {}
    	local msg
    	for i = start, fin, step do
    		msg = ustring.gsub(template, pattern, i)
    		result[#result + 1] = msg
    	end
    	
    	return preprocess(frame, table.concat(result)) -- preprocess at the end
    end
    
    return loops;