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" } + } + } +} |