Module:Switch by pattern

require('strict')
 
local p = {}

--will find either "human" or "homo" as part of the following _input, and return "orange"
--args = {_input="[[Homo sampiens|humans]]", ["pink"]="virus", ["green"]="plant", ["light gray"]="fung", ["orange"]="homo;human", _returnall="", _respectcase="", _sep=";"}
--aliases to search keys are separated by _sep, so _sep cannot be part of any key
--returns the first key found unless _returnall is nonempty, in which case it returns "all#keys#found" (for further processing?)
function p._found_in(args)
    local skip_args = "#_input#_respectcase#_returncaptures#_returnall#_sep#_outputsep#_default#" --each key must be surrounded by #'s'
    local res = {}

    local all = args["_returnall"] and args["_returnall"]~=""
    local returnkeys = not(args["_returncaptures"] and args["_returncaptures"]~="")
    local sep = args["_sep"]~="" and args["_sep"] or "#" --should not be blank
    local outputsep = args["_outputsep"] or "#" --can be blank
    local lowercase = not (args["_respectcase"] and args["_respectcase"]~="") --lowercase input (but not search keys, they can be regex patterns)
    local input = args["_input"] or ""
    if input == "" then return "" end
    
    if lowercase then input = mw.ustring.lower(input) end
    for k,v in pairs(args) do
    	if not mw.ustring.match(skip_args, "#"..k.."#" ) then
    		local aliases = mw.text.split(v, sep, true)
    		for _,a in ipairs(aliases) do
    			if a~="" then
    				local match = mw.ustring.match(input, a)
    				if match then
    					local key_or_capture = returnkeys and k  or  match
    					if not all then return key_or_capture end
    					table.insert(res, key_or_capture)
    					break --first found alias
    				end
    			end
    		end
    	end
    end
   
   if #res>0 then return table.concat(res, outputsep) end --returnall was not blank
   return args["_default"] or ""
end

function p.found_in(frame)
	local args = frame:getParent() and frame:getParent().args
	if not (args["_input"] and args["_input"]~="") then args = frame.args end
	if args["_input"] and args["_input"]~="" then return p._found_in(args) end
	return args["_default"] or ""
end

return p