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 01:15, 4 September 2024 (Rename function to map). 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')

local function escPattern(s)
	return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end

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

function p.map(frame)
	local result = {}
	local parent = frame:getParent()
	
	-- Note: The difference between angle brackets and their entities is lost
	local code = mw.text.unstripNoWiki(frame.args[1]):gsub('&lt;', '<'):gsub('&gt;', '>')
	local sep = frame.args.sep or ''
	local conj = frame.args.conj or sep
	local start = tonumber(frame.args.start or 1)
	local expand = yesno(frame.args.expand or true)
	local prefixes = getPrefixes(frame.args)
	
	local iter
	local nums
	local first
	
	if yesno(frame.args.sparse or false) then
		local seenNums = {} 
	    nums = {}

	    for k, _ in pairs(parent.args) 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
	    
	    iter = sequenceIter
	    first = 0
	else
		-- 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
		
	    iter = prefixIter
	    nums = parent.args
	    first = start - 1
	end
	
	for _, num in iter, nums, first 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
		
		local processed = code
			:gsub("{{[iI]}}", num) -- Custom magic word {{I}}
			:gsub("{{{([^{}|]*)|?[^{}]*}}}", args) -- Substitute parameters
			
		if expand then
			table.insert(result, frame:preprocess(processed))
		else
			table.insert(result, processed)
		end
	end
	
	return mw.text.listToText(result, sep, conj)
end

return p