Modul:FormatTemplate

Seba na module şıma şenê yû pela dokumani vırazê Modul:FormatTemplate/dok

---- 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><span style="color:'..c..';">'..chars..'</span><nowiki>'
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,"</nowiki><br /><nowiki>"..mw.ustring.rep("&nbsp;",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 ---></nowiki><br />'''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,"<br />''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,"<br />''To continue this run, preview or enter <nowiki>{{#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>(.-)</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,"<nowiki>(.-)</nowiki>","<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>","<nowiki>"..nowikisafehouse[nw].."</now</nowiki>iki>",1)
    end
     -- preprocess as nowiki-bounded text
    return frame:preprocess("<nowiki>"..text.."</nowiki>")
end

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

return p