%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 ADE \& \CONTEXT\ Development Team}]
%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. This list is only
%D right when run in the minimals as my machine might have more files.
%D
%D Als, the remaining tex code can proably be lua also which is more
%D consistent.
%D
%D \starttyping
%D context auto:s-inf-01
%D context auto:s-inf-01 --basepath=t:/texmf/tex/context/base
%D \stoptyping

% \enabletrackers[context.*]

\startluacode
    local format, gsub, find, match = string.format, string.gsub, string.find, string.match

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

    local omit = {
        "char%-def%.lua",
        "mult%-def%.lua", "mult%-..%.mkii", "mult%-m..%.mkii",
    }
    local skip = {
        "prag%-.*%.tex", "docs%-.*.tex", "list%-.*%.tex", "test%-.*%.tex", "demo%-.*%.tex",
        "opti%-.*%.tex", "chrt%-.*%.tex", ".*%-old", ".*%-obs", ".*%-tst", "supp%-.*%.tex",
        "colo%-pan.tex", ".*test.*"
    }
    local types = {
        "tex", "mkii", "mkiv", "mkvi", "lua", -- "mpiv"
    }
    local patterns = {
        "^([a-z][a-z][a-z][a-z])%-[a-z0-9%-]+%.[a-z]+",
        "^([xms])%-[a-z0-9%-]+%.[a-z]+",
    }

    local function collect(list,suffix,n)
        local path = document.arguments.basepath or file.dirname(resolvers.find_file("context.mkiv"),".")
        local pattern = path .. "/*." .. suffix .. "$" -- avoid bla.tex~
        local texfiles = dir.glob(pattern)
        for i=1,#texfiles do
            local name = texfiles[i]
            local base = file.basename(name)
            for p=1,#patterns do
                local category = match(base,patterns[p])
                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, 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 data then
                            if suffix == "lua" then
                                data = gsub(data,"%-%-%[%[.-%]%]%-%-","")
                                data = gsub(data,"%-%-.-[\n\r]","")
                            else
                                data = gsub(data,"%%.-[\n\r]","")
                            end
                            data = gsub(data,"%s","")
                        else
                            logs.report("error","unknown file %a",name)
                            data = ""
                        end
                        sm[n+5] = sm[n+5] + #data
                        if done then
                            sm[n] = sm[n] + #data
                        else
                            cm[n] = cm[n] + 1
                        end
                    end
                end
            end
        end
    end

    local function prepare(what)
        if next(list) then
            -- already loaded
        else
            for i=1,#types do
                collect(list,types[i],i)
            end
            for category in next, list do
                pattern ="{"..category.."%-"
                for suffix, t in next, used do
                    local data = io.loaddata(resolvers.find_file("context."..suffix))
                    if data and 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,5 do if v[i] > max then max = v[i] end end
        end
        return max, what, function(n) return (max == 0 and 0) or (n == 0 and 0) or n/max end
    end

    local f_norm = string.formatters["%0.3f"]

    function document.context_state_1(what)
        local max, what, norm = prepare(what)
        context.starttabulate { "|Tl|T|T|T|T|T|" }
        context.NC()
        context(category)
        context.NC()
        for i=1,#types do
            local n, m = 0, 0
            for k, v in next, list do
                local nn, mm = what[k][i], what[k][i+5]
                n = n + nn
                m = m + (mm or nn)
            end
            context.Top(types[i],norm(max),n,m)
            context.NC()
        end
        context.NC()
        context.NR()
        context.HL()
        for k, v in table.sortedpairs(what) do
            local c = what == size and comp[k] or nope
            context.NC()
            context("\\bf %s~%s~~%s~~%s",
                (used.mkii[k] and "ii") or "~~",
                (used.mkiv[k] and "iv") or "~~",
                (used.mkvi[k] and "vi") or "~~",
                k
            )
         -- context("%s\\enspace %s\\quad %s\\quad %s",
         --     (used.mkii[k] and "ii") or "\\quad",
         --     (used.mkiv[k] and "iv") or "\\quad",
         --     (used.mkvi[k] and "vi") or "\\quad",
         --     k
         -- )
            context.NC()
            for i=1,#types do
                context.Bar(types[i],v[i],c[i],f_norm(norm(v[i])))
                context.NC()
            end
            context.NR()
        end
        context.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
            context.StartUp(k)
            for i=1,#types do
                context.Up(types[i],f_norm(norm(v[i])))
            end
            context.StopUp()
        end
    end

\stopluacode

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

\newcount\UpCounter

\starttexdefinition Top #what#fraction#total#bigones
    \hbox to 5em{\hss#total}%
    \enspace
    \hbox {{\bf#what}\ifnum#total=#bigones\else~#bigones\rlap{~+}\fi\hss}%
\stoptexdefinition

\starttexdefinition Bar #color#size#nobigones#fraction
    \ifcase#size\else
        \hbox to 5em{\hss\ifcase#nobigones\else\llap{-~}\fi#size}%
        \enspace
        \blackrule[color=bar:#color,width=#fraction\dimexpr 20em\relax,height=.8\strutht]%
    \fi
\stoptexdefinition

\starttexdefinition StartUp #name
    \def\UpName{#name}%
    \dontleavehmode\framed[frame=off,align={middle,low},height=18em]\bgroup
\stoptexdefinition

\starttexdefinition StopUp
    \par\nointerlineskip\blackrule[height=1pt,width=5em,depth=0pt,color=darkgray]
    \par\tttf\strut\UpName\par
    \egroup
    \ifnum\UpCounter=17
        \par \UpCounter\zerocount
    \else
        \kern1em \advance\UpCounter\plusone
    \fi
\stoptexdefinition

\starttexdefinition Up #color#width
%     \scratchdimen#width\dimexpr 16em\relax
    \scratchdimen#width\dimexpr 40em\relax
    \ifdim\scratchdimen=\zeropoint
        \kern1em
    \else\ifdim\scratchdimen>13em
        \blackrule[color=bar:#color,height=15em,width=1em]%
        \hskip-1.1em
        \blackrule[color=white,height=14em,width=1.2em]%
        \hskip-1.1em
        \blackrule[color=bar:#color,height=13em,width=1em]%
    \else
        \ifdim\scratchdimen<\onepoint \scratchdimen\onepoint \fi
        \blackrule[color=bar:#color,height=\scratchdimen,width=1em]%
    \fi\fi
\stoptexdefinition

\starttexdefinition Show #title#how#what
    \startTEXpage[offset=1em,width=fit]
        \hbox{\tttf\strut\currentdate~-~#title}
        \blank[line]
        \ctxlua{document.context_state_\number#how("#what")}
    \stopTEXpage
\stoptexdefinition

% \continueifinputfile{s-inf-01.mkvi}

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