% \nopdfcompression

% \starttext
%   There is a loop somewhere ... todo.
% \stoptext

\enablemode[tablet] % whatever that means

\setupbodyfont[dejavu]

\doifelsemode {tablet} {

    \setuppapersize
      [S6,landscape]
      [S6,landscape]

    \definefont
      [TitlePageFont]
      [MonoBold at 14pt]

    \setupbodyfont
      [tt,8pt]

} {

    \definefont
      [TitlePageFont]
      [MonoBold at 17pt]

    \setupbodyfont
      [tt]

}

\setuplayout
  [header=0cm,
   footer=1cm,
   backspace=.5cm,
   topspace=.5cm,
   width=middle,
   height=middle]

\setuphead
  [title]
  [style=\ttc,
   interaction=reference]

\definehead
  [xtitle]
  [title]

\setuphead
  [xtitle]
  [color=darkgreen]

\setupfootertexts
  [\llap{\goto{\hbox to 5cm{\hss previous}}[previouspage]}%
   \quad\pagenumber\quad
   \rlap{\goto{\hbox to 5cm{next\hss}}[nextpage]}]

\ifcase\contextlmtxmode
    \setupinteraction
      [title={ConTeXt MkIV}]
\else
    \setupinteraction
      [title={ConTeXt LMTX}]
\fi

\setupinteraction
  [state=start,
   style=,
   color=,
   subtitle={Lua modules and functions},
   author={Hans Hagen - automatically generated},
   contrastcolor=]

\setupinteractionscreen
  [option=bookmark]

\placebookmarks
  [title,xtitle]
  [force=yes]

\definecolor[darkyellow][r=.5,g=.5,b=0]
\definecolor[darkgray]  [s=.15]

\nonknuthmode

\starttext

\startbuffer
\startluacode
local basiclua = libraries.basiclua
local basictex = libraries.basictex
local extratex = libraries.extratex
local extralua = libraries.extralua
local obsolete = libraries.obsolete

local find = string.find
local color, gotolocation = context.color, context["goto"]

for k, v in table.sortedpairs(_G) do
    if obsolete[k] or find(k,"_") or k == "arg" or k == "utf" then
        --
    elseif basiclua[k] then
        gotolocation(function() color( { "darkred" }, k) end, { k } )
    elseif extralua[k] then
        gotolocation(function() color( { "darkgreen" }, k) end, { k } )
    elseif basictex[k] then
        gotolocation(function() color( { "darkblue" }, k) end, { k } )
    elseif extratex[k] then
        gotolocation(function() color( { "darkyellow" }, k) end, { k } )
    elseif type(v) == "table" then
        gotolocation(function() color( { "white" }, k) end, { k } )
    end
    context(" ")
end
\stopluacode
\stopbuffer

\setupbackgrounds
  [page]
  [background=color,
   backgroundcolor=darkgray,
   backgroundoffset=2mm]

\startpagemakeup
    \vfill
    \pagereference[global]
    \startnarrower[10mm]
        \setupalign[nothyhenated,middle,broad]
        \TitlePageFont \setupinterlinespace
        \getbuffer % luabuffer
        \par
    \stopnarrower
    \vfill
    \vfill
    \hskip10mm\scale[width=\dimexpr\paperwidth-20mm\relax]{\ttbf\white\ConTeXt\ \ifcase\contextlmtxmode MkIV\else LMTX\fi}
    \par
  % \hskip10mm\scale[width=\dimexpr\paperwidth-20mm\relax]{\white \strut Lua infrastructure \emdash\ \currentdate}
    \vfill
\stoppagemakeup

\setupbackgrounds
  [page]
  [background=]

\startluacode
local builtin  = libraries.builtin
local globals  = libraries.globals
local basiclua = libraries.basiclua
local basictex = libraries.basictex
local extratex = libraries.extratex
local extralua = libraries.extralua
local obsolete = libraries.obsolete

local sortedkeys = table.sortedkeys
local mark       = storage.mark
local marked     = storage.marked
local gsub       = string.gsub
local sub        = string.sub
local byte       = string.byte
local upper      = string.upper

local skipglobal = table.tohash {
    "_G", "_M", "_ENV", "",
    "context", "modules", "global", "arg", "utf", 1,
    "kpse", "commands", "ffi",
}

local skipkeys = table.tohash {
 -- "_cldf_", "_cldn_", "_cldo_",
    "_clmb_", "_clme_", "_clmm_", "_clmn_", "_clma_", "_clmh_",
    "_G", "_M", "_ENV", "",
 -- "global",  "shortcuts",
    "_VERSION", "_COPYRIGHT", "_DESCRIPTION", "_NAME", "_PACKAGE", "__unload",
    "__index", "__newindex",
}

local sameglobal = {
 -- ["global"]   = "_G", -- global has become a keyword in 5.5
 -- ["commands"] = "cs", -- already gone
}

-- -- -- -- -- -- -- -- -- -- -- -- --
-- this should be done internally
-- -- -- -- -- -- -- -- -- -- -- -- --

for k,v in next, modules do
    mark(v)
end

mark(document.arguments)
mark(environment.arguments)
mark(environment.engineflags)
mark(characters.data)

-- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- -- --

local variant = 1 -- all parents
local variant = 2 -- parent name too
local variant = 3 -- no parents

local done = { }

local function childtables(key,tab,handler,depth)
    depth = depth or 1
    local keys = sortedkeys(tab) -- no sorted_pairs
    for i=1,#keys do
        local k = keys[i]
