%D \module
%D   [      file=s-inf-01,
%D        version=2009.07.09,
%D          title=\CONTEXT\ Style File,
%D       subtitle=Information 1 (\MKII/\MKIV\ usage),
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D Some day I will generalize this table mechanism.

\startluacode
    local format, gsub, find, match = string.format, string.gsub, string.find, string.match
    local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes

    local list, size, comp, used, nope = { }, { }, { }, { mkii = { }, mkiv = { } }, { 0, 0, 0, 0 }

    local omit = {
        "char%-def%.lua",
        "mult%-def%.lua", "mult%-..%.tex", "mult%-m..%.tex",
    }
    local skip = {
        "prag%-.*%.tex", "docs%-.*.tex", "list%-.*%.tex", "test%-.*%.tex", "demo%-.*%.tex",
        "opti%-.*%.tex", "chrt%-.*%.tex",
    }
    local types = {
        "tex", "mkii", "mkiv", "lua"
    }

    local function collect(list,suffix,n)
        local path = file.dirname(resolvers.find_file("context.tex"),".")
        local pattern = path .. "/*." .. suffix
        local texfiles = dir.glob(pattern)
        for _, name in ipairs(texfiles) do
            local base = file.basename(name)
            local category = match(base,"^([a-z][a-z][a-z][a-z])%-[a-z0-9]+%.[a-z]+")
            if category and lfs.isfile(name) then
                local okay = true
                for s=1,#skip do
                    if find(base,skip[s]) then
                        okay = false
                        break
                    end
                end
                if okay then
                    local lm, sm, cm = list[category], size[category], comp[category]
                    if not lm then
                        lm, sm, cm = { 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0 }
                        list[category], size[category], comp[category] = lm, sm, cm
                    end
                    lm[n] = lm[n] + 1
                    local done = true
                    for o=1,#omit do
                        if find(base,omit[o]) then
                            done = false
                            break
                        end
                    end
                    local data = io.loaddata(name)
                    if suffix == "lua" then
                        data = gsub(data,"%-%-%[%[.-%]%]%-%-","")
                        data = gsub(data,"%-%-.-[\n\r]","")
                    else
                        data = gsub(data,"%%.-[\n\r]","")
                    end
                    data = gsub(data,"%s","")
                    sm[n+4] = sm[n+4] + #data
                    if done then
                        sm[n] = sm[n] + #data
                    else
                        cm[n] = cm[n] + 1
                    end
                end
            end
        end
    end

    local function prepare(what)
        if next(list) then
            -- already loaded
        else
            for k, v in ipairs(types) do
                collect(list,v,k)
            end
            for category, _ in pairs(list) do
                pattern ="{"..category.."%-"
                for suffix, t in pairs(used) do
                    local data = io.loaddata(resolvers.find_file("context."..suffix))
                    if find(data,pattern) then
                        t[category] = true
                    end
                end
            end
        end
        local max, what = 0, (what == "size" and size) or list
        for k, v in table.sortedpairs(what) do
            for i=1,4 do if v[i] > max then max = v[i] end end
        end
        return max, what, function(n) return n/max end
    end

    function document.context_state_1(what)
        local max, what, norm = prepare(what)
        texsprint(ctxcatcodes,"\\starttabulate[|Tc|T|T|T|T|]")
        texsprint(ctxcatcodes,"\\NC category\\NC")
        for i, t in ipairs(types) do
            local n, m = 0, 0
            for k, v in pairs(list) do
                local nn, mm = what[k][i], what[k][i+4]
                n = n + nn
                m = m + (mm or nn)
            end
            texsprint(ctxcatcodes,format("\\Top{%s}{%s}{%s}{%s}\\NC",t,norm(max),n,m))
        end
        texsprint(ctxcatcodes,"\\NC\\NR\\HL")
        for k, v in table.sortedpairs(what) do
            local c = (what == size and comp[k]) or nope
            local cat = format("%s~%s~~%s",(used.mkii[k] and "ii") or "~~",(used.mkiv[k] and "iv") or "~~",k)
            texsprint(ctxcatcodes,"\\NC",cat,"\\NC")
            for i, t in ipairs(types) do
                texsprint(ctxcatcodes,format("\\Bar{%s}{%s}{%s}{%s}\\NC",t,v[i],c[i],norm(v[i])))
            end
            texsprint(ctxcatcodes,"\\NR")
        end
        texsprint(ctxcatcodes,"\\stoptabulate")
    end

    function document.context_state_2(what)
        local max, what, norm = prepare(what)
        for k, v in table.sortedpairs(what) do
            local c = (what == size and comp[k]) or nope
            texsprint(ctxcatcodes,format("\\StartUp{%s}",k))
            for i, t in ipairs(types) do
                texsprint(ctxcatcodes,format("\\Up{%s}{%s}",t,norm(v[i])))
            end
            texsprint(ctxcatcodes,"\\StopUp")
        end
    end

\stopluacode

\definecolor[bar:tex] [middlegreen]
\definecolor[bar:mkii][middleblue]
\definecolor[bar:mkiv][middlered]
\definecolor[bar:lua] [middlegray]

\def\Top#1#2#3#4%
  {\hbox to 5em{\hss#3}%
   \enspace
   \hbox to #2\dimexpr 20em\relax{#1\ifnum#3=#4\else~#4\rlap{~+}\fi\hss}}

\def\Bar#1#2#3#4%
  {\ifcase#2\else
     \hbox to 5em{\hss\ifcase#3\else\llap{-~}\fi#2}%
     \enspace
     \blackrule[color=bar:#1,width=#4\dimexpr 20em\relax,height=.8\strutht]%
   \fi}

\newcount\UpCounter

\def\StartUp#1%
  {\dontleavehmode\framed[frame=off,align={middle,low},height=18em]\bgroup
   \def\StopUp
     {\par\nointerlineskip\blackrule[height=1pt,width=4em,depth=0pt,color=darkgray]%
      \par\tttf\strut#1\par
      \egroup
      \ifnum\UpCounter=17 \par \UpCounter\zerocount\else \kern1em \advance\UpCounter\plusone \fi}}

\def\Up#1#2%
  {\scratchdimen#2\dimexpr 16em\relax
   \ifdim\scratchdimen=\zeropoint
     \kern1em
   \else
     \ifdim\scratchdimen<\onepoint \scratchdimen\onepoint \fi
     \blackrule[color=bar:#1,height=\scratchdimen,width=1em]%
   \fi}

\def\Show#1#2#3%
  {\startTEXpage[offset=1em,width=fit]
     \hbox{\tttf\strut\currentdate~-~#1}
     \ctxlua{document.context_state_\number#2("#3")}
   \stopTEXpage}

% \doifnotmode{demo}{\endinput}

\starttext
    \Show
        {The number of files used in ConTeXt (modules and styles are excluded).}
        {1}{number}
    \Show
        {The size of (core) files used in ConTeXt (- indicates exclusion of large data files; + indicates inclusion of large data files; comment and spaces removed.)}
        {1}{size}
    \Show
        {The relative number of files used in ConTeXt (tex, mkii, mkiv, lua).}
        {2}{number}
    \Show
        {The relative size of files used in ConTeXt (tex, mkii, mkiv, lua).}
        {2}{size}
\stoptext
