diff options
Diffstat (limited to 'tex/context/base/strc-reg.lua')
-rw-r--r-- | tex/context/base/strc-reg.lua | 332 |
1 files changed, 163 insertions, 169 deletions
diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua index c5519141f..1ea285a90 100644 --- a/tex/context/base/strc-reg.lua +++ b/tex/context/base/strc-reg.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['strc-reg'] = { local next, type = next, type local texwrite, texcount = tex.write, tex.count -local format, gmatch, concat = string.format, string.gmatch, table.concat +local format, gmatch, concat, remove = string.format, string.gmatch, table.concat, table.remove local utfchar = utf.char local lpegmatch = lpeg.match local allocate, mark = utilities.storage.allocate, utilities.storage.mark @@ -333,6 +333,7 @@ function registers.compare(a,b) elseif page_a > page_b then return 1 end + else -- see end return 0 end @@ -448,94 +449,161 @@ function registers.userdata(index,name) end end --- proc can be wrapped +-- todo: ownnumber local seeindex = 0 -function registers.flush(data,options,prefixspec,pagespec) - local equal = table.are_equal - -- local usedtags = { } - -- for i=1,#result do - -- usedtags[#usedtags+1] = result[i].tag - -- end - -- context.setvalue("usedregistertags",concat(usedtags,",")) -- todo: { } and escape special chars - -- - context.startregisteroutput() - local collapse_singles = options.compress == interfaces.variables.yes - local collapse_ranges = options.compress == interfaces.variables.all - local result = data.result - -- todo ownnumber - local function pagenumber(entry) - local er = entry.references - context.registeronepage( - entry.processors and entry.processors[2] or "", - er.internal or 0, - er.realpage or 0, - function() helpers.prefixpage(entry,prefixspec,pagespec) end - ) - end - local function pagerange(f_entry,t_entry,is_last) - local fer = f_entry.references - local ter = t_entry.references - context.registerpagerange( - f_entry.processors and f_entry.processors[2] or "", - fer.internal or 0, - fer.realpage or 0, - function() - helpers.prefixpage(f_entry,prefixspec,pagespec) - end, - ter.internal or 0, - ter.lastrealpage or ter.realpage or 0, - function() - if is_last then - helpers.prefixlastpage(t_entry,prefixspec,pagespec) -- swaps page and realpage keys - else - helpers.prefixpage (t_entry,prefixspec,pagespec) - end +local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec) + local fer, ter = f_entry.references, t_entry.references + context.registerpagerange( + f_entry.processors and f_entry.processors[2] or "", + fer.internal or 0, + fer.realpage or 0, + function() + helpers.prefixpage(f_entry,prefixspec,pagespec) + end, + ter.internal or 0, + ter.lastrealpage or ter.realpage or 0, + function() + if is_last then + helpers.prefixlastpage(t_entry,prefixspec,pagespec) -- swaps page and realpage keys + else + helpers.prefixpage (t_entry,prefixspec,pagespec) end - ) - end - -- - -- maybe we can nil the splits and save memory - -- - do - -- hash words (potential see destinations) - local words = { } - for i=1,#result do - local data = result[i].data - for j=1,#data do - local d = data[j] - local word = d.list[1][1] - words[word] = d + end + ) +end + +local function pagenumber(entry,prefixspec,pagespec) + local er = entry.references + context.registeronepage( + entry.processors and entry.processors[2] or "", + er.internal or 0, + er.realpage or 0, + function() helpers.prefixpage(entry,prefixspec,pagespec) end + ) +end + +-- local usedtags = { } +-- for i=1,#result do +-- usedtags[#usedtags+1] = result[i].tag +-- end +-- context.setvalue("usedregistertags",concat(usedtags,",")) -- todo: { } and escape special chars + +--~ local function remove(pages,i) -- todo: use table.remove(pages,i) +--~ for j=i,#pages-1 do +--~ pages[j] = pages[j+1] +--~ end +--~ pages[#pages] = nil +--~ 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 - -- link seewords to words and tag destination - for i=1,#result do - local data = result[i].data - for j=1,#data do - local d = data[j] - local seeword = d.seeword - if seeword then - local text = seeword.text - if text then - local w = words[text] - if w then - local wr = w.references -- the referred word - local dr = d.references -- the see word - if wr.seeparent then - dr.seeindex = wr.seeparent - else - seeindex = seeindex + 1 - wr.seeparent = seeindex - dr.seeindex = seeindex - end + end + return false +end + +function collapsepages(pages) + while collapsedpage(pages) do end +end + +local function crosslinkseewords(result) + -- hash words (potential see destinations) + local words = { } + for i=1,#result do + local data = result[i].data + for j=1,#data do + local d = data[j] + local word = d.list[1][1] + words[word] = d + end + end + -- link seewords to words and tag destination + for i=1,#result do + local data = result[i].data + for j=1,#data do + local d = data[j] + local seeword = d.seeword + if seeword then + local text = seeword.text + if text then + local w = words[text] + if w then + local wr = w.references -- the referred word + local dr = d.references -- the see word + if wr.seeparent then + dr.seeindex = wr.seeparent + else + seeindex = seeindex + 1 + wr.seeparent = seeindex + dr.seeindex = seeindex end end end end end end - -- +end + +function registers.flush(data,options,prefixspec,pagespec) + local equal = table.are_equal + local collapse_singles = options.compress == variables.yes + local collapse_ranges = options.compress == variables.all + local result = data.result + crosslinkseewords(result) + context.startregisteroutput() for i=1,#result do -- ranges need checking ! local sublist = result[i] @@ -568,7 +636,7 @@ function registers.flush(data,options,prefixspec,pagespec) context.startregisterentries(n) end end - local internal = entry.references.internal or 0 + local internal = entry.references.internal or 0 local seeparent = entry.references.seeparent or "" local processor = entry.processors and entry.processors[1] or "" if metadata then @@ -588,9 +656,7 @@ function registers.flush(data,options,prefixspec,pagespec) 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 = entry, nil, entry - local pages = { } - local dd = d + local first, last, prev, pages, dd = entry, nil, entry, { }, d while dd < #data do dd = dd + 1 local next = data[dd] @@ -600,11 +666,7 @@ function registers.flush(data,options,prefixspec,pagespec) --~ first = nil break elseif next.references.lastrealpage then - if first then - pages[#pages+1] = { first, last or first } - else - pages[#pages+1] = { entry, entry } - end + pages[#pages+1] = first and { first, last or first } or { entry, entry } pages[#pages+1] = { next, next } first, last, prev = nil, nil, nil elseif not first then @@ -620,102 +682,35 @@ function registers.flush(data,options,prefixspec,pagespec) pages[#pages+1] = { first, last or first } end if collapse_ranges and #pages > 1 then - -- ok, not that efficient - local function doit() - local function bubble(i) - for j=i,#pages-1 do - pages[j] = pages[j+1] - end - pages[#pages] = nil - end - 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 - bubble(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 } - bubble(i) - return true - elseif second_last_pn < first_last_pn then - -- 2=8, 3-4 -> 2=8 - bubble(i) - return true - elseif first_last_pn < second_last_pn then - -- 2=8, 3-9 -> 2-9 - pages[i-1] = { first_first, second_last } - bubble(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 } - bubble(i) - return true - elseif second_first.references.lastrealpage then - -- 2=8, 9=11 -> 2-11 - pages[i-1] = { first_first, second_last } - bubble(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 } - bubble(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 } - bubble(i) - return true - end - end - return false - end - while doit() do end + collapsepages(pages) end - -- if #pages > 0 then -- or 0 d = dd for p=1,#pages do local first, last = pages[p][1], pages[p][2] if first == last then if first.references.lastrealpage then - pagerange(first,first,true) + pagerange(first,first,true,prefixspec,pagespec) else - pagenumber(first) + pagenumber(first,prefixspec,pagespec) end elseif last.references.lastrealpage then - pagerange(first,last,true) + pagerange(first,last,true,prefixspec,pagespec) else - pagerange(first,last,false) + pagerange(first,last,false,prefixspec,pagespec) end end + elseif entry.references.lastrealpage then + pagerange(entry,entry,true,prefixspec,pagespec) else - if entry.references.lastrealpage then - pagerange(entry,entry,true) - else - pagenumber(entry) - end + pagenumber(entry,prefixspec,pagespec) end else while true do if entry.references.lastrealpage then - pagerange(entry,entry,true) + pagerange(entry,entry,true,prefixspec,pagespec) else - pagenumber(entry) + pagenumber(entry,prefixspec,pagespec) end if d == #data then break @@ -733,13 +728,12 @@ function registers.flush(data,options,prefixspec,pagespec) end context.stopregisterpages() elseif kind == 'see' then - -- maybe some day more words + -- maybe some day more words, todo: metadata like normal entries context.startregisterseewords() - local seeindex = entry.references.seeindex or "" - local seetext = entry.seeword.text or "" - local proc = entry.processors and entry.processors[1] - -- todo: metadata like normal entries - context.registeroneword(proc or "",0,seeindex,seetext) + local seeindex = entry.references.seeindex or "" + local seetext = entry.seeword.text or "" + local processor = entry.processors and entry.processors[1] or "" + context.registeroneword(processor,0,seeindex,seetext) context.stopregisterseewords() end end |