Module:template utilities

local export = {}

export.brackets_temp = { ['' } export.brackets_temp_and_link = { ['', ['%[%['] = ']]' }

function export.find_bracket(str, brackets, p_start) local function find_left(pos_start) local p1_result, cap_result, right_result = str:len + 1 local cap_this for k, v in pairs(brackets) do			cap_this = {str:find(k, pos_start)} if cap_this[1] and cap_this[1] < p1_result then p1_result, cap_result, right_result = cap_this[1], cap_this, v			end end if not cap_result then return nil end local p2_result = cap_result[2] cap_result[2] = str:sub(p1_result, p2_result) local t = type(right_result) if t == 'string' then return p1_result, p2_result, right_result:gsub('%%(.)', function(m1)				if m1:match'%d' then					return cap_result[m1 + 2]				else return m1 end			end) end local repl if t == 'function' then cap_result[3] = cap_result[3] or cap_result[2] repl = right_result(select(3, unpack(cap_result))) elseif t == 'table' then repl = right_result[cap_result[3] or cap_result[2]] else error('bad right bracket type: ' .. t) end if not repl then repl = cap_result[2] elseif type(repl) == 'number' then repl = tostring(repl) end return p1_result, p2_result, repl end local p_init, p0, str_brac = find_left(p_start) if p_init == nil then return nil end local nest = {str_brac} local p1, p2, p3, p4	repeat p0 = p0 + 1 p1, p2 = str:find(str_brac, p0) if p1 == nil then return nil end if p1 > p2 then error'Any bracket must not have zero length.' end p3, p4, str_brac = find_left(p0) if p3 == nil then local n = #nest - 1 while n > 0 do				p1, p2 = str:find(nest[n], p2 + 1) if p1 == nil then return nil end n = n - 1 end p0 = p2			break else if p3 > p4 then error'Any bracket must not have zero length.' end if p3 < p1 then table.insert(nest, str_brac) p0 = p4			else table.remove(nest) str_brac = nest[#nest] p0 = p2			end end until #nest == 0 return p_init, p0, str:sub(p_init, p0) end

function export.gfind_bracket(str, brackets) local p0 = 0 return function p0 = p0 + 1 local p1, p2, text_b = export.find_bracket(str, brackets, p0) p0 = p2       return p1, p2, text_b end end

function export.find_ignoring_brackets(str, brackets, pat, init, ...) local find_result = {str:find(pat, init, ...)} local p1, p2 = find_result[1], find_result[2] if p1 == nil then return nil end local p3, p4 = export.find_bracket(str, brackets) while p4 and p4 <= p2 do p3, p4 = export.find_bracket(str, brackets, p4 + 1) end

while p3 and p3 <= p2 do       find_result = {str:find(pat, p4 + 1, ...)} p1, p2 = find_result[1], find_result[2] if p1 == nil then return nil end while p4 and p4 <= p2 do p3, p4 = export.find_bracket(str, brackets, p4 + 1) end end return unpack(find_result) end

function export.gsplit_ignoring_brackets(str, brackets, sep) local p0 = 0 local empty = 0 return function if p0 == nil then return nil end p0 = p0 + empty if p0 > str:len then return nil end p0 = p0 + 1 local p1, p2 = export.find_ignoring_brackets(str, brackets, sep, p0) p0, p2 = p2, p0 - empty if p1 then empty = p1 > p0 and 1 or 0 return str:sub(p2, p1 - 1) else return str:sub(p2) end end end

function export.parse_temp(str) if str:sub(1, 2) ~= '' then return nil end str = str:sub(3, -3) local p_title_end = export.find_ignoring_brackets(str, export.brackets_temp_and_link, '|') if not p_title_end then return { title = str, args = {} } end

local args = {} local count = 0 for arg in export.gsplit_ignoring_brackets(str:sub(p_title_end + 1), export.brackets_temp_and_link, '|') do       local p_eqsign = export.find_ignoring_brackets(arg, export.brackets_temp_and_link, '=') if p_eqsign then local arg_name = arg:sub(1, p_eqsign - 1) local arg_name_num = tonumber(arg_name) if arg_name_num and arg_name_num > 0 and arg_name_num == math.floor(arg_name_num) then arg_name = arg_name_num else arg_name = arg_name:match'^%s*(%S-)%s*$' end args[arg_name] = arg:sub(p_eqsign + 1):match'^%s*(%S-)%s*$' else count = count + 1 args[count] = arg end end

return { title = str:sub(1, p_title_end - 1), args = args } end

function export.iter_num(t) local i = 0 local index_max = 0 for k, _ in pairs(t.args) do		if type(k) == 'number' and index_max < k then index_max = k		end end return function local v		repeat i = i + 1 if i > index_max then return nil end v = t.args[i] until v		return i, v	end end

function export.glue_temp(t) local content = { t.title } for i, v in export.iter_num(t) do		if i == #content then table.insert(content, v)		else table.insert(content, i .. '=' .. v)		end end for k, v in pairs(t.args) do		if type(k) == 'string' then table.insert(content, k .. '=' .. v)		end end return '' end

return export