diff options
Diffstat (limited to 'tex/context/base/mkxl/strc-syn.lmt')
| -rw-r--r-- | tex/context/base/mkxl/strc-syn.lmt | 420 | 
1 files changed, 420 insertions, 0 deletions
| diff --git a/tex/context/base/mkxl/strc-syn.lmt b/tex/context/base/mkxl/strc-syn.lmt new file mode 100644 index 000000000..940b982a7 --- /dev/null +++ b/tex/context/base/mkxl/strc-syn.lmt @@ -0,0 +1,420 @@ +if not modules then modules = { } end modules ['strc-syn'] = { +    version   = 1.001, +    comment   = "companion to str-syn.mkiv", +    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", +    copyright = "PRAGMA ADE / ConTeXt Development Team", +    license   = "see context related readme files" +} + +local next, type = next, type +local sortedkeys = table.sortedkeys + +local context      = context +local implement    = interfaces.implement + +local allocate     = utilities.storage.allocate + +local sorters      = sorters + +local structures   = structures +local synonyms     = structures.synonyms +local tags         = structures.tags + +local collected    = allocate() +local tobesaved    = allocate() + +local firstofsplit = sorters.firstofsplit +local strip        = sorters.strip +local splitter     = sorters.splitters.utf + +synonyms.collected = collected +synonyms.tobesaved = tobesaved + +local progressions = { } -- false=not_yet_shown  true=shown + +local variables    = interfaces.variables +local v_all        = variables.all +local v_current    = variables.current + +local function initializer() +    collected = synonyms.collected +    tobesaved = synonyms.tobesaved +end + +local function finalizer() +    for entry, data in next, tobesaved do +        data.hash = nil +     -- being sparse can be an option but often we actually do want the +     -- whole list so we don't do this ... only as possible option +     -- +-- maybe pages = sortedkeys(pages) is more efficient +     -- +     -- local entries = data.entries +     -- local t = { } +     -- local n = 0 +     -- for i=1,#entries do +     --     local e = entries[i] +     --     if e.definition.shown then +     --         n = n + 1 +     --         t[n] = e +     --     end +     -- end +     -- data.entries = t +    end +end + +job.register('structures.synonyms.collected', tobesaved, initializer, finalizer) + +-- todo: allocate becomes metatable + +table.setmetatableindex(tobesaved,function(t,k) +    local v = { +        metadata = { +            language = 'en', +            sorted   = false, +            class    = v +        }, +        entries  = { +        }, +        hash = { +        } +    } +    t[k] = v +    return v +end) + +function synonyms.define(class,kind) +    local data = tobesaved[class] +    data.metadata.kind = kind +end + +function synonyms.register(class,kind,spec) +    local data       = tobesaved[class] +    local hash       = data.hash +    local definition = spec.definition +    local tag        = definition.tag or "" +    data.metadata.kind = kind -- runtime, not saved in format (yet) +    if not hash[tag] then +        local entries = data.entries +        entries[#entries+1] = spec +        hash[tag] = spec +    end +end + +function synonyms.registerused(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    if okay then +        local definition = okay.definition +        definition.used = true +        definition.list = true +    end +end + +function synonyms.registershown(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    if okay then +        local definition = okay.definition +        definition.shown = true +        definition.list  = true +    end +end + +function synonyms.isused(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    return okay and okay.definition.used or false +end + +function synonyms.isshown(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    return okay and okay.definition.shown or false +end + +local function resetused(class) +    for tag, data in next, tobesaved[class].hash do +        data.definition.used = nil +    end +end + +local function resetshown(class) +    for tag, data in next, tobesaved[class].hash do +        data.definition.shown = nil +    end +end + +local function resetlist(class) +    for tag, data in next, tobesaved[class].hash do +        data.definition.list = nil +    end +end + +local function resetall(class) +    for tag, data in next, tobesaved[class].hash do +        local definition = data.definition +        definition.used  = nil +        definition.shown = nil +        definition.list  = nil +    end +end + +synonyms.resetused  = resetused +synonyms.resetshown = resetshown +synonyms.resetlist  = resetlist +synonyms.resetall   = resetall + +function synonyms.reset(class,what) +    if what == "progress" then +        progressions = { } +    elseif what == "used" then +        resetused(class) +    elseif what == "shown" then +        resetshown(class) +    elseif what == "list" then +        resetlist(class) +    else +        resetall(class) +    end +end + +function synonyms.synonym(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    if okay then +        local definition = okay.definition +        definition.used = true +        definition.list = true +        context(definition.synonym) +    end +    if progressions[tag] == nil then +        progressions[tag] = false -- not yet shown +    end +end + +function synonyms.meaning(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    if okay then +        local definition = okay.definition +        definition.shown = true +        definition.list  = true +        context(definition.meaning) +    end +end + +function synonyms.pages(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    if okay then +        local definition = okay.definition +        local pages = definition.pages +        if pages and next(pages) then +            context("%,t",sortedkeys(pages)) +        end +    end +end + +local ctx_latelua = context.latelua + +local function enhance(data) +    local page = tex.getcount("realpageno") +    data.pages[page] = true +end + +function synonyms.enhance(class,tag) +    local data = tobesaved[class] +    local okay = data.hash[tag] +    if okay then +        local definition = okay.definition +        local pages      = definition.pages +        if not pages then +            pages            = { } +            definition.pages = pages +        end +        ctx_latelua { action = enhance, pages = pages } +    end +end + +synonyms.compare = sorters.comparers.basic -- (a,b) + +function synonyms.filter(data,options) +    local result    = { } +    local entries   = data.entries +    local criterium = options and options.criterium +    if criterium == v_all then +        for i=1,#entries do +            result[i] = entries[i] +        end +    else +        for i=1,#entries do +            local entry      = entries[i] +            local definition = entry.definition +            if definition.list then +                local tag  = definition.tag +                local done = progressions[tag] +                if done == false then +                    result[#result+1] = entry +                    progressions[tag] = true +                end +            end +        end +        if criterium == v_current then +            progressions = { } +        end +    end +    data.result = result +end + +function synonyms.prepare(data) +    local result = data.result +    if result then +        for i=1, #result do +            local entry      = result[i] +            local definition = entry.definition +            if definition then +                local srt = definition.sortkey or "" +                local tag = definition.tag or "" +                local key = (srt ~= "" and srt) or (tag ~= "" and tag) or definition.synonym +                if key then +                    entry.split = splitter(strip(key)) +                end +            end +        end +    end +end + +function synonyms.sort(data,options) +    sorters.sort(data.result,synonyms.compare) +    data.metadata.sorted = true +end + +function synonyms.finalize(data,options) -- mostly the same as registers so we will generalize it: sorters.split +    local result   = data.result +    local split    = { } +    local nofsplit = 0 +    local lasttag  = nil +    local lasttag  = nil +    local nofdone  = 0 +    for k=1,#result do +        local entry = result[k] +        local first, tag = firstofsplit(entry) +        if tag ~= lasttag then +         -- if trace_registers then +         --     report_registers("splitting at %a",tag) +         -- end +            done     = { } +            nofdone  = 0 +            nofsplit = nofsplit + 1 +            lasttag  = tag +            split[nofsplit] = { tag = tag, data = done } +        end +        nofdone = nofdone + 1 +        done[nofdone] = entry +    end +    data.result = split +end + +-- for now, maybe at some point we will do a multipass or so +-- maybe pass the settings differently + +local ctx_synonymentry = context.synonymentry + +function synonyms.flush(data,options) +    local result = data.result +    for i=1,#result do +        local sublist = result[i] +        local data    = sublist.data +        for d=1,#data do +            local entry = data[d].definition +            ctx_synonymentry(d,entry.tag,entry.synonym,entry.meaning or "") +        end +    end +    data.result          = nil +    data.metadata.sorted = false +end + +function synonyms.analyzed(class,options) +    local data = collected[class] +    if data and data.entries then +        options = options or { } +        sorters.setlanguage(options.language,options.method) +        synonyms.filter(data,options)   -- filters entries to result +        synonyms.prepare(data,options)  -- adds split table parallel to list table +        synonyms.sort(data,options)     -- sorts entries in result +        synonyms.finalize(data,options) -- do things with data.entries +        data.metadata.sorted = true +    end +    return data and data.metadata.sorted and data.result and next(data.result) +end + +function synonyms.process(class,options) +    if synonyms.analyzed(class,options) then +        synonyms.flush(collected[class],options) +    end +end + +-- todo: local higher up + +implement { name = "registerusedsynonym",  actions = synonyms.registerused,  arguments = "2 strings" } +implement { name = "registershownsynonym", actions = synonyms.registershown, arguments = "2 strings" } +implement { name = "synonymmeaning",       actions = synonyms.meaning,       arguments = "2 arguments" } +implement { name = "synonymname",          actions = synonyms.synonym,       arguments = "2 arguments" } +implement { name = "synonympages",         actions = synonyms.pages,         arguments = "2 arguments" } +implement { name = "enhancesynonym",       actions = synonyms.enhance,       arguments = "2 arguments" } +--        { name = "resetusedsynonyms",    actions = resetused,              arguments = "string" } +--        { name = "resetshownsynonyms",   actions = resetshown,             arguments = "string" } +--        { name = "resetlistsynonyms",    actions = resetlist,              arguments = "string" } +implement { name = "resetsynonyms",        actions = synonyms.reset,         arguments = "2 strings" } + +implement { +    name      = "doifelsesynonymused", +    actions   = { synonyms.isused, commands.doifelse }, +    arguments = "2 arguments", +} + +implement { +    name      = "doifelsesynonymshown", +    actions   = { synonyms.isshown, commands.doifelse }, +    arguments = "2 arguments", +} + +implement { +    name      = "registersynonym", +    actions   = synonyms.register, +    arguments = { +        "string", +        "string", +        { +            { "metadata", { +                    { "catcodes", "integer" }, +                    { "coding" }, +                    { "xmlroot" } +                } +            }, +            { +                "definition", { +                    { "tag" }, +                    { "synonym" }, +                    { "meaning" }, +                    { "sortkey" }, +                    { "used", "boolean" } +                } +            } +        } +    } +} + +implement { +    name      = "processsynonyms", +    actions   = synonyms.process, +    arguments = { +        "string", +        { +            { "criterium" }, +            { "language" }, +            { "method" } +        } +    } +} | 