--      if k ~= "_G" and k ~= "_M" and type(k) == "string" then
        if not skipkeys[k] and type(k) == "string" then
            local v = tab[k]
            local t = type(v)
            local s = k
            if variant ~= 3 then
                s = key and (key .. "." .. s) or s
            end
            if t == "table" then
                if marked(v) then
                    t = "data"
                    handler(s,t,depth)
                elseif done[v] then
                    -- logs.report("inf-03","key %a in %a already done",k,v)
                else
                    done[v] = true
                    handler(s,t,depth)
                    if variant == 3 then
                        childtables(false,v,handler,depth+1)
                    elseif variant == 2 then
                        childtables(k,v,handler,depth+1)
                    else
                        childtables(s,v,handler,depth+1)
                    end
                end
            else
                handler(s,t,depth)
            end
        end
    end
end

local NC, NR = context.NC, context.NR
local overstrike, rlap, bf = context.overstrike, context.rlap, context.bf
local color, gotolocation = context.color, context["goto"]

local function cleanup(s)
    return "\\char" ..byte(s) .. " "
end

local function handler(k,t,depth)
    k = gsub(k,"([~#$%%^&{}\\|])",cleanup)
    NC() rlap("\\quad\\tx\\kern" .. (depth or 0).. "em" .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR()
end

local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mark,obsolete)
    -- todo: table as argument
 -- print(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mark,obsolete)
    local keys = sortedkeys(t) -- no sorted_pairs
    if #keys > 0 then
        local fulltitle = title
        if subtitle and subtitle ~= "" then
            fulltitle = fulltitle .. " (" .. subtitle .. ")"
        end
        if alias and alias ~= "" then
            fulltitle = fulltitle .. " (alias: " .. alias .. ")"
        end
        if builtin then
            context.startxtitle { reference = title, title = fulltitle, backreference = "global" }
        else
            context.starttitle  { reference = title, title = fulltitle, backreference = "global" }
        end
        context.startcolumns { n = 2 }
        context.starttabulate { "|||" }
        local t_obsolete = rawget(t,"obsolete") -- tricky a t.obsolete fails
        if type(t_obsolete) ~= "table" then
            t_obsolete = nil
        end
        for i=1,#keys do
            local k = keys[i]
            local v = t[k]
            if k and k ~= "obsolete" and not skipkeys[k] and (not obsolete or not obsolete[k]) then
                local inlib = lib and lib[k]
                local inglo = glo and glo[k]
                local t = type(v)
                local kstr, tstr = k, t
                local obs = t_obsolete and t_obsolete[k]
                if obs then
                    tstr = function() overstrike(t) end
                    kstr = function() overstrike(k) end
                end
                local marked = marked(v)
                if marked then
                    tstr = "data table"
                end
                if t == "table" then
                    local m = getmetatable(v)
                    if m and m.__call then
                        tstr = "function"
                    end
                end
                if not mark then
                    --
                elseif inlib and tostring(inlib) ~= tostring(v) then
                    tstr = "overloaded ".. tstr
                elseif inglo and tostring(inglo) ~= tostring(v) then
                    tstr = "overloaded ".. tstr
                end
                NC() bf()
                if inlib then
                    if not mark and t == "table" then
                        gotolocation(function() color( { libcolor }, kstr) end, { k } )
                    else
                        color( { libcolor }, kstr)
                    end
                elseif inglo then
                    if not mark and t == "table" then
                        gotolocation(function() color( { glocolor }, kstr) end, { k } )
                    else
                        color( { glocolor }, kstr)
                    end
                else
                    if not mark and t == "table" then
                        gotolocation(k, { kstr } )
                    else
                        context(kstr)
                    end
                end
                NC()
                if inlib then
                    color( { libcolor }, tstr)
                elseif inglo then
                    color( { glocolor }, tstr)
                else
                    context(tstr)
                end
                NC() NR()
                if mark and t == "table" and title ~= "libraries" and title ~= "package" and not marked then
                    childtables(false,v,handler) -- (k,v,handler)
                end
            end
        end
        context.stoptabulate()
        context.stopcolumns()
        if builtin then
            context.stopxtitle()
        else
            context.stoptitle()
        end
    end
end

show("global","",sameglobal["global"],false,_G,builtin,"darkgreen",globals,"darkblue",false,obsolete)

-- inspect(table.sortedkeys(context))

for k, v in table.sortedpairs(_G) do
    if not skipglobal[k] and not obsolete[k] and type(v) == "table" and not marked(v) then

 --     local mt = getmetatable(v)
 --     print("!!!!!!!!!!",k,v,mt,mt and mt.__index)

        if     basiclua[k] then show(k,"basic lua",sameglobal[k],basiclua[k],v,builtin[k],"darkred",   false,false,true)
        elseif extralua[k] then show(k,"extra lua",sameglobal[k],extralua[k],v,builtin[k],"darkred",   false,false,true)
        elseif basictex[k] then show(k,"basic tex",sameglobal[k],basictex[k],v,builtin[k],"darkred",   false,false,true)
        elseif extratex[k] then show(k,"extra tex",sameglobal[k],extratex[k],v,builtin[k],"darkred",   false,false,true)
        else
            show(k,"context",  sameglobal[k],false,      v,builtin[k],"darkyellow",false,false,true)
        end
    end
end

\stopluacode

\stoptext
