diff options
Diffstat (limited to 'tex/context/base/strc-syn.lua')
-rw-r--r-- | tex/context/base/strc-syn.lua | 284 |
1 files changed, 202 insertions, 82 deletions
diff --git a/tex/context/base/strc-syn.lua b/tex/context/base/strc-syn.lua index ca4b3ac18..5f3557a69 100644 --- a/tex/context/base/strc-syn.lua +++ b/tex/context/base/strc-syn.lua @@ -7,10 +7,13 @@ if not modules then modules = { } end modules ['strc-syn'] = { } local next, type = next, type -local format = string.format -local allocate = utilities.storage.allocate --- interface to tex end +local context = context +local implement = interfaces.implement + +local allocate = utilities.storage.allocate + +local sorters = sorters local structures = structures local synonyms = structures.synonyms @@ -19,6 +22,10 @@ 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 @@ -37,94 +44,144 @@ job.register('structures.synonyms.collected', tobesaved, initializer, finalizer) -- todo: allocate becomes metatable -local function allocate(class) - local d = tobesaved[class] - if not d then - d = { - metadata = { - language = 'en', - sorted = false, - class = class - }, - entries = { - }, - hash = { - } +table.setmetatableindex(tobesaved,function(t,k) + local v = { + metadata = { + language = 'en', + sorted = false, + class = v + }, + entries = { + }, + hash = { } - tobesaved[class] = d - end - return d -end + } + t[k] = v + return v +end) function synonyms.define(class,kind) - local data = allocate(class) + local data = tobesaved[class] data.metadata.kind = kind end function synonyms.register(class,kind,spec) - local data = allocate(class) + 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 data.hash[spec.definition.tag or ""] then - data.entries[#data.entries+1] = spec - data.hash[spec.definition.tag or ""] = spec + if not hash[tag] then + if definition.used == nil then + definition.used = false + end + if definition.shown == nil then + definition.shown = false + end + local entries = data.entries + entries[#entries+1] = spec + hash[tag] = spec end end function synonyms.registerused(class,tag) - local data = allocate(class) - local dht = data.hash[tag] - if dht then - dht.definition.used = true + 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 +end + +function synonyms.isshown(class,tag) + local data = tobesaved[class] + local okay = data.hash[tag] + return okay and okay.definition.shown +end + +function synonyms.resetused(class) + for tag, data in next, tobesaved[class].hash do + data.definition.used = false + end +end + +function synonyms.resetshown(class) + for tag, data in next, tobesaved[class].hash do + data.definition.shown = false end end function synonyms.synonym(class,tag) - local data = allocate(class).hash - local d = data[tag] - if d then - local de = d.definition - de.used = true - context(de.synonym) + 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 end function synonyms.meaning(class,tag) - local data = allocate(class).hash - local d = data[tag] - if d then - local de = d.definition - de.used = true - context(de.meaning) + 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 synonyms.compare = sorters.comparers.basic -- (a,b) function synonyms.filter(data,options) - local result = { } + local result = { } local entries = data.entries - local all = options and options.criterium == interfaces.variables.all - for i=1,#entries do - local entry = entries[i] - if all or entry.definition.used then - result[#result+1] = entry + local all = options and options.criterium == interfaces.variables.all + if 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 + result[#result+1] = entry + end end end data.result = result end function synonyms.prepare(data) - local strip = sorters.strip - local splitter = sorters.splitters.utf local result = data.result if result then for i=1, #result do - local r = result[i] - local rd = r.definition - if rd then - local rt = rd.tag - local sortkey = (rt and rt ~= "" and rt) or rd.synonym - r.split = splitter(strip(sortkey)) + local entry = result[i] + local definition = entry.definition + if definition then + local tag = definition.tag + local key = tag ~= "" and tag or definition.synonym + entry.split = splitter(strip(key)) end end end @@ -132,21 +189,31 @@ end function synonyms.sort(data,options) sorters.sort(data.result,synonyms.compare) + data.metadata.sorted = true end -function synonyms.finalize(data,options) - local result = data.result - data.metadata.nofsorted = #result - local split = { } +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 v = result[k] - local entry, tag = sorters.firstofsplit(v) - local s = split[entry] -- keeps track of change - if not s then - s = { tag = tag, data = { } } - split[entry] = s + 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 - s.data[#s.data+1] = v + nofdone = nofdone + 1 + done[nofdone] = entry end data.result = split end @@ -154,33 +221,28 @@ 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 kind = data.metadata.kind -- hack, will be done better - -- context[format("\\start%soutput",kind)]() local result = data.result - local sorted = table.sortedkeys(result) - for k=1,#sorted do - local letter = sorted[k] - local sublist = result[letter] - local data = sublist.data - -- context[format("\\start%ssection",kind)](sublist.tag) + for i=1,#result do + local sublist = result[i] + local letter = sublist.tag + local data = sublist.data for d=1,#data do local entry = data[d].definition - -- context[format("\\%sentry",kind)](d,entry.tag,entry.synonym,entry.meaning or "") - context("\\%sentry{%s}{%s}{%s}{%s}",kind,d,entry.tag,entry.synonym,entry.meaning or "") + ctx_synonymentry(d,entry.tag,entry.synonym,entry.meaning or "") end - -- context[format("\\stop%ssection",kind)]() end - -- context[format("\\stop%soutput",kind)]() - data.result = nil + data.result = nil data.metadata.sorted = false end function synonyms.analyzed(class,options) - local data = synonyms.collected[class] + local data = collected[class] if data and data.entries then options = options or { } - sorters.setlanguage(options.language) + 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 @@ -192,7 +254,65 @@ end function synonyms.process(class,options) if synonyms.analyzed(class,options) then - synonyms.flush(synonyms.collected[class],options) + synonyms.flush(collected[class],options) end end +-- todo: local higher up + +implement { name = "registerusedsynonym", actions = synonyms.registerused, arguments = { "string", "string" } } +implement { name = "registershownsynonym", actions = synonyms.registershown, arguments = { "string", "string" } } +implement { name = "synonymmeaning", actions = synonyms.meaning, arguments = { "string", "string" } } +implement { name = "synonymname", actions = synonyms.synonym, arguments = { "string", "string" } } +implement { name = "resetusedsynonyms", actions = synonyms.resetused, arguments = "string" } +implement { name = "resetshownsynonyms", actions = synonyms.resetshown, arguments = "string" } + +implement { + name = "doifelsesynonymused", + actions = { synonyms.isused, commands.doifelse }, + arguments = { "string", "string" } +} + +implement { + name = "doifelsesynonymshown", + actions = { synonyms.isshown, commands.doifelse }, + arguments = { "string", "string" } +} + +implement { + name = "registersynonym", + actions = synonyms.register, + arguments = { + "string", + "string", + { + { "metadata", { + { "catcodes", "integer" }, + { "coding" }, + { "xmlroot" } + } + }, + { + "definition", { + { "tag" }, + { "synonym" }, + { "meaning" }, + { "used", "boolean" } + } + } + } + } +} + +implement { + name = "processsynonyms", + actions = synonyms.process, + arguments = { + "string", + { + { "criterium" }, + { "language" }, + { "method" } + } + } +} |