Module:FormatTemplate

From Sarkarverse
Jump to navigation Jump to search

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 '</nowiki>'..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=="{{#" then
                holding=""
                table.insert(outputtable,color.ize(pop,"}}"))
            elseif pop=="{{{" then
                if char=="}" then
                    char=""
                    holding=""
                    table.insert(outputtable,color.ize(pop,"}}}"))
                else table.insert(outputtable,color.ize(pop,"}}").."<--- error?")
                    holding=""
                end
            elseif pop=="[[" then
                table.insert(outputtable,color.ize(pop,"}}").."<--- error?")
                holding=""
            end
        elseif holding=="]" then
            if char=="]" then
                local pop=stack[stackposn]
                stack[stackposn]=nil
                stackposn=stackposn-1
                table.insert(outputtable,color.ize(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,"<br />''If you have an additional segment of template to process, preview or enter <nowiki>{{#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,"<nowiki>(.-)") repeat local nowikimatch=prowl() if not(nowikimatch) then break end nowikielementnumber=nowikielementnumber+1 table.insert(nowikisafehouse,nowikimatch) until false text=mw.ustring.gsub(text,"(.-)","<Module:FormatTemplate internal nowiki token>") -- 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,"<Module:FormatTemplate internal nowiki token>",""..nowikisafehouse[nw].."</nowiki>",1) end -- preprocess as nowiki-bounded text return frame:preprocess(""..text.."")

end

function p.format(frame)

   return p.main(frame,"format")

end

return p