diff options
Diffstat (limited to 'tex/context/base/strc-reg.lua')
-rw-r--r-- | tex/context/base/strc-reg.lua | 1347 |
1 files changed, 0 insertions, 1347 deletions
diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua deleted file mode 100644 index ed3292195..000000000 --- a/tex/context/base/strc-reg.lua +++ /dev/null @@ -1,1347 +0,0 @@ -if not modules then modules = { } end modules ['strc-reg'] = { - version = 1.001, - comment = "companion to strc-reg.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 format, gmatch = string.format, string.gmatch -local equal, concat, remove = table.are_equal, table.concat, table.remove -local utfchar = utf.char -local lpegmatch = lpeg.match -local allocate = utilities.storage.allocate - -local trace_registers = false trackers.register("structures.registers", function(v) trace_registers = v end) - -local report_registers = logs.reporter("structure","registers") - -local structures = structures -local registers = structures.registers -local helpers = structures.helpers -local sections = structures.sections -local documents = structures.documents -local pages = structures.pages -local references = structures.references - -local usedinternals = references.usedinternals - -local mappings = sorters.mappings -local entries = sorters.entries -local replacements = sorters.replacements - -local processors = typesetters.processors -local splitprocessor = processors.split - -local texgetcount = tex.getcount - -local variables = interfaces.variables -local v_forward = variables.forward -local v_all = variables.all -local v_yes = variables.yes -local v_current = variables.current -local v_previous = variables.previous -local v_text = variables.text - -local context = context -local commands = commands - -local implement = interfaces.implement - -local matchingtilldepth = sections.matchingtilldepth -local numberatdepth = sections.numberatdepth -local currentlevel = sections.currentlevel -local currentid = sections.currentid - -local touserdata = helpers.touserdata - -local internalreferences = references.internals -local setinternalreference = references.setinternalreference - -local setmetatableindex = table.setmetatableindex -local texsetattribute = tex.setattribute - -local a_destination = attributes.private('destination') - -local absmaxlevel = 5 -- \c_strc_registers_maxlevel - -local h_prefixpage = helpers.prefixpage -local h_prefixlastpage = helpers.prefixlastpage -local h_title = helpers.title - -local ctx_startregisteroutput = context.startregisteroutput -local ctx_stopregisteroutput = context.stopregisteroutput -local ctx_startregistersection = context.startregistersection -local ctx_stopregistersection = context.stopregistersection -local ctx_startregisterentries = context.startregisterentries -local ctx_stopregisterentries = context.stopregisterentries -local ctx_startregisterentry = context.startregisterentry -local ctx_stopregisterentry = context.stopregisterentry -local ctx_startregisterpages = context.startregisterpages -local ctx_stopregisterpages = context.stopregisterpages -local ctx_startregisterseewords = context.startregisterseewords -local ctx_stopregisterseewords = context.stopregisterseewords -local ctx_registerentry = context.registerentry -local ctx_registerseeword = context.registerseeword -local ctx_registerpagerange = context.registerpagerange -local ctx_registeronepage = context.registeronepage - --- possible export, but ugly code (overloads) --- --- local output, section, entries, nofentries, pages, words, rawtext --- --- h_title = function(a,b) rawtext = a end --- --- local function ctx_startregisteroutput() --- output = { } --- section = nil --- entries = nil --- nofentries = nil --- pages = nil --- words = nil --- rawtext = nil --- end --- local function ctx_stopregisteroutput() --- inspect(output) --- output = nil --- section = nil --- entries = nil --- nofentries = nil --- pages = nil --- words = nil --- rawtext = nil --- end --- local function ctx_startregistersection(tag) --- section = { } --- output[#output+1] = { --- section = section, --- tag = tag, --- } --- end --- local function ctx_stopregistersection() --- end --- local function ctx_startregisterentries(n) --- entries = { } --- nofentries = 0 --- section[#section+1] = entries --- end --- local function ctx_stopregisterentries() --- end --- local function ctx_startregisterentry(n) -- or subentries (nested?) --- nofentries = nofentries + 1 --- entry = { } --- entries[nofentries] = entry --- end --- local function ctx_stopregisterentry() --- nofentries = nofentries - 1 --- entry = entries[nofentries] --- end --- local function ctx_startregisterpages() --- pages = { } --- entry.pages = pages --- end --- local function ctx_stopregisterpages() --- end --- local function ctx_startregisterseewords() --- words = { } --- entry.words = words --- end --- local function ctx_stopregisterseewords() --- end --- local function ctx_registerentry(processor,internal,seeparent,text) --- text() --- entry.text = { --- processor = processor, --- internal = internal, --- seeparent = seeparent, --- text = rawtext, --- } --- end --- local function ctx_registerseeword(i,n,processor,internal,seeindex,seetext) --- seetext() --- entry.words[i] = { --- processor = processor, --- internal = internal, --- seeparent = seeparent, --- seetext = rawtext, --- } --- end --- local function ctx_registerpagerange(fprocessor,finternal,frealpage,lprocessor,linternal,lrealpage) --- pages[#pages+1] = { --- first = { --- processor = fprocessor, --- internal = finternal, --- realpage = frealpage, --- }, --- last = { --- processor = lprocessor, --- internal = linternal, --- realpage = lrealpage, --- }, --- } --- end --- local function ctx_registeronepage(processor,internal,realpage) --- pages[#pages+1] = { --- processor = processor, --- internal = internal, --- realpage = realpage, --- } --- end - --- some day we will share registers and lists (although there are some conceptual --- differences in the application of keywords) - -local function filtercollected(names,criterium,number,collected,prevmode) - if not criterium or criterium == "" then - criterium = v_all - end - local data = documents.data - local numbers = data.numbers - local depth = data.depth - local hash = { } - local result = { } - local nofresult = 0 - local all = not names or names == "" or names == v_all - local detail = nil - if not all then - for s in gmatch(names,"[^, ]+") do - hash[s] = true - end - end - if criterium == v_all or criterium == v_text then - for i=1,#collected do - local v = collected[i] - if all then - nofresult = nofresult + 1 - result[nofresult] = v - else - local vmn = v.metadata and v.metadata.name - if hash[vmn] then - nofresult = nofresult + 1 - result[nofresult] = v - end - end - end - elseif criterium == v_current then - local collectedsections = sections.collected - for i=1,#collected do - local v = collected[i] - local sectionnumber = collectedsections[v.references.section] - if sectionnumber then - local cnumbers = sectionnumber.numbers - if prevmode then - if (all or hash[v.metadata.name]) and #cnumbers >= depth then -- is the = ok for lists as well? - local ok = true - for d=1,depth do - if not (cnumbers[d] == numbers[d]) then -- no zero test - ok = false - break - end - end - if ok then - nofresult = nofresult + 1 - result[nofresult] = v - end - end - else - if (all or hash[v.metadata.name]) and #cnumbers > depth then - local ok = true - for d=1,depth do - local cnd = cnumbers[d] - if not (cnd == 0 or cnd == numbers[d]) then - ok = false - break - end - end - if ok then - nofresult = nofresult + 1 - result[nofresult] = v - end - end - end - end - end - elseif criterium == v_previous then - local collectedsections = sections.collected - for i=1,#collected do - local v = collected[i] - local sectionnumber = collectedsections[v.references.section] - if sectionnumber then - local cnumbers = sectionnumber.numbers - if (all or hash[v.metadata.name]) and #cnumbers >= depth then - local ok = true - if prevmode then - for d=1,depth do - if not (cnumbers[d] == numbers[d]) then - ok = false - break - end - end - else - for d=1,depth do - local cnd = cnumbers[d] - if not (cnd == 0 or cnd == numbers[d]) then - ok = false - break - end - end - end - if ok then - nofresult = nofresult + 1 - result[nofresult] = v - end - end - end - end - elseif criterium == variables["local"] then - if sections.autodepth(data.numbers) == 0 then - return filtercollected(names,v_all,number,collected,prevmode) - else - return filtercollected(names,v_current,number,collected,prevmode) - end - else -- sectionname, number - -- beware, this works ok for registers - -- to be redone with reference instead - local depth = sections.getlevel(criterium) - local number = tonumber(number) or numberatdepth(depth) or 0 - if trace_registers then - detail = format("depth: %s, number: %s, numbers: %s, startset: %s",depth,number,concat(sections.numbers(),".",1,depth),#collected) - end - if number > 0 then - for i=1,#collected do - local v = collected[i] - local r = v.references - if r then - local sectionnumber = sections.collected[r.section] - if sectionnumber then - local metadata = v.metadata - local cnumbers = sectionnumber.numbers - if cnumbers then - if (all or hash[metadata.name or false]) and #cnumbers >= depth and matchingtilldepth(depth,cnumbers) then - nofresult = nofresult + 1 - result[nofresult] = v - end - end - end - end - end - end - end - if trace_registers then - if detail then - report_registers("criterium %a, detail %a, found %a",criterium,detail,#result) - else - report_registers("criterium %a, detail %a, found %a",criterium,nil,#result) - end - end - return result -end - -local tobesaved = allocate() -local collected = allocate() - -registers.collected = collected -registers.tobesaved = tobesaved -registers.filtercollected = filtercollected - --- we follow a different strategy than by lists, where we have a global --- result table; we might do that here as well but since sorting code is --- older we delay that decision - --- maybe store the specification in the format (although we predefine only --- saved registers) - -local function checker(t,k) - local v = { - metadata = { - language = 'en', - sorted = false, - class = class, - }, - entries = { }, - } - t[k] = v - return v -end - -local function initializer() - tobesaved = registers.tobesaved - collected = registers.collected - setmetatableindex(tobesaved,checker) - setmetatableindex(collected,checker) - local usedinternals = references.usedinternals - for name, list in next, collected do - local entries = list.entries - if not list.metadata.notsaved then - for e=1,#entries do - local entry = entries[e] - local r = entry.references - if r then - local internal = r and r.internal - if internal then - internalreferences[internal] = entry - usedinternals[internal] = r.used - end - end - end - end - end -end - -local function finalizer() - local flaginternals = references.flaginternals - for k, v in next, tobesaved do - local entries = v.entries - if entries then - for i=1,#entries do - local r = entries[i].references - if r and flaginternals[r.internal] then - r.used = true - end - end - end - end -end - -job.register('structures.registers.collected', tobesaved, initializer, finalizer) - -setmetatableindex(tobesaved,checker) -setmetatableindex(collected,checker) - -local function defineregister(class,method) - local d = tobesaved[class] - if method == v_forward then - d.metadata.notsaved = true - end -end - -registers.define = defineregister -- 4 times is somewhat over the top but we want consistency -registers.setmethod = defineregister -- and we might have a difference some day - -implement { - name = "defineregister", - actions = defineregister, - arguments = { "string", "string" } -} - -implement { - name = "setregistermethod", - actions = defineregister, -- duplicate use - arguments = { "string", "string" } -} - -local entrysplitter = lpeg.tsplitat('+') -- & obsolete in mkiv - -local tagged = { } - --- this whole splitting is an inheritance of mkii - -local function preprocessentries(rawdata) - local entries = rawdata.entries - if entries then - -- - -- local e = entries[1] or "" - -- local k = entries[2] or "" - -- local et, kt, entryproc, pageproc - -- if type(e) == "table" then - -- et = e - -- else - -- entryproc, e = splitprocessor(e) - -- et = lpegmatch(entrysplitter,e) - -- end - -- if type(k) == "table" then - -- kt = k - -- else - -- pageproc, k = splitprocessor(k) - -- kt = lpegmatch(entrysplitter,k) - -- end - -- - local processors = rawdata.processors - local et = entries.entries - local kt = entries.keys - local entryproc = processors and processors.entry - local pageproc = processors and processors.page - if entryproc == "" then - entryproc = nil - end - if pageproc == "" then - pageproc = nil - end - if not et then - local p, e = splitprocessor(entries.entry or "") - if p then - entryproc = p - end - et = lpegmatch(entrysplitter,e) - end - if not kt then - local p, k = splitprocessor(entries.key or "") - if p then - pageproc = p - end - kt = lpegmatch(entrysplitter,k) - end - -- - entries = { } - local ok = false - for k=#et,1,-1 do - local etk = et[k] - local ktk = kt[k] - if not ok and etk == "" then - entries[k] = nil - else - entries[k] = { etk or "", ktk ~= "" and ktk or nil } - ok = true - end - end - rawdata.list = entries - if pageproc or entryproc then - rawdata.processors = { entryproc, pageproc } -- old way: indexed .. will be keys - end - rawdata.entries = nil - end - local seeword = rawdata.seeword - if seeword then - seeword.processor, seeword.text = splitprocessor(seeword.text or "") - end -end - -local function storeregister(rawdata) -- metadata, references, entries - local references = rawdata.references - local metadata = rawdata.metadata - -- checking - if not metadata then - metadata = { } - rawdata.metadata = metadata - end - -- - if not metadata.kind then - metadata.kind = "entry" - end - -- - if not metadata.catcodes then - metadata.catcodes = tex.catcodetable -- get - end - -- - local name = metadata.name - local notsaved = tobesaved[name].metadata.notsaved - -- - if not references then - references = { } - rawdata.references = references - end - -- - local internal = references.internal - if not internal then - internal = texgetcount("locationcount") -- we assume that it has been set - references.internal = internal - end - -- - if notsaved then - usedinternals[internal] = true -- todo view (we assume that forward references index entries are used) - end - -- - if not references.realpage then - references.realpage = 0 -- just to be sure as it can be refered to - end - -- - local userdata = rawdata.userdata - if userdata then - rawdata.userdata = touserdata(userdata) - end - -- - references.section = currentid() - metadata.level = currentlevel() - -- - local data = notsaved and collected[name] or tobesaved[name] - local entries = data.entries - internalreferences[internal] = rawdata - preprocessentries(rawdata) - entries[#entries+1] = rawdata - local label = references.label - if label and label ~= "" then - tagged[label] = #entries - else - references.label = nil - end - return #entries -end - -registers.store = storeregister - -function registers.enhance(name,n) - local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name] - local entry = data.entries[n] - if entry then - entry.references.realpage = texgetcount("realpageno") - end -end - -function registers.extend(name,tag,rawdata) -- maybe do lastsection internally - if type(tag) == "string" then - tag = tagged[tag] - end - if tag then - local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name] - local entry = data.entries[tag] - if entry then - local references = entry.references - references.lastrealpage = texgetcount("realpageno") - references.lastsection = currentid() - if rawdata then - local userdata = rawdata.userdata - if userdata then - rawdata.userdata = touserdata(userdata) - end - if rawdata.entries then - preprocessentries(rawdata) - end - local metadata = rawdata.metadata - if metadata and not metadata.catcodes then - metadata.catcodes = tex.catcodetable -- get - end - for k, v in next, rawdata do - local rk = references[k] - if not rk then - references[k] = v - else - for kk, vv in next, v do - if type(vv) == "table" then - if next(vv) then - rk[kk] = vv - end - elseif vv ~= "" then - rk[kk] = vv - end - end - end - end - end - end - end -end - -function registers.get(tag,n) - local list = tobesaved[tag] - return list and list.entries[n] -end - -implement { - name = "enhanceregister", - actions = registers.enhance, - arguments = { "string", "integer" } -} - -implement { - name = "extendregister", - actions = registers.extend, - arguments = { "string", "string" } -} - -implement { - name = "storeregister", - actions = function(rawdata) - local nofentries = storeregister(rawdata) - setinternalreference { internal = rawdata.references.internal } - context(nofentries) - end, - arguments = { - { - { "metadata", { - { "kind" }, - { "name" }, - { "coding" }, - { "level", "integer" }, - { "catcodes", "integer" }, - { "own" }, - { "xmlroot" }, - { "xmlsetup" } - } - }, - { "entries", { - { "entries", "list" }, - { "keys", "list" }, - { "entry" }, - { "key" } - } - }, - { "references", { - { "internal", "integer" }, - { "section", "integer" }, - { "label" } - } - }, - { "seeword", { - { "text" } - } - }, - { "processors", { - { "entry" }, - { "key" }, - { "page" } - } - }, - { "userdata" }, - } - } -} - --- sorting and rendering - -local compare = sorters.comparers.basic - -function registers.compare(a,b) - local result = compare(a,b) - if result ~= 0 then - return result - else - local ka = a.metadata.kind - local kb = b.metadata.kind - if ka == kb then - local page_a, page_b = a.references.realpage, b.references.realpage - if not page_a or not page_b then - return 0 - elseif page_a < page_b then - return -1 - elseif page_a > page_b then - return 1 - end - elseif ka == "see" then - return 1 - elseif kb == "see" then - return -1 - end - end - return 0 -end - -function registers.filter(data,options) - data.result = registers.filtercollected(nil,options.criterium,options.number,data.entries,true) -end - -local seeindex = 0 - --- meerdere loops, seewords, dan words, anders seewords - -local function crosslinkseewords(result) -- all words - -- collect all seewords - local seewords = { } - for i=1,#result do - local data = result[i] - local seeword = data.seeword - if seeword then - local seetext = seeword.text - if seetext and not seewords[seetext] then - seeindex = seeindex + 1 - seewords[seetext] = seeindex - if trace_registers then - report_registers("see word %03i: %s",seeindex,seetext) - end - end - end - end - -- mark seeparents - local seeparents = { } - for i=1,#result do - local data = result[i] - local word = data.list[1] - word = word and word[1] - if word then - local seeindex = seewords[word] - if seeindex then - seeparents[word] = data - data.references.seeparent = seeindex - if trace_registers then - report_registers("see parent %03i: %s",seeindex,word) - end - end - end - end - -- mark seewords and extend sort list - for i=1,#result do - local data = result[i] - local seeword = data.seeword - if seeword then - local text = seeword.text - if text then - local seeparent = seeparents[text] - if seeparent then - local seeindex = seewords[text] - local s, ns, d, w, l = { }, 0, data.split, seeparent.split, data.list - -- trick: we influence sorting by adding fake subentries - for i=1,#d do - ns = ns + 1 - s[ns] = d[i] -- parent - end - for i=1,#w do - ns = ns + 1 - s[ns] = w[i] -- see - end - data.split = s - -- we also register a fake extra list entry so that the - -- collapser works okay - l[#l+1] = { text, "" } - data.references.seeindex = seeindex - if trace_registers then - report_registers("see crosslink %03i: %s",seeindex,text) - end - end - end - end - end -end - -local function removeemptyentries(result) - local i, n, m = 1, #result, 0 - while i <= n do - local entry = result[i] - if #entry.list == 0 or #entry.split == 0 then - remove(result,i) - n = n - 1 - m = m + 1 - else - i = i + 1 - end - end - if m > 0 then - report_registers("%s empty entries removed in register",m) - end -end - -function registers.prepare(data) - -- data has 'list' table - local strip = sorters.strip - local splitter = sorters.splitters.utf - local result = data.result - if result then - for i=1, #result do - local entry = result[i] - local split = { } - local list = entry.list - if list then - for l=1,#list do - local ll = list[l] - local word = ll[1] - local key = ll[2] - if not key or key == "" then - key = word - end - split[l] = splitter(strip(key)) - end - end - entry.split = split - end - removeemptyentries(result) - crosslinkseewords(result) - end -end - -function registers.sort(data,options) - -- if options.pagenumber == false then - -- sorters.sort(data.result,compare) - -- else - sorters.sort(data.result,registers.compare) - -- end -end - -function registers.unique(data,options) - local result, nofresult, prev = { }, 0, nil - local dataresult = data.result - for k=1,#dataresult do - local v = dataresult[k] - if prev then - local vr = v.references - local pr = prev.references - if not equal(prev.list,v.list) then - -- ok - elseif pr.realpage ~= vr.realpage then - -- ok - else - local pl, vl = pr.lastrealpage, vr.lastrealpage - if pl or vl then - if not vl then - -- ok - elseif not pl then - -- ok - elseif pl ~= vl then - -- ok - else - v = nil - end - else - v = nil - end - end - end - if v then - nofresult = nofresult + 1 - result[nofresult] = v - prev = v - end - end - data.result = result -end - -function registers.finalize(data,options) -- maps character to index (order) - local result = data.result - data.metadata.nofsorted = #result - local split, nofsplit, lasttag, done, nofdone = { }, 0, nil, nil, 0 - local firstofsplit = sorters.firstofsplit - for k=1,#result do - local v = result[k] - local entry, tag = firstofsplit(v) - 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] = v - end - data.result = split -end - -local function analyzeregister(class,options) - local data = collected[class] - if data and data.entries then - options = options or { } - sorters.setlanguage(options.language,options.method,options.numberorder) - registers.filter(data,options) -- filter entries into results (criteria) - registers.prepare(data,options) -- adds split table parallel to list table - registers.sort(data,options) -- sorts results - registers.unique(data,options) -- get rid of duplicates - registers.finalize(data,options) -- split result in ranges - data.metadata.sorted = true - return data.metadata.nofsorted or 0 - else - return 0 - end -end - -registers.analyze = analyzeregister - -implement { - name = "analyzeregister", - actions = { analyzeregister, context }, - arguments = { - "string", - { - { "language" }, - { "method" }, - { "numberorder" }, - { "compress" }, - { "criterium" }, - { "pagenumber", "boolean" }, - } - } -} - --- todo take conversion from index - -function registers.userdata(index,name) - local data = references.internals[tonumber(index)] - return data and data.userdata and data.userdata[name] or nil -end - -implement { - name = "registeruserdata", - actions = { registers.userdata, context }, - arguments = { "integer", "string" } -} - --- todo: ownnumber - -local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec) - local fer, ter = f_entry.references, t_entry.references - ctx_registerpagerange( - f_entry.processors and f_entry.processors[2] or "", - fer.internal or 0, - fer.realpage or 0, - function() - h_prefixpage(f_entry,prefixspec,pagespec) - end, - ter.internal or 0, - ter.lastrealpage or ter.realpage or 0, - function() - if is_last then - h_prefixlastpage(t_entry,prefixspec,pagespec) -- swaps page and realpage keys - else - h_prefixpage (t_entry,prefixspec,pagespec) - end - end - ) -end - -local function pagenumber(entry,prefixspec,pagespec) - local er = entry.references - ctx_registeronepage( - entry.processors and entry.processors[2] or "", - er.internal or 0, - er.realpage or 0, - function() h_prefixpage(entry,prefixspec,pagespec) end - ) -end - -local function collapsedpage(pages) - for i=2,#pages do - local first, second = pages[i-1], pages[i] - local first_first, first_last, second_first, second_last = first[1], first[2], second[1], second[2] - local first_last_pn = first_last .references.realpage - local second_first_pn = second_first.references.realpage - local second_last_pn = second_last .references.realpage - local first_last_last = first_last .references.lastrealpage - local second_first_last = second_first.references.lastrealpage - if first_last_last then - first_last_pn = first_last_last - if second_first == second_last and second_first_pn <= first_last_pn then - -- 2=8, 5 -> 12=8 - remove(pages,i) - return true - elseif second_first == second_last and second_first_pn > first_last_pn then - -- 2=8, 9 -> 2-9 - pages[i-1] = { first_first, second_last } - remove(pages,i) - return true - elseif second_last_pn < first_last_pn then - -- 2=8, 3-4 -> 2=8 - remove(pages,i) - return true - elseif first_last_pn < second_last_pn then - -- 2=8, 3-9 -> 2-9 - pages[i-1] = { first_first, second_last } - remove(pages,i) - return true - elseif first_last_pn + 1 == second_first_pn and second_last_pn > first_last_pn then - -- 2=8, 9-11 -> 2-11 - pages[i-1] = { first_first, second_last } - remove(pages,i) - return true - elseif second_first.references.lastrealpage then - -- 2=8, 9=11 -> 2-11 - pages[i-1] = { first_first, second_last } - remove(pages,i) - return true - end - elseif second_first_last then - second_first_pn = second_first_last - if first_last_pn == second_first_pn then - -- 2-4, 5=9 -> 2-9 - pages[i-1] = { first_first, second_last } - remove(pages,i) - return true - end - elseif first_last_pn == second_first_pn then - -- 2-3, 3-4 -> 2-4 - pages[i-1] = { first_last, second_last } - remove(pages,i) - return true - end - end - return false -end - -local function collapsepages(pages) - while collapsedpage(pages) do end - return #pages -end - -function registers.flush(data,options,prefixspec,pagespec) - local collapse_singles = options.compress == v_yes - local collapse_ranges = options.compress == v_all - local show_page_number = options.pagenumber ~= false -- true or false - local result = data.result - local maxlevel = 0 - -- - for i=1,#result do - local data = result[i].data - for d=1,#data do - local m = #data[d].list - if m > maxlevel then - maxlevel = m - end - end - end - if maxlevel > absmaxlevel then - maxlevel = absmaxlevel - report_registers("limiting level to %a",maxlevel) - end - -- - ctx_startregisteroutput() - local done = { } - local started = false - for i=1,#result do - -- ranges need checking ! - local sublist = result[i] - -- local done = { false, false, false, false } - for i=1,maxlevel do - done[i] = false - end - local data = sublist.data - local d, n = 0, 0 - ctx_startregistersection(sublist.tag) - for d=1,#data do - local entry = data[d] - if entry.metadata.kind == "see" then - local list = entry.list - if #list > 1 then - list[#list] = nil - else - -- we have an \seeindex{Foo}{Bar} without Foo being defined anywhere .. somehow this message is wrong - -- report_registers("invalid see entry in register %a, reference %a",entry.metadata.name,list[1][1]) - end - end - end - -- ok, this is tricky: we use e[i] delayed so we need it to be local - -- but we don't want to allocate too many entries so there we go - while d < #data do - d = d + 1 - local entry = data[d] - local metadata = entry.metadata - local kind = metadata.kind - local list = entry.list - local e = { false, false, false } - for i=3,maxlevel do - e[i] = false - end - for i=1,maxlevel do - if list[i] then - e[i] = list[i][1] - end - if e[i] == done[i] then - -- skip - elseif not e[i] then - -- see ends up here - -- can't happen any more - done[i] = false - for j=i+1,maxlevel do - done[j] = false - end - elseif e[i] == "" then - done[i] = false - for j=i+1,maxlevel do - done[j] = false - end - else - done[i] = e[i] - for j=i+1,maxlevel do - done[j] = false - end - if started then - ctx_stopregisterentry() - started = false - end - if n == i then --- ctx_stopregisterentries() --- ctx_startregisterentries(n) - else - while n > i do - n = n - 1 - ctx_stopregisterentries() - end - while n < i do - n = n + 1 - ctx_startregisterentries(n) - end - end - local references = entry.references - local processors = entry.processors - local internal = references.internal or 0 - local seeparent = references.seeparent or "" - local processor = processors and processors[1] or "" - -- so, we need to keep e as is (local), or we need local title = e[i] ... which might be - -- more of a problem - ctx_startregisterentry(0) -- will become a counter - started = true - if metadata then - ctx_registerentry(processor,internal,seeparent,function() h_title(e[i],metadata) end) - else - -- can this happen? - ctx_registerentry(processor,internal,seeindex,e[i]) - end - end - end - if kind == 'entry' then - if show_page_number then - ctx_startregisterpages() - if collapse_singles or collapse_ranges then - -- we collapse ranges and keep existing ranges as they are - -- so we get prebuilt as well as built ranges - local first, last, prev, pages, dd, nofpages = entry, nil, entry, { }, d, 0 - while dd < #data do - dd = dd + 1 - local next = data[dd] - if next and next.metadata.kind == "see" then - dd = dd - 1 - break - else - local el, nl = entry.list, next.list - if not equal(el,nl) then - dd = dd - 1 - --~ first = nil - break - elseif next.references.lastrealpage then - nofpages = nofpages + 1 - pages[nofpages] = first and { first, last or first } or { entry, entry } - nofpages = nofpages + 1 - pages[nofpages] = { next, next } - first, last, prev = nil, nil, nil - elseif not first then - first, prev = next, next - elseif next.references.realpage - prev.references.realpage == 1 then -- 1 ? - last, prev = next, next - else - nofpages = nofpages + 1 - pages[nofpages] = { first, last or first } - first, last, prev = next, nil, next - end - end - end - if first then - nofpages = nofpages + 1 - pages[nofpages] = { first, last or first } - end - if collapse_ranges and nofpages > 1 then - nofpages = collapsepages(pages) - end - if nofpages > 0 then -- or 0 - d = dd - for p=1,nofpages do - local first, last = pages[p][1], pages[p][2] - if first == last then - if first.references.lastrealpage then - pagerange(first,first,true,prefixspec,pagespec) - else - pagenumber(first,prefixspec,pagespec) - end - elseif last.references.lastrealpage then - pagerange(first,last,true,prefixspec,pagespec) - else - pagerange(first,last,false,prefixspec,pagespec) - end - end - elseif entry.references.lastrealpage then - pagerange(entry,entry,true,prefixspec,pagespec) - else - pagenumber(entry,prefixspec,pagespec) - end - else - while true do - if entry.references.lastrealpage then - pagerange(entry,entry,true,prefixspec,pagespec) - else - pagenumber(entry,prefixspec,pagespec) - end - if d == #data then - break - else - d = d + 1 - local next = data[d] - if next.metadata.kind == "see" or not equal(entry.list,next.list) then - d = d - 1 - break - else - entry = next - end - end - end - end - ctx_stopregisterpages() - end - elseif kind == 'see' then - local t, nt = { }, 0 - while true do - nt = nt + 1 - t[nt] = entry - if d == #data then - break - else - d = d + 1 - local next = data[d] - if next.metadata.kind ~= "see" or not equal(entry.list,next.list) then - d = d - 1 - break - else - entry = next - end - end - end - ctx_startregisterseewords() - for i=1,nt do - local entry = t[i] - local seeword = entry.seeword - local seetext = seeword.text or "" - local processor = seeword.processor or (entry.processors and entry.processors[1]) or "" - local seeindex = entry.references.seeindex or "" - -- ctx_registerseeword(i,nt,processor,0,seeindex,seetext) - ctx_registerseeword(i,nt,processor,0,seeindex,function() h_title(seetext,metadata) end) - end - ctx_stopregisterseewords() - end - end - if started then - ctx_stopregisterentry() - started = false - end - while n > 0 do - ctx_stopregisterentries() - n = n - 1 - end - ctx_stopregistersection() - end - ctx_stopregisteroutput() - -- for now, maybe at some point we will do a multipass or so - data.result = nil - data.metadata.sorted = false - -- temp hack for luajittex : - local entries = data.entries - for i=1,#entries do - entries[i].split = nil - end - -- collectgarbage("collect") -end - -function registers.process(class,...) - if analyzeregister(class,...) > 0 then - local data = collected[class] - registers.flush(data,...) - end -end - -implement { - name = "processregister", - actions = registers.process, - arguments = { - "string", - { - { "language" }, - { "method" }, - { "numberorder" }, - { "compress" }, - { "criterium" }, - { "pagenumber", "boolean" }, - }, - { - { "separatorset" }, - { "conversionset" }, - { "starter" }, - { "stopper" }, - { "set" }, - { "segments" }, - { "connector" }, - }, - { - { "prefix" }, - { "separatorset" }, - { "conversionset" }, - { "starter" }, - { "stopper" }, - { "segments" }, - } - } -} |