if not modules then modules = { } end modules ['mtx-server-ctx-help'] = { version = 1.001, comment = "Basic Definition Browser", author = "Hans Hagen", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- todo in lua interface: noargument, oneargument, twoarguments, threearguments -- todo: pickup translations from mult file dofile(resolvers.findfile("trac-lmx.lua","tex")) -- problem ... serialize parent stack local format, match, gsub, find = string.format, string.match, string.gsub, string.find local concat = table.concat local report = logs.reporter("ctx-help") -- -- -- make this a module: cont-xx.lua document = document or { } document.setups = document.setups or { } document.setups.div = { pe = "
%s
" } document.setups.span = { pe = "%s" } document.setups.translations = document.setups.translations or { nl = { ["title"] = "setup", ["formula"] = "formule", ["number"] = "getal", ["list"] = "lijst", ["dimension"] = "maat", ["mark"] = "markering", ["reference"] = "verwijzing", ["command"] = "commando", ["file"] = "file", ["name"] = "naam", ["identifier"] = "naam", ["text"] = "tekst", ["section"] = "sectie", ["singular"] = "naam enkelvoud", ["plural"] = "naam meervoud", ["matrix"] = "n*m", ["see"] = "zie", ["inherits"] = "erft van", ["optional"] = "optioneel", ["displaymath"] = "formule", ["index"] = "ingang", ["math"] = "formule", ["nothing"] = "leeg", ["file"] = "file", ["position"] = "positie", ["reference"] = "verwijzing", ["csname"] = "naam", ["destination"] = "bestemming", ["triplet"] = "triplet", ["word"] = "woord", ["content"] = "tekst", }, en = { ["title"] = "setup", ["formula"] = "formula", ["number"] = "number", ["list"] = "list", ["dimension"] = "dimension", ["mark"] = "mark", ["reference"] = "reference", ["command"] = "command", ["file"] = "file", ["name"] = "name", ["identifier"] = "identifier", ["text"] = "text", ["section"] = "section", ["singular"] = "singular name", ["plural"] = "plural name", ["matrix"] = "n*m", ["see"] = "see", ["inherits"] = "inherits from", ["optional"] = "optional", ["displaymath"] = "formula", ["index"] = "entry", ["math"] = "formula", ["nothing"] = "empty", ["file"] = "file", ["position"] = "position", ["reference"] = "reference", ["csname"] = "name", ["destination"] = "destination", ["triplet"] = "triplet", ["word"] = "word", ["content"] = "text", ["noargument"] = "\\cs", ["oneargument"] = "\\cs#1{..}", ["twoarguments"] = "\\cs#1#2{..}{..}", ["threearguments"] = "\\cs#1#2#3{..}{..}{..}", }, de = { ["title"] = "Setup", ["formula"] = "Formel", ["number"] = "Nummer", ["list"] = "Liste", ["dimension"] = "Dimension", ["mark"] = "Beschriftung", ["reference"] = "Referenz", ["command"] = "Befehl", ["file"] = "Datei", ["name"] = "Name", ["identifier"] = "Name", ["text"] = "Text", ["section"] = "Abschnitt", ["singular"] = "singular", ["plural"] = "plural", ["matrix"] = "n*m", ["see"] = "siehe", ["inherits"] = "inherits from", ["optional"] = "optioneel", ["displaymath"] = "formula", ["index"] = "entry", ["math"] = "formula", ["nothing"] = "empty", ["file"] = "file", ["position"] = "position", ["reference"] = "reference", ["csname"] = "name", ["destination"] = "destination", ["triplet"] = "triplet", ["word"] = "word", ["content"] = "text", }, cz = { ["title"] = "setup", ["formula"] = "rovnice", ["number"] = "cislo", ["list"] = "seznam", ["dimension"] = "dimenze", ["mark"] = "znacka", ["reference"] = "reference", ["command"] = "prikaz", ["file"] = "soubor", ["name"] = "jmeno", ["identifier"] = "jmeno", ["text"] = "text", ["section"] = "sekce", ["singular"] = "jmeno v singularu", ["plural"] = "jmeno v pluralu", ["matrix"] = "n*m", ["see"] = "viz", ["inherits"] = "inherits from", ["optional"] = "optioneel", ["displaymath"] = "formula", ["index"] = "entry", ["math"] = "formula", ["nothing"] = "empty", ["file"] = "file", ["position"] = "position", ["reference"] = "reference", ["csname"] = "name", ["destination"] = "destination", ["triplet"] = "triplet", ["word"] = "word", ["content"] = "text", }, it = { ["title"] = "setup", ["formula"] = "formula", ["number"] = "number", ["list"] = "list", ["dimension"] = "dimension", ["mark"] = "mark", ["reference"] = "reference", ["command"] = "command", ["file"] = "file", ["name"] = "name", ["identifier"] = "name", ["text"] = "text", ["section"] = "section", ["singular"] = "singular name", ["plural"] = "plural name", ["matrix"] = "n*m", ["see"] = "see", ["inherits"] = "inherits from", ["optional"] = "optioneel", ["displaymath"] = "formula", ["index"] = "entry", ["math"] = "formula", ["nothing"] = "empty", ["file"] = "file", ["position"] = "position", ["reference"] = "reference", ["csname"] = "name", ["destination"] = "destination", ["triplet"] = "triplet", ["word"] = "word", ["content"] = "text", }, ro = { ["title"] = "setari", ["formula"] = "formula", ["number"] = "numar", ["list"] = "lista", ["dimension"] = "dimensiune", ["mark"] = "marcaj", ["reference"] = "referinta", ["command"] = "comanda", ["file"] = "fisier", ["name"] = "nume", ["identifier"] = "nume", ["text"] = "text", ["section"] = "sectiune", ["singular"] = "nume singular", ["plural"] = "nume pluram", ["matrix"] = "n*m", ["see"] = "vezi", ["inherits"] = "inherits from", ["optional"] = "optioneel", ["displaymath"] = "formula", ["index"] = "entry", ["math"] = "formula", ["nothing"] = "empty", ["file"] = "file", ["position"] = "position", ["reference"] = "reference", ["csname"] = "name", ["destination"] = "destination", ["triplet"] = "triplet", ["word"] = "word", ["content"] = "text", }, fr = { ["title"] = "réglage", ["formula"] = "formule", ["number"] = "numéro", ["list"] = "liste", ["dimension"] = "dimension", ["mark"] = "marquage", ["reference"] = "reference", ["command"] = "commande", ["file"] = "fichier", ["name"] = "nom", ["identifier"] = "identificateur", ["text"] = "texte", ["section"] = "section", ["singular"] = "nom singulier", ["plural"] = "nom pluriel", ["matrix"] = "n*m", ["see"] = "vois", ["inherits"] = "herite de", ["optional"] = "optionel", ["displaymath"] = "formule", ["index"] = "entrée", ["math"] = "formule", ["nothing"] = "vide", ["file"] = "fichier", ["position"] = "position", ["reference"] = "réference", ["csname"] = "nom", ["destination"] = "destination", ["triplet"] = "triplet", ["word"] = "mot", ["content"] = "texte", } } document.setups.formats = { open_command = { tex = [[\%s]], lua = [[context.%s (]], }, close_command = { tex = [[]], lua = [[ )]], }, connector = { tex = [[]], lua = [[, ]], }, href_in_list = { tex = [[%s]], lua = [[%s]], }, href_as_command = { tex = [[\%s]], lua = [[context.%s]], }, modes = { tex = [[lua mode]], lua = [[tex mode]], }, optional_single = { tex = "[optional string %s]", lua = "{optional string %s}", }, optional_list = { tex = "[optional list %s]", lua = "{optional table %s}" , } , mandate_single = { tex = "[mandate string %s]", lua = "{mandate string %s}", }, mandate_list = { tex = "[mandate list %s]", lua = "{mandate list %s}", }, interface = [[%s]], source = [[%s]], parameter = [[%s%s%s]], parameters = [[%s
]], listing = [[
%s]],
    special         = [[%s]],
    default         = [[%s]],
}

