Jump to content

Module:Sandbox/BrandonXLF/Module:Map params

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by BrandonXLF (talk | contribs) at 04:20, 4 September 2024 (Undid revision 1243929835 by BrandonXLF (talk)). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local p = {}
local yesno = require('Module:Yesno')

-- Escape a string to add to a Lua pattern
local function escPattern(s)
	return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end

-- Get the prefixes to process
local function getPrefixes(args)
	local prefixes = {}
    local i = 1

    repeat
    	table.insert(prefixes, args['prefix' .. i] or '')
    	i = i + 1
    until not args['prefix' .. i]
    
    return prefixes
end

-- Perform wikitext parameter substitution
function substParams(code, num, args)
	local processed = code
		:gsub("{{[iI]}}", num) -- Custom magic word {{I}}
		:gsub("{{{([^{}|]*)|?[^{}]*}}}", args) -- Substitute parameters
		
	return processed
end

-- Return the function that processes each iteration
function makeProcessor(frame)
	local template = frame.args.call
	
	if template then
		return function(num, args)
			return frame:expandTemplate{
				title = template,
				args = args
			}
		end
	end
	
	-- Note: The difference between angle brackets and their entities is lost
	local code = mw.text.unstripNoWiki(frame.args[1]):gsub('&lt;', '<'):gsub('&gt;', '>')
	local expand = yesno(frame.args.expand or true)
	
	if expand then
		return function(num, args)
			return frame:preprocess(substParams(code, num, args))
		end
	end

	return function(num, args)
		return substParams(code, num, args)
	end
end

function numPairs(args, parentArgs, prefixes)
	local start = tonumber(args.start or 1)
	
	if yesno(args.sparse or false) then
		local nums = {}
		local seenNums = {} 

	    for k, _ in pairs(parentArgs) do
	    	local prefixMatch = false
	    	local j = 1

			-- Check every prefix for a match
	    	while prefixes[j] and not prefixMatch do
	    		local numStr = tostring(k):match('^' .. escPattern(prefixes[j]) .. '([1-9]%d*)$')

	    		if numStr then
	    			local num = tonumber(numStr)

	    			if num ~= nil and num >= start and not seenNums[num] then
	    				table.insert(nums, num)
	    				seenNums[num] = true
	    			end
	    		end
	    		
	    		if numStr ~= nil then
	    			prefixMatch = true
	    		end

	    		j = j + 1
	    	end
	    end
	
	    table.sort(nums)
	    
	    -- Iterate over each found number
	    function sequenceIter(a, i)
			i = i + 1
			
			local v = a[i]
			
			if v then
				return i, v
			end
	    end
	    
	    return sequenceIter, nums, 0
	end
	
	-- Iterate each number and check for any matches
	local function prefixIter(a, i)
		i = i + 1
		
    	local j = 1
    	local prefixMatch = false
    	
    	-- Check every prefix for a match
    	while prefixes[j] and not prefixMatch do
    		prefixMatch = a[prefixes[j] .. i]
    		j = j + 1
    	end
    	
    	if prefixMatch then
    		return i, i
    	end
	end
	
	return prefixIter, parentArgs, start - 1
end

function p.map(frame)
	local result = {}
	local parent = frame:getParent()
	
	local sep = frame.args.sep or ''
	local conj = frame.args.conj or sep
	local prefixes = getPrefixes(frame.args)
	local process = makeProcessor(frame)
	
	for _, num in numPairs(frame.args, parent.args, prefixes) do
		local args = {}
		
		-- Inherent arguments passed to the template
		for k, v in pairs(parent.args) do
			args[k] = v
		end
		
		-- Pass current parameters without their numeric suffix
		for _, prefix in ipairs(prefixes) do
			args[prefix ~= '' and prefix or '@'] = args[prefix ~= '' and prefix .. num or num]
		end
		
		table.insert(result, process(num, args))
	end
	
	return mw.text.listToText(result, sep, conj)
end

return p