diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/strc-lst.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/strc-lst.lua | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/strc-lst.lua b/Master/texmf-dist/tex/context/base/strc-lst.lua new file mode 100644 index 00000000000..dd45e7f689d --- /dev/null +++ b/Master/texmf-dist/tex/context/base/strc-lst.lua @@ -0,0 +1,413 @@ +if not modules then modules = { } end modules ['strc-lst'] = { + version = 1.001, + comment = "companion to strc-lst.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- when all datastructures are stable a packer will be added which will +-- bring down memory consumption a bit; we can use for instance a pagenumber, +-- section, metadata cache (internal then has to move up one level) or a +-- shared cache [we can use a fast and stupid serializer] + +local format, tonumber = string.format, tonumber +local texsprint, texprint, texwrite, texcount = tex.sprint, tex.print, tex.write, tex.count +local insert, remove = table.insert, table.remove + +local ctxcatcodes = tex.ctxcatcodes + +structure.lists = structure.lists or { } +structure.sections = structure.sections or { } +structure.helpers = structure.helpers or { } +structure.documents = structure.documents or { } +structure.pages = structure.pages or { } + +local lists = structure.lists +local sections = structure.sections +local helpers = structure.helpers +local documents = structure.documents +local pages = structure.pages + +lists.collected = lists.collected or { } +lists.tobesaved = lists.tobesaved or { } +lists.enhancers = lists.enhancers or { } +lists.internals = lists.internals or { } +lists.ordered = lists.ordered or { } + +local variables = interfaces.variables + +local function initializer() + -- create a cross reference between internal references + -- and list entries + local collected = lists.collected + local internals = jobreferences.internals + local ordered = lists.ordered + for i=1,#collected do + local c = collected[i] + local m = c.metadata + local r = c.references + if m then + -- access by internal reference + local internal = r and r.internal + if internal then + internals[internal] = c + end + -- access by order in list + local kind, name = m.kind, m.name + if kind and name then + local ok = ordered[kind] + if ok then + local on = ok[name] + if on then + on[#on+1] = c + else + ok[name] = { c } + end + else + ordered[kind] = { [name] = { c } } + end + end + end + end +end + +if job then + job.register('structure.lists.collected', structure.lists.tobesaved, initializer) +end + +local cached = { } +local pushed = { } + +function lists.push(t) + local r = t.references + local i = (r and r.internal) or 0 -- brrr + local p = pushed[i] + if not p then + p = #cached + 1 + cached[p] = helpers.simplify(t) + pushed[i] = p + end + texwrite(p) +end + +function lists.doifstoredelse(n) + commands.doifelse(cached[tonumber(n)]) +end + +-- this is the main pagenumber enhancer + +function lists.enhance(n) + -- todo: symbolic names for counters + local l = cached[n] + if l then + -- + l.directives = nil -- might change + -- save in the right order (happen sat shipout) + lists.tobesaved[#lists.tobesaved+1] = l + -- default enhancer (cross referencing) + l.references.realpage = texcount.realpageno + -- specific enhancer (kind of obsolete) + local kind = l.metadata.kind + local enhancer = kind and lists.enhancers[kind] + if enhancer then + enhancer(l) + end + end +end + +-- we can use level instead but we can also decide to remove level from the metadata + +local nesting = { } + +function lists.pushnesting(i) + local r = lists.result[i] + local name = r.metadata.name + local numberdata = r and r.numberdata + local n = (numberdata and numberdata.numbers[sections.getlevel(name)]) or 0 + insert(nesting, { number = n, name = name, result = lists.result }) +end + +function lists.popnesting() + local old = remove(nesting) + lists.result = old.result +end + +local function filter_collected(names, criterium, number, collected) + local numbers, depth = documents.data.numbers, documents.data.depth + local hash, result, all = { }, { }, not names or names == "" or names == variables.all + if not all then + for s in names:gmatch("[^, ]+") do + hash[s] = true + end + end + if criterium == variables.all or criterium == variables.text then + for i=1,#collected do + local v = collected[i] + local r = v.references + if r then + local sectionnumber = (r.section == 0) or jobsections.collected[r.section] + if sectionnumber then -- and not sectionnumber.hidenumber then + local metadata = v.metadata + if metadata and not metadata.nolist and (all or hash[metadata.name or false]) then + result[#result+1] = v + end + end + end + end + elseif criterium == variables.current then + for i=1,#collected do + local v = collected[i] + local r = v.references + if r then + local sectionnumber = jobsections.collected[r.section] + if sectionnumber then -- and not sectionnumber.hidenumber then + local cnumbers = sectionnumber.numbers + local metadata = v.metadata + if cnumbers then + if metadata and not metadata.nolist and (all or hash[metadata.name or false]) 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 + result[#result+1] = v + end + end + end + end + end + end + elseif criterium == variables.here then + for i=1,#collected do + local v = collected[i] + local r = v.references + if r then + local sectionnumber = jobsections.collected[r.section] + if sectionnumber then -- and not sectionnumber.hidenumber then + local cnumbers = sectionnumber.numbers + local metadata = v.metadata + if cnumbers then + if metadata and not metadata.nolist and (all or hash[metadata.name or false]) 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 + result[#result+1] = v + end + end + end + end + end + end + elseif criterium == variables.previous then + for i=1,#collected do + local v = collected[i] + local r = v.references + if r then + local sectionnumber = jobsections.collected[r.section] + if sectionnumber then -- and not sectionnumber.hidenumber then + local cnumbers = sectionnumber.numbers + local metadata = v.metadata + if cnumbers then + if metadata and not metadata.nolist and (all or hash[metadata.name or false]) and #cnumbers >= depth then + local ok = true + for d=1,depth-1 do + local cnd = cnumbers[d] + if not (cnd == 0 or cnd == numbers[d]) then + ok = false + break + end + end + if ok then + result[#result+1] = v + end + end + end + end + end + end + elseif criterium == variables["local"] then -- not yet ok + local nested = nesting[#nesting] + if nested then + return filter_collected(names,nested.name,nested.number,collected) + elseif sections.autodepth(documents.data.numbers) == 0 then + return filter_collected(names,variables.all,number,collected) + else + return filter_collected(names,variables.current,number,collected) + end + else -- sectionname, number + local depth = sections.getlevel(criterium) + local number = tonumber(number) or 0 + for i=1,#collected do + local v = collected[i] + local r = v.references + if r then + local sectionnumber = jobsections.collected[r.section] + if sectionnumber then -- and not sectionnumber.hidenumber then + local cnumbers = sectionnumber.numbers + local metadata = v.metadata + if cnumbers then +-- if metadata and not metadata.nolist and (all or hash[metadata.name or false]) and #cnumbers >= depth and cnumbers[depth] == number then + if metadata and not metadata.nolist and (all or hash[metadata.name or false]) and #cnumbers >= depth and (number == 0 or cnumbers[depth] == number) then + result[#result+1] = v + end + end + end + end + end + end + return result +end + +lists.filter_collected = filter_collected + +function lists.filter(names, criterium, number) + return filter_collected(names, criterium, number, lists.collected) +end + +lists.result = { } + +function lists.process(...) + lists.result = lists.filter(...) + for i=1,#lists.result do + local r = lists.result[i] + local m = r.metadata + texsprint(ctxcatcodes,format("\\processlistofstructure{%s}{%s}{%i}",m.name,m.kind,i)) + end +end + +function lists.analyze(...) + lists.result = lists.filter(...) +end + +function lists.userdata(name,r,tag) -- to tex + local str = lists.result[r] + str = str and str.userdata + str = str and str[tag] + if str then + texsprint(ctxcatcodes,str) + end +end + +function lists.uservalue(name,r,tag,default) -- to lua + local str = lists.result[r] + str = str and str.userdata + str = str and str[tag] + return str or default +end + +function lists.size() + texprint(#lists.result) +end + +function lists.location(name,n) + local l = lists.result[n] + texsprint(l.references.internal or n) +end + +function lists.sectionnumber(name,n,spec) + local data = lists.result[n] + local sectiondata = jobsections.collected[data.references.section] + -- hm, prefixnumber? + sections.typesetnumber(sectiondata,"prefix",spec,sectiondata) -- data happens to contain the spec too +end + +-- some basics (todo: helpers for pages) + +function lists.title(name,n,tag) -- tag becomes obsolete + local data = lists.result[n] + if data then + local titledata = data.titledata + if titledata then + helpers.title(titledata[tag] or titledata.list or titledata.title or "",data.metadata) +--~ texsprint(ctxcatcodes,titledata[tag] or titledata.list or titledata.title or "") + end + end +end + +function lists.savedtitle(name,n,tag) + local data = cached[tonumber(n)] + if data then + local titledata = data.titledata + if titledata then + helpers.title(titledata[tag] or titledata.title or "",data.metadata) +--~ texsprint(ctxcatcodes,titledata[tag] or titledata.title or "") + end + end +end + +function lists.savednumber(name,n) + local data = cached[tonumber(n)] + if data then + local numberdata = data.numberdata + if numberdata then + sections.typesetnumber(numberdata,"number",numberdata or false) + end + end +end + +function lists.savedprefixednumber(name,n) + local data = cached[tonumber(n)] + if data then + helpers.prefix(data,data.prefixdata) + local numberdata = data.numberdata + if numberdata then + sections.typesetnumber(numberdata,"number",numberdata or false) + end + end +end + +function lists.prefix(name,n,spec) + helpers.prefix(lists.result[n],spec) +end + +function lists.page(name,n,pagespec) + helpers.page(lists.result[n],pagespec) +end + +function lists.prefixedpage(name,n,prefixspec,pagespec) + helpers.prefixpage(lists.result[n],prefixspec,pagespec) +end + +function lists.realpage(name,n) + local data = lists.result[n] + if data then + local references = data.references + texsprint(references and references.realpage or 0) + else + texsprint(0) + end +end + +-- numbers stored in entry.numberdata + entry.numberprefix + +function lists.number(name,n,spec) + local data = lists.result[n] + if data then + local numberdata = data.numberdata + if numberdata then + sections.typesetnumber(numberdata,"number",spec or false,numberdata or false) + end + end +end + +function lists.prefixednumber(name,n,prefixspec,numberspec) + local data = lists.result[n] + if data then + helpers.prefix(data,prefixspec) + local numberdata = data.numberdata + if numberdata then + sections.typesetnumber(numberdata,"number",spec or false,numberdata or false) + end + end +end |