local function translate(tag,int,noformat)
    local t = document.setups.translations
    local te = t["en"]
    local ti = t[int] or te
    if noformat then
        return ti[tag] or te[tag] or tag
    else
        return format(document.setups.formats.special,ti[tag] or te[tag] or tag)
    end
end

local function translated(e,int)
    local attributes = e.at
    local s = attributes.type or "?"
    local tag = match(s,"^cd:(.*)$")
    if attributes.default == "yes" then
        return format(document.setups.formats.default,tag or "?")
    elseif tag then
        return translate(tag,int)
    else
        return s
    end
end

document.setups.loaded = document.setups.loaded or { }

document.setups.current = { }
document.setups.showsources = true
document.setups.mode = "tex"

function document.setups.load(filename)
    filename = resolvers.findfile(filename) or ""
    if filename ~= "" then
        local current = document.setups.loaded[filename]
        if not current then
            local loaded = xml.load(filename)
            if loaded then
                -- xml.inject(document.setups.root,"/",loaded)
                current = {
                    file = filename,
                    root = loaded,
                    names = { },
                    used = { },
                }
                document.setups.loaded[filename] = current
            end
        end
        document.setups.current = current or { }
    end
end

function document.setups.name(ek)
    local at = ek.at
    local name = at.name
    if at.type == 'environment' then
        name = "start" .. name
    end
    if at.variant then
        name = name .. ":" .. at.variant
    end
    if at.generated == "yes" then
        name = name .. "*"
    end
    return name:lower()
