Module:FormatTemplate

This module is intended to format templates to make them readable. It should work by recognizing every beginning that should not be intermingled: [[, {{, {{#, {{{ It will count how many levels deep you've gone. It will add 4 times that many spaces before each pipe | in a non-[[ element, removing any now present It will label the beginning and end with a color specific to the type of element even when it can't indent It will return everything in a nowiki wrapper (excluding the color formatting)

local p={}

function getContent(template) local title -- holds the result of the mw.title.xxx call if not(template) then title=mw.title.getCurrentTitle if not(title) then return "error: failed to getCurrentTitle" end local tdedoc=mw.ustring.match(title.fullText,"Template:(.-)/doc") if tdedoc then title=mw.title.new("Template:"..tdedoc) end -- SPECIAL CASE: Invoke in the template documentation processes the template instead else title=mw.title.new(page) if not (title) then return "error: failed to mw.title.new(" .. template .. ")" end end -- if not(template) return title.getContent(title) or "" end

local color={} color["{{"]="red" color["{{#"]="blue" color["{{{"]="orange" color["[["]="green"

function color.ize(model,chars) if not(chars) then return "" end local c=color[model] or "black" return ' '..chars..' ' end

function formatTemplate(text,stack,posn,template) -- note template is just for the error message local debug="" local char="" local output="" local outputtable={} local wrapper=true local holding="" local nowiki posn=tonumber(posn) or 0 if posn>0 then text=mw.ustring.sub(text,posn,-1) end --- need to chop off the preceding text so it doesn't gmatch to it   local getchar=mw.ustring.gmatch(text,".") local stopposn=posn+50000 stack=stack or {} local stackposn=#stack template=template or "" local spaces=0 repeat posn=posn+1 char=getchar if not char then break end if spaces>0 and char~=" " and char~="|" then table.insert(outputtable,mw.ustring.rep(" ",spaces)) spaces=0 end -- cases based on what holding value is presently if holding=="{{" then -- cases based on the next char after "{{" if char=="#" then stackposn=stackposn+1 stack[stackposn]="{{#" holding="" char="" table.insert(outputtable,color.ize("{{#","{{#")) elseif char=="{" then stackposn=stackposn+1 stack[stackposn]="{{{" holding="" char="" table.insert(outputtable,color.ize("{{{","{{{")) else stackposn=stackposn+1 stack[stackposn]="{{" holding="" table.insert(outputtable,color.ize("{{","{{")) end elseif holding=="[" then -- cases based on the next char after "[" if char=="[" then stackposn=stackposn+1 stack[stackposn]=""               holding=""                char=""                table.insert(outputtable,color.ize("[[","[["))            else table.insert(outputtable,holding)                holding=""                       end        elseif holding=="{" then             -- cases based on the next char after "{"            if char=="{" then                holding="{{"                char=""            end        elseif holding=="}}" then             -- cases based on the POP once "{{" is found (something has to pop...)            local pop=stack[stackposn]            stack[stackposn]=nil            stackposn=stackposn-1            if pop=="{{" or pop=="{{"))                if pop~="[[" then table.insert(outputtable,"<--- error?") end                char=""                holding=""            else table.insert(outputtable,holding)                holding=""            end        elseif holding=="}" then            if char=="}" then                holding="}}"                char=""            else table.insert(outputtable,holding)                holding=""            end        end         -- OK!  No more cases based on holding; these are body chars        if char==" " then            char=""            spaces=spaces+1        elseif char=="|" and stack[stackposn]~="{{{" and stack[stackposn]~="[[" then            if mw.ustring.sub(holding,1,1)==" " then holding="" end            table.insert(outputtable,holding)            holding=""            table.insert(outputtable," "..mw.ustring.rep(" ",4*stackposn).."|")        elseif holding=="" then            if char=="{" or char=="[" or char=="]" or char=="}" then                holding=char                char=""            else table.insert(outputtable,char)                char=""            end        end    until posn>stopposn    if stackposn>0 then        table.insert(outputtable,"<--- end of run ---> run incomplete.")        local stackcrypt=table.concat(stack,",")        stackcrypt=mw.ustring.gsub(stackcrypt,"{","<")        stackcrypt=mw.ustring.gsub(stackcrypt,"%[","(")        stackcrypt=mw.ustring.gsub(stackcrypt,"}",">")        stackcrypt=mw.ustring.gsub(stackcrypt,"%]",")")        if posn>50000 then            table.insert(outputtable," Note: due to restrictions on Lua time usage, runs are truncated at 50000 characters")            posn=posn+1-mw.ustring.len(holding)-spaces

table.insert(outputtable," ''To continue this run, preview or enter {{#invoke:FormatTemplate|format|page="..template.."|stack="..stackcrypt.."|position="..posn.."}}") else table.insert(outputtable," ''If you have an additional segment of template to process, preview or enter {{#invoke:FormatTemplate|format|page="..template.."|stack="..stackcrypt.."|position=0}}") end end output=table.concat(outputtable) return output end

function p.main(frame,fcn) local args=frame.args local parent=frame.getParent(frame) if parent then pargs=parent.args else pargs={} end page=args.page or pargs.page local text=getContent(page) local stackcrypt=args.stack or pargs.stack or "" stackcrypt=mw.ustring.gsub(stackcrypt,"<","{") stackcrypt=mw.ustring.gsub(stackcrypt,"%(","[")   stackcrypt=mw.ustring.gsub(stackcrypt,">","}")    stackcrypt=mw.ustring.gsub(stackcrypt,"%)","]") local stack={} local posn=args.position or pargs.position or 0 local prowl=mw.ustring.gmatch(stackcrypt,"[^,%s]+") repeat local x=prowl if x then table.insert(stack,x) end until not x   fcn=fcn or args["function"] or pargs["function"] or "" fcn=mw.ustring.match(fcn,"%S+") -- text=text or args.text or pargs.text or args[1] or pargs[1] or "" -- doesn't work - gets interpreted or passed as "UNIQ..QINU", either way unusuable! local nowikisafehouse={} local nowikielementnumber=0 local prowl=mw.ustring.gmatch(text," (.-) ") repeat local nowikimatch=prowl if not(nowikimatch) then break end nowikielementnumber=nowikielementnumber+1 table.insert(nowikisafehouse,nowikimatch) until false text=mw.ustring.gsub(text," (.-) ","") -- this is the meat of the formatting if fcn=="format" then text=formatTemplate(text,stack,posn,page) end -- unprotect the nowikis from the template itself - but inactivate them on first display! for nw = 1,nowikielementnumber do       text=mw.ustring.gsub(text,""," "..nowikisafehouse[nw].." ",1) end -- preprocess as nowiki-bounded text return frame:preprocess(" "..text.." ") end

function p.format(frame) return p.main(frame,"format") end

return p