end

function document.setups.csname(ek,int)
    local cs = ""
    local at = ek.at or { }
    if at.type == 'environment' then
        cs = translate("start",int,true) .. cs
    end
    for e in xml.collected(ek,'cd:sequence/(cd:string|variable)') do
        if e.tg == "string" then
            cs = cs .. e.at.value
        else
            cs = cs .. e.at.value -- to be translated
        end
    end
    return cs
end

function document.setups.names()
    local current = document.setups.current
    local names = current.names
    if not names or #names == 0 then
        names = { }
        local name = document.setups.name
        local csname = document.setups.csname
        for e in xml.collected(current.root,'cd:command') do
            names[#names+1] = { e.at.name, csname(e,int) }
        end
        table.sort(names, function(a,b) return a[2]:lower() < b[2]:lower() end)
        current.names = names
    end
    return names
end

function document.setups.show(name)
    local current = document.setups.current
    if current.root then
        local name = gsub(name,"[<>]","")
        local setup = xml.first(current.root,"cd:command[@name='" .. name .. "']")
        current.used[#current.used+1] = setup
        xml.sprint(setup)
    end
end

function document.setups.showused()
    local current = document.setups.current
    if current.root and next(current.used) then
        local sorted = table.sortedkeys(current.used)
        for i=1,#sorted do
            xml.sprint(current.used[sorted[i]])
        end
    end
end
function document.setups.showall()
    local current = document.setups.current
    if current.root then
        local list = { }
        for e in xml.collected(current.root,"cd:command") do
            list[document.setups.name(e)] = e
        end
        local sorted = table.sortedkeys(list)
        for i=1,#sorted do
            xml.sprint(list[sorted[i]])
        end
    end
end
function document.setups.resolve(name)
    local current = document.setups.current
    if current.root then
        local e = xml.filter(current.root,format("cd:define[@name='%s']/text()",name))
        if e then
            xml.sprint(e)
        end
    end
end

function document.setups.collect(name,int,lastmode)
    local current = document.setups.current
    local formats = document.setups.formats
    local command = xml.filter(current.root,format("cd:command[@name='%s']/first()",name))
    if command then
        local attributes = command.at or { }
        local data = {
            command = command,
            category = attributes.category or "",
        }
        if document.setups.showsources then
            data.source = (attributes.file and format(formats.source,attributes.file,lastmode,attributes.file)) or ""
        else
            data.source = attributes.file or ""
        end
        local n, sequence, tags = 0, { }, { }
        sequence[#sequence+1] = format(formats.open_command[lastmode],document.setups.csname(command,int))
        local arguments, tag = { }, ""
        for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do
            n = n + 1
            local attributes = d[k].at
            if #sequence > 1 then
                local c = formats.connector[lastmode]
                if c ~= "" then
                    sequence[#sequence+1] = c
                end
            end
            if attributes.optional == 'yes' then
                if attributes.list == 'yes' then
                    tag = format(formats.optional_list[lastmode],n)
                else
                    tag = format(formats.optional_single[lastmode],n)
                end
            else
                if attributes.list == 'yes' then
                    tag = format(formats.mandate_list[lastmode],n)
                else
                    tag = format(formats.mandate_single[lastmode],n)
                end
            end
            sequence[#sequence+1] = tag
            tags[#tags+1] = tag
        end
        sequence[#sequence+1] = formats.close_command[lastmode]
        data.sequence = concat(sequence, " ")
        local parameters, n = { }, 0
        for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do
            n = n + 1
            if d[k].tg == "keywords" then
                local left = tags[n]
                local right = { }
                for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do
                    local tag = d[k].tg
                    if tag == "resolve" then
                        local name = d[k].at.name or ""
                        if name ~= "" then
                            local resolved = xml.filter(current.root,format("cd:define[@name='%s']",name))
                            for r, d, k in xml.elements(resolved,"cd:constant") do
                                right[#right+1] = translated(d[k],int)
                            end
                        end
                    else
                        right[#right+1] = translated(d[k],int)
                    end
                end
                parameters[#parameters+1] = format(formats.parameter,left,"",concat(right, ", "))
            else
                local what = tags[n]
                for r, d, k in xml.elements(d[k],"(cd:parameter|cd:inherit)") do
                    local tag = d[k].tg
                    local left, right = d[k].at.name or "?", { }
                    if tag == "inherit" then
                        local name = d[k].at.name or "?"
                        local url  = format(document.setups.formats.href_as_command[lastmode],name,lastmode,name)
                        if #parameters > 0 and not find(parameters[#parameters],"
") then parameters[#parameters+1] = format(formats.parameter,"
","","") end parameters[#parameters+1] = format(formats.parameter,what,format(formats.special,translate("inherits",int)),url) else for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do local tag = d[k].tg if tag == "resolve" then local name = d[k].at.name or "" if name ~= "" then local resolved = xml.filter(current.root,format("cd:define[@name='%s']",name)) for r, d, k in xml.elements(resolved,"cd:constant") do right[#right+1] = translated(d[k],int) end end else right[#right+1] = translated(d[k],int) end end parameters[#parameters+1] = format(formats.parameter,what,left,concat(right, ", ")) end what = "" end end parameters[#parameters+1] = format(formats.parameter,"
","","") end data.parameters = parameters or { } data.mode = formats.modes[lastmode or "tex"] return data else return nil end end -- -- -- tex = tex or { } -- -- -- local interfaces = { czech = 'cz', dutch = 'nl', english = 'en', french = 'fr', german = 'de', italian = 'it', persian = 'pe', romanian = 'ro', } local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", "tex" local variables = { ['color-background-main-left'] = '#3F3F3F', ['color-background-main-right'] = '#5F5F5F', ['color-background-one'] = lmx.get('color-background-green'), ['color-background-two'] = lmx.get('color-background-blue'), ['title'] = 'ConTeXt Help Information', } --~ function lmx.loadedfile(filename) --~ return io.loaddata(resolvers.findfile(filename)) -- return resolvers.texdatablob(filename) --~ end local function doit(configuration,filename,hashed) local formats = document.setups.formats local start = os.clock() local detail = hashed.queries or { } if detail then lastinterface = detail.interface or lastinterface lastcommand = detail.command or lastcommand lastsource = detail.source or lastsource lastmode = detail.mode or lastmode or "tex" lastcommand = gsub(lastcommand,"%s*^\\*(.+)%s*","%1") if lastinterface then report("checking interface: %s",lastinterface) document.setups.load(format("cont-%s.xml",lastinterface)) end local div = document.setups.div [lastinterface] local span = document.setups.span[lastinterface] local names, refs, ints = document.setups.names(lastinterface), { }, { } for k=1,#names do local v = names[k] refs[k] = format(formats.href_in_list[lastmode],v[1],lastmode,v[2]) end if lastmode ~= "lua" then local sorted = table.sortedkeys(interfaces) for k=1,#sorted do local v = sorted[k] ints[k] = format(formats.interface,interfaces[v],lastmode,v) end end local n = concat(refs,"
") local i = concat(ints,"

") if div then variables.names = format(div,n) variables.interfaces = format(div,i) else variables.names = n variables.interfaces = i end -- first we need to add information about mkii/mkiv variables.maintitle = "no definition" variables.maintext = "" variables.extra = "" if document.setups.showsources and lastsource and lastsource ~= "" then -- todo: mkii, mkiv, tex (can be different) local name = lastsource local full = resolvers.findfile(name) if full == "" and file.suffix(lastsource) == "tex" then name = file.replacesuffix(lastsource,"mkiv") full = resolvers.findfile(name) if full == "" then name = file.replacesuffix(lastsource,"mkvi") full = resolvers.findfile(name) end end if full == "" then variables.maintitle = lastsource variables.maintext = format(formats.listing,"no source found") else variables.maintitle = name variables.maintext = format(formats.listing,io.loaddata(full)) end lastsource = "" elseif lastcommand and lastcommand ~= "" then local data = document.setups.collect(lastcommand,lastinterface,lastmode) if data then local what, extra = { "environment", "category", "source", "mode" }, { } for k=1,#what do local v = what[k] if data[v] and data[v] ~= "" then lmx.set(v, data[v]) extra[#extra+1] = v .. ": " .. data[v] end end variables.maintitle = data.sequence variables.maintext = format(formats.parameters,concat(data.parameters)) variables.extra = concat(extra,"   ") else variables.maintext = "select command" end end else variables.maintitle = "no definition" variables.maintext = "some error" variables.extra = "" end local content = lmx.convert('context-help.lmx',false,variables) report("time spent on page: %0.03f seconds",os.clock()-start) return { content = content } end return doit, true