summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/strc-ref.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/strc-ref.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ref.lua866
1 files changed, 657 insertions, 209 deletions
diff --git a/Master/texmf-dist/tex/context/base/strc-ref.lua b/Master/texmf-dist/tex/context/base/strc-ref.lua
index 3f2c0608d2a..b6f2e9a3778 100644
--- a/Master/texmf-dist/tex/context/base/strc-ref.lua
+++ b/Master/texmf-dist/tex/context/base/strc-ref.lua
@@ -53,6 +53,7 @@ local v_auto = variables.auto
local context = context
local commands = commands
+local implement = interfaces.implement
local texgetcount = tex.getcount
local texsetcount = tex.setcount
@@ -76,6 +77,8 @@ local references = structures.references
local lists = structures.lists
local counters = structures.counters
+local jobpositions = job.positions
+
-- some might become local
references.defined = references.defined or allocate()
@@ -83,6 +86,7 @@ references.defined = references.defined or allocate()
local defined = references.defined
local derived = allocate()
local specials = allocate()
+local functions = allocate()
local runners = allocate()
local internals = allocate()
local filters = allocate()
@@ -98,6 +102,7 @@ local usedviews = allocate()
references.derived = derived
references.specials = specials
+references.functions = functions
references.runners = runners
references.internals = internals
references.filters = filters
@@ -123,7 +128,7 @@ local context_delayed = context.delayed
local ctx_pushcatcodes = context.pushcatcodes
local ctx_popcatcodes = context.popcatcodes
-local ctx_dofinishsomereference = context.dofinishsomereference
+local ctx_dofinishreference = context.dofinishreference
local ctx_dofromurldescription = context.dofromurldescription
local ctx_dofromurlliteral = context.dofromurlliteral
local ctx_dofromfiledescription = context.dofromfiledescription
@@ -339,8 +344,8 @@ local function setcomponent(data)
local references = data and data.references
if references then
references.component = component
- if references.referenceprefix == component then
- references.referenceprefix = nil
+ if references.prefix == component then
+ references.prefix = nil
end
end
return component
@@ -353,15 +358,32 @@ references.setnextinternal = setnextinternal
references.currentorder = currentorder
references.setcomponent = setcomponent
-commands.setnextreferenceorder = setnextorder
-commands.setnextinternalreference = setnextinternal
+implement {
+ name = "setnextreferenceorder",
+ actions = setnextorder,
+ arguments = { "string", "string" }
+}
-function commands.currentreferenceorder(kind,name)
- context(currentorder(kind,name))
-end
+implement {
+ name = "setnextinternalreference",
+ actions = setnextinternal,
+ arguments = { "string", "string" }
+}
+
+implement {
+ name = "currentreferenceorder",
+ actions = { currentorder, context },
+ arguments = { "string", "string" }
+}
-function references.set(kind,prefix,tag,data)
--- setcomponent(data)
+function references.set(data)
+ local references = data.references
+ local prefix = references.prefix or ""
+ local reference = references.reference
+ if not reference or reference == "" then
+ report_references("invalid reference")
+ return 0
+ end
local pd = tobesaved[prefix] -- nicer is a metatable
if not pd then
pd = { }
@@ -380,21 +402,44 @@ function references.set(kind,prefix,tag,data)
else
n = n + 1
pd[ref] = data
- ctx_dofinishsomereference(kind,prefix,ref)
+ local r = data.references
+ ctx_dofinishreference(prefix or "",ref or "",r and r.internal or 0)
end
end
- process_settings(tag,action)
+ process_settings(reference,action)
return n > 0
end
+-- function references.enhance(prefix,tag)
+-- local l = tobesaved[prefix][tag]
+-- if l then
+-- l.references.realpage = texgetcount("realpageno")
+-- end
+-- end
+
+local getpos = function() getpos = backends.codeinjections.getpos return getpos () end
+
+local function synchronizepage(reference) -- non public helper
+ reference.realpage = texgetcount("realpageno")
+ if jobpositions.used then
+ reference.x, reference.y = getpos()
+ end
+end
+
+references.synchronizepage = synchronizepage
+
function references.enhance(prefix,tag)
local l = tobesaved[prefix][tag]
if l then
- l.references.realpage = texgetcount("realpageno")
+ synchronizepage(l.references)
end
end
-commands.enhancereference = references.enhance
+implement {
+ name = "enhancereference",
+ actions = references.enhance,
+ arguments = { "string", "string" }
+}
-- -- -- related to strc-ini.lua -- -- --
@@ -402,15 +447,34 @@ commands.enhancereference = references.enhance
local function register_from_lists(collected,derived,pages,sections)
local derived_g = derived[""] -- global
+ local derived_p = nil
+ local derived_c = nil
+ local prefix = nil
+ local component = nil
+ local entry = nil
if not derived_g then
derived_g = { }
derived[""] = derived_g
end
+ local function action(s)
+ if trace_referencing then
+ report_references("list entry %a provides %a reference %a on realpage %a",i,kind,s,realpage)
+ end
+ if derived_p and not derived_p[s] then
+ derived_p[s] = entry
+ end
+ if derived_c and not derived_c[s] then
+ derived_c[s] = entry
+ end
+ if not derived_g[s] then
+ derived_g[s] = entry -- first wins
+ end
+ end
for i=1,#collected do
- local entry = collected[i]
+ entry = collected[i]
local metadata = entry.metadata
if metadata then
- local kind = metadata.kind
+ local kind = metadata.kind -- why this check
if kind then
local references = entry.references
if references then
@@ -418,10 +482,8 @@ local function register_from_lists(collected,derived,pages,sections)
if reference and reference ~= "" then
local realpage = references.realpage
if realpage then
- local prefix = references.referenceprefix
- local component = references.component
- local derived_p = nil
- local derived_c = nil
+ prefix = references.prefix
+ component = references.component
if prefix and prefix ~= "" then
derived_p = derived[prefix]
if not derived_p then
@@ -436,20 +498,6 @@ local function register_from_lists(collected,derived,pages,sections)
derived[component] = derived_c
end
end
- local function action(s)
- if trace_referencing then
- report_references("list entry %a provides %a reference %a on realpage %a",i,kind,s,realpage)
- end
- if derived_p and not derived_p[s] then
- derived_p[s] = entry
- end
- if derived_c and not derived_c[s] then
- derived_c[s] = entry
- end
- if not derived_g[s] then
- derived_g[s] = entry -- first wins
- end
- end
process_settings(reference,action)
end
end
@@ -462,6 +510,78 @@ end
references.registerinitializer(function() register_from_lists(lists.collected,derived) end)
+-- tracing
+
+local function collectbypage(tracedpages)
+ -- lists
+ do
+ local collected = structures.lists.collected
+ local data = nil
+ local function action(reference)
+ local prefix = data.prefix
+ local component = data.component
+ local realpage = data.realpage
+ if realpage then
+ local pagelist = rawget(tracedpages,realpage)
+ local internal = data.internal or 0
+ local prefix = (prefix ~= "" and prefix) or (component ~= "" and component) or ""
+ local pagedata = { prefix, reference, internal }
+ if pagelist then
+ pagelist[#pagelist+1] = pagedata
+ else
+ tracedpages[realpage] = { pagedata }
+ end
+ if internal > 0 then
+ data.usedprefix = prefix
+ end
+ end
+ end
+ for i=1,#collected do
+ local entry = collected[i]
+ local metadata = entry.metadata
+ if metadata and metadata.kind then
+ data = entry.references
+ if data then
+ local reference = data.reference
+ if reference and reference ~= "" then
+ process_settings(reference,action)
+ end
+ end
+ end
+ end
+ end
+ -- references
+ do
+ for prefix, list in next, collected do
+ for reference, entry in next, list do
+ local data = entry.references
+ if data then
+ local realpage = data.realpage
+ local internal = data.internal or 0
+ local pagelist = rawget(tracedpages,realpage)
+ local pagedata = { prefix, reference, internal }
+ if pagelist then
+ pagelist[#pagelist+1] = pagedata
+ else
+ tracedpages[realpage] = { pagedata }
+ end
+ if internal > 0 then
+ data.usedprefix = prefix
+ end
+ end
+ end
+ end
+ end
+end
+
+references.tracedpages = table.setmetatableindex(allocate(),function(t,k)
+ if collectbypage then
+ collectbypage(t)
+ collectbypage = nil
+ end
+ return rawget(t,k)
+end)
+
-- urls
local urls = references.urls or { }
@@ -487,7 +607,11 @@ function urls.get(name)
end
end
-function commands.geturl(name)
+function urls.found(name)
+ return urldata[name]
+end
+
+local function geturl(name)
local url = urls.get(name)
if url and url ~= "" then
ctx_pushcatcodes(txtcatcodes)
@@ -496,18 +620,23 @@ function commands.geturl(name)
end
end
--- function commands.gethyphenatedurl(name,...)
--- local url = urls.get(name)
--- if url and url ~= "" then
--- hyphenatedurl(url,...)
--- end
--- end
+implement {
+ name = "doifelseurldefined",
+ actions = { urls.found, commands.doifelse },
+ arguments = "string"
+}
-function commands.doifurldefinedelse(name)
- commands.doifelse(urldata[name])
-end
+implement {
+ name = "useurl",
+ actions = urls.define,
+ arguments = { "string", "string", "string", "string" }
+}
-commands.useurl= urls.define
+implement {
+ name = "geturl",
+ actions = geturl,
+ arguments = "string",
+}
-- files
@@ -529,11 +658,36 @@ function files.get(name,method,space) -- method: none, before, after, both, spac
end
end
-function commands.doiffiledefinedelse(name)
- commands.doifelse(filedata[name])
+function files.found(name)
+ return filedata[name]
+end
+
+local function getfile(name)
+ local fil = files.get(name)
+ if fil and fil ~= "" then
+ ctx_pushcatcodes(txtcatcodes)
+ context(fil)
+ ctx_popcatcodes()
+ end
end
-commands.usefile= files.define
+implement {
+ name = "doifelsefiledefined",
+ actions = { files.found, commands.doifelse },
+ arguments = "string"
+}
+
+implement {
+ name = "usefile",
+ actions = files.define,
+ arguments = { "string", "string", "string" }
+}
+
+implement {
+ name = "getfile",
+ actions = getfile,
+ arguments = "string"
+}
-- helpers
@@ -613,20 +767,30 @@ function references.checkedprogram(whatever) -- return whatever if not resolved
end
end
-commands.defineprogram = programs.define
+implement {
+ name = "defineprogram",
+ actions = programs.define,
+ arguments = { "string", "string", "string" }
+}
-function commands.getprogram(name)
- local f = programdata[name]
- if f then
- context(f[1])
+local function getprogram(name)
+ local p = programdata[name]
+ if p then
+ context(p[1])
end
end
+implement {
+ name = "getprogram",
+ actions = getprogram,
+ arguments = "string"
+}
+
-- shared by urls and files
-function references.whatfrom(name)
- context((urldata[name] and v_url) or (filedata[name] and v_file) or v_unknown)
-end
+-- function references.whatfrom(name)
+-- context((urldata[name] and v_url) or (filedata[name] and v_file) or v_unknown)
+-- end
function references.from(name)
local u = urldata[name]
@@ -653,7 +817,7 @@ function references.from(name)
end
end
-function commands.from(name)
+local function from(name)
local u = urldata[name]
if u then
local url, file, description = u[1], u[2], u[3]
@@ -678,6 +842,12 @@ function commands.from(name)
end
end
+implement {
+ name = "from",
+ actions = from,
+ arguments = "string"
+}
+
function references.define(prefix,reference,list)
local d = defined[prefix] if not d then d = { } defined[prefix] = d end
d[reference] = list
@@ -690,86 +860,17 @@ function references.reset(prefix,reference)
end
end
-commands.definereference = references.define
-commands.resetreference = references.reset
-
--- \primaryreferencefoundaction
--- \secondaryreferencefoundaction
--- \referenceunknownaction
-
--- t.special t.operation t.arguments t.outer t.inner
-
--- to what extend do we check the non prefixed variant
+implement {
+ name = "definereference",
+ actions = references.define,
+ arguments = { "string", "string", "string" }
+}
--- local strict = false
---
--- local function resolve(prefix,reference,args,set) -- we start with prefix,reference
--- if reference and reference ~= "" then
--- if not set then
--- set = { prefix = prefix, reference = reference }
--- else
--- if not set.reference then set.reference = reference end
--- if not set.prefix then set.prefix = prefix end
--- end
--- local r = settings_to_array(reference)
--- for i=1,#r do
--- local ri = r[i]
--- local d
--- if strict then
--- d = defined[prefix] or defined[""]
--- d = d and d[ri]
--- else
--- d = defined[prefix]
--- d = d and d[ri]
--- if not d then
--- d = defined[""]
--- d = d and d[ri]
--- end
--- end
--- if d then
--- resolve(prefix,d,nil,set)
--- else
--- local var = splitreference(ri)
--- if var then
--- var.reference = ri
--- local vo, vi = var.outer, var.inner
--- if not vo and vi then
--- -- to be checked
--- if strict then
--- d = defined[prefix] or defined[""]
--- d = d and d[vi]
--- else
--- d = defined[prefix]
--- d = d and d[vi]
--- if not d then
--- d = defined[""]
--- d = d and d[vi]
--- end
--- end
--- --
--- if d then
--- resolve(prefix,d,var.arguments,set) -- args can be nil
--- else
--- if args then var.arguments = args end
--- set[#set+1] = var
--- end
--- else
--- if args then var.arguments = args end
--- set[#set+1] = var
--- end
--- if var.has_tex then
--- set.has_tex = true
--- end
--- else
--- -- report_references("funny pattern %a",ri)
--- end
--- end
--- end
--- return set
--- else
--- return { }
--- end
--- end
+implement {
+ name = "resetreference",
+ actions = references.reset,
+ arguments = { "string", "string" }
+}
setmetatableindex(defined,"table")
@@ -824,11 +925,11 @@ end
references.currentset = nil
-function commands.setreferenceoperation(k,v)
+local function setreferenceoperation(k,v)
references.currentset[k].operation = v
end
-function commands.setreferencearguments(k,v)
+local function setreferencearguments(k,v)
references.currentset[k].arguments = v
end
@@ -849,7 +950,22 @@ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex
end
end
-commands.expandcurrentreference = references.expandcurrent -- for the moment the same
+implement {
+ name = "expandcurrentreference",
+ actions = references.expandcurrent
+}
+
+implement {
+ name = "setreferenceoperation",
+ actions = setreferenceoperation,
+ arguments = { "integer", "string" }
+}
+
+implement {
+ name = "setreferencearguments",
+ actions = setreferencearguments,
+ arguments = { "integer", "string" }
+}
local externals = { }
@@ -893,7 +1009,7 @@ local function loadexternalreferences(name,utilitydata)
local realpage = references.realpage
if kind and realpage then
references.pagedata = pages[realpage]
- local prefix = references.referenceprefix or ""
+ local prefix = references.prefix or ""
local target = external[prefix]
if not target then
target = { }
@@ -995,7 +1111,7 @@ local function loadproductreferences(productname,componentname,utilitydata)
local realpage = references.realpage
if kind and realpage then
references.pagedata = pages[realpage]
- local prefix = references.referenceprefix or ""
+ local prefix = references.prefix or ""
local component = references.component
local ctarget, ptarget
if not component or component == componentname then
@@ -1141,7 +1257,7 @@ local useproduct = commands.useproduct
if useproduct then
- function commands.useproduct(product)
+ local function newuseproduct(product)
useproduct(product)
if texconditionals.autocrossfilereferences then
local component = justacomponent()
@@ -1154,6 +1270,13 @@ if useproduct then
end
end
+ implement {
+ name = "useproduct",
+ actions = newuseproduct,
+ arguments = "string",
+ overload = true,
+ }
+
end
-- productdata.firstsection.numberdata.numbers
@@ -1648,7 +1771,11 @@ local function identify(prefix,reference)
set.n = nofidentified
for i=1,#set do
local var = set[i]
- if var.special then
+ local spe = var.special
+ local fnc = functions[spe]
+ if fnc then
+ var = fnc(var) or { error = "invalid special function" }
+ elseif spe then
var = identify_special(set,var,i)
elseif var.outer then
var = identify_outer(set,var,i)
@@ -1675,7 +1802,7 @@ references.identify = identify
local unknowns, nofunknowns, f_valid = { }, 0, formatters["[%s][%s]"]
-function references.valid(prefix,reference,highlight,newwindow,layer)
+function references.valid(prefix,reference,specification)
local set, bug = identify(prefix,reference)
local unknown = bug or #set == 0
if unknown then
@@ -1690,16 +1817,28 @@ function references.valid(prefix,reference,highlight,newwindow,layer)
unknowns[str] = u + 1
end
else
- set.highlight, set.newwindow, set.layer = highlight, newwindow, layer
+ set.highlight = specification.highlight
+ set.newwindow = specification.newwindow
+ set.layer = specification.layer
currentreference = set[1]
end
-- we can do the expansion here which saves a call
return not unknown
end
-function commands.doifelsereference(prefix,reference,highlight,newwindow,layer)
- commands.doifelse(references.valid(prefix,reference,highlight,newwindow,layer))
-end
+implement {
+ name = "doifelsereference",
+ actions = { references.valid, commands.doifelse },
+ arguments = {
+ "string",
+ "string",
+ {
+ { "highlight", "boolean" },
+ { "newwindow", "boolean" },
+ { "layer" },
+ }
+ }
+}
function references.reportproblems() -- might become local
if nofunknowns > 0 then
@@ -1742,6 +1881,13 @@ function references.setinnermethod(m)
end
end
+implement {
+ name = "setinnerreferencemethod",
+ actions = references.setinnermethod,
+ arguments = "string",
+ onlyonce = true
+}
+
function references.getinnermethod()
return innermethod or defaultinnermethod
end
@@ -1754,24 +1900,27 @@ end)
local destinationattributes = { }
-local function setinternalreference(prefix,tag,internal,view) -- needs checking
+local function setinternalreference(specification)
+ local internal = specification.internal
local destination = unsetvalue
if innermethod == v_auto then
- local t, tn = { }, 0 -- maybe add to current
- if tag then
+ local t, tn = { }, 0 -- maybe add to current (now only used for tracing)
+ local reference = specification.reference
+ if reference then
+ local prefix = specification.prefix
if prefix and prefix ~= "" then
prefix = prefix .. ":" -- watch out, : here
local function action(ref)
tn = tn + 1
t[tn] = prefix .. ref
end
- process_settings(tag,action)
+ process_settings(reference,action)
else
local function action(ref)
tn = tn + 1
t[tn] = ref
end
- process_settings(tag,action)
+ process_settings(reference,action)
end
end
-- ugly .. later we decide to ignore it when we have a real one
@@ -1780,7 +1929,7 @@ local function setinternalreference(prefix,tag,internal,view) -- needs checking
tn = tn + 1
t[tn] = internal -- when number it's internal
end
- destination = references.mark(t,nil,nil,view) -- returns an attribute
+ destination = references.mark(t,nil,nil,specification.view) -- returns an attribute
end
if internal then -- new
destinationattributes[internal] = destination
@@ -1795,16 +1944,103 @@ end
references.setinternalreference = setinternalreference
references.getinternalreference = getinternalreference
-commands.setinternalreference = setinternalreference
-commands.getinternalreference = getinternalreference
-function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do internal automatically here
- local attr = references.set(kind,prefix,tag,data) and setinternalreference(prefix,tag,nil,view) or unsetvalue
+implement {
+ name = "setinternalreference",
+ actions = setinternalreference,
+ arguments = {
+ {
+ { "prefix" },
+ { "reference" },
+ { "internal", "integer" },
+ { "view" }
+ }
+ }
+}
+
+-- implement {
+-- name = "getinternalreference",
+-- actions = { getinternalreference, context },
+-- arguments = "integer",
+-- }
+
+function references.setandgetattribute(data) -- maybe do internal automatically here
+ local attr = unsetvalue
+ local mdat = data.metadata
+ local rdat = data.references
+ if mdat and rdat then
+ if not rdat.section then
+ rdat.section = structures.sections.currentid()
+ end
+ local ndat = data.numberdata
+ if ndat then
+ local numbers = ndat.numbers
+ if type(numbers) == "string" then
+ ndat.numbers = counters.compact(numbers,nil,true)
+ end
+ data.numberdata = helpers.simplify(ndat)
+ end
+ local pdat = data.prefixdata
+ if pdat then
+ data.prefixdata = helpers.simplify(pdat)
+ end
+ local udat = data.userdata
+ if type(udat) == "string" then
+ data.userdata = helpers.touserdata(udat)
+ end
+ if not rdat.block then
+ rdat.block = structures.sections.currentblock()
+ end
+ local done = references.set(data) -- we had kind i.e .item -> full
+ if done then
+ attr = setinternalreference {
+ prefix = prefix,
+ reference = tag,
+ internal = rdat.internal,
+ view = rdat.view
+ } or unsetvalue
+ end
+ end
texsetcount("lastdestinationattribute",attr)
return attr
end
-commands.setreferenceattribute = references.setandgetattribute
+implement {
+ name = "setreferenceattribute",
+ actions = references.setandgetattribute,
+ arguments = {
+ {
+ {
+ "references", {
+ { "internal", "integer" },
+ { "block" },
+ { "view" },
+ { "prefix" },
+ { "reference" },
+ },
+ },
+ {
+ "metadata", {
+ { "kind" },
+ { "xmlroot" },
+ { "catcodes", "integer" },
+ },
+ },
+ {
+ "prefixdata", { "*" }
+ },
+ {
+ "numberdata", { "*" }
+ },
+ {
+ "entries", { "*" }
+ },
+ {
+ "userdata"
+ }
+ }
+ }
+}
function references.getinternallistreference(n) -- n points into list (todo: registers)
local l = lists.collected[n]
@@ -1812,11 +2048,11 @@ function references.getinternallistreference(n) -- n points into list (todo: reg
return i and destinationattributes[i] or 0
end
-function commands.getinternallistreference(n) -- this will also be a texcount
- local l = lists.collected[n]
- local i = l and l.references.internal
- context(i and destinationattributes[i] or 0)
-end
+implement {
+ name = "getinternallistreference",
+ actions = { references.getinternallistreference, context },
+ arguments = "integer"
+}
--
@@ -1825,12 +2061,11 @@ function references.getcurrentmetadata(tag)
return data and data.metadata and data.metadata[tag]
end
-function commands.getcurrentreferencemetadata(tag)
- local data = references.getcurrentmetadata(tag)
- if data then
- context(data)
- end
-end
+implement {
+ name = "getcurrentreferencemetadata",
+ actions = { references.getcurrentmetadata, context },
+ arguments = "string",
+}
local function currentmetadata(tag)
local data = currentreference and currentreference.i
@@ -1840,15 +2075,29 @@ end
references.currentmetadata = currentmetadata
local function getcurrentprefixspec(default)
- -- todo: message
- return currentmetadata("kind") or "?", currentmetadata("name") or "?", default or "?"
+ local data = currentreference and currentreference.i
+ local metadata = data and data.metadata
+ return
+ metatadata and metadata.kind or "?",
+ metatadata and metadata.name or "?",
+ default or "?"
end
references.getcurrentprefixspec = getcurrentprefixspec
-function commands.getcurrentprefixspec(default)
- ctx_getreferencestructureprefix(getcurrentprefixspec(default))
-end
+-- implement {
+-- name = "getcurrentprefixspec",
+-- actions = { getcurrentprefixspec, context }, -- returns 3 arguments
+-- arguments = "string",
+-- }
+
+implement {
+ name = "getcurrentprefixspec",
+ actions = function(tag)
+ context("{%s}{%s}{%s}",getcurrentprefixspec(tag))
+ end,
+ arguments = "string",
+}
local genericfilters = { }
local userfilters = { }
@@ -1862,12 +2111,12 @@ filters.text = textfilters
filters.full = fullfilters
filters.section = sectionfilters
-local function filterreference(name,...) -- number page title ...
+local function filterreference(name,prefixspec,numberspec) -- number page title ...
local data = currentreference and currentreference.i -- maybe we should take realpage from here
if data then
if name == "realpage" then
local cs = references.analyze() -- normally already analyzed but also sets state
- context(tonumber(cs.realpage) or 0) -- todo, return and in command namespace
+ context(tonumber(cs.realpage) or 0)
else -- assumes data is table
local kind = type(data) == "table" and data.metadata and data.metadata.kind
if kind then
@@ -1877,7 +2126,7 @@ local function filterreference(name,...) -- number page title ...
if trace_referencing then
report_references("name %a, kind %a, using dedicated filter",name,kind)
end
- filter(data,name,...)
+ filter(data,name,prefixspec,numberspec)
elseif trace_referencing then
report_references("name %a, kind %a, using generic filter",name,kind)
end
@@ -1893,21 +2142,27 @@ local function filterreference(name,...) -- number page title ...
end
local function filterreferencedefault()
- return filterreference("default",getcurrentprefixspec(v_default))
+ return filterreference("default",getcurrentprefixspec("default"))
end
references.filter = filterreference
references.filterdefault = filterreferencedefault
-commands.filterreference = filterreference
-commands.filterdefaultreference = filterreferencedefault
+implement {
+ name = "filterreference",
+ actions = filterreference,
+ arguments = "string",
+}
-function commands.currentreferencedefault(tag)
- if not tag then
- tag = "default"
- end
- filterreference(tag,context_delayed(getcurrentprefixspec(tag)))
-end
+implement {
+ name = "filterdefaultreference",
+ actions = filterreference,
+ arguments = {
+ "string", -- 'default'
+ { { "*" } }, -- prefixspec
+ { { "*" } }, -- numberspec
+ }
+}
function genericfilters.title(data)
if data then
@@ -1927,12 +2182,12 @@ function genericfilters.text(data)
end
end
-function genericfilters.number(data,what,prefixspec) -- todo: spec and then no stopper
+function genericfilters.number(data,what,prefixspec,numberspec)
if data then
numberdata = lists.reordered(data) -- data.numberdata
if numberdata then
helpers.prefix(data,prefixspec)
- sections.typesetnumber(numberdata,"number",numberdata)
+ sections.typesetnumber(numberdata,"number",numberspec,numberdata)
else
local useddata = data.useddata
if useddata and useddata.number then
@@ -2056,12 +2311,71 @@ local specials = references.testspecials
-- pretty slow (progressively). In the pagebody one can best check the reference
-- real page to determine if we need contrastlocation as that is more lightweight.
-local function checkedpagestate(n,page)
- local r = referredpage(n)
+local function checkedpagestate(n,page,actions,position,spread)
local p = tonumber(page)
if not p then
return 0
- elseif p > r then
+ end
+ if position and #actions > 0 then
+ local i = actions[1].i -- brrr
+ if i then
+ local a = i.references
+ if a then
+ local x = a.x
+ local y = a.y
+ if x and y then
+ local jp = jobpositions.collected[position]
+ if jp then
+ local px = jp.x
+ local py = jp.y
+ local pp = jp.p
+ if p == pp then
+ -- same page
+ if py > y then
+ return 5 -- above
+ elseif py < y then
+ return 4 -- below
+ elseif px > x then
+ return 4 -- below
+ elseif px < x then
+ return 5 -- above
+ else
+ return 1 -- same
+ end
+ elseif spread then
+ if pp % 2 == 0 then
+ -- left page
+ if pp > p then
+ return 2 -- before
+ elseif pp + 1 == p then
+-- return 4 -- below (on right page)
+ return 5 -- above (on left page)
+ else
+ return 3 -- after
+ end
+ else
+ -- right page
+ if pp < p then
+ return 3 -- after
+ elseif pp - 1 == p then
+-- return 5 -- above (on left page)
+ return 4 -- below (on right page)
+ else
+ return 2 -- before
+ end
+ end
+ elseif pp > p then
+ return 2 -- before
+ else
+ return 3 -- after
+ end
+ end
+ end
+ end
+ end
+ end
+ local r = referredpage(n) -- sort of obsolete
+ if p > r then
return 3 -- after
elseif p < r then
return 2 -- before
@@ -2100,11 +2414,13 @@ local function setreferencerealpage(actions)
end
end
+references.setreferencerealpage = setreferencerealpage
+
-- we store some analysis data alongside the indexed array
-- at this moment only the real reference page is analyzed
-- normally such an analysis happens in the backend code
-function references.analyze(actions)
+function references.analyze(actions,position,spread)
if not actions then
actions = references.currentset
end
@@ -2119,32 +2435,56 @@ function references.analyze(actions)
elseif actions.external then
actions.pagestate = 0
else
- actions.pagestate = checkedpagestate(actions.n,realpage)
+ actions.pagestate = checkedpagestate(actions.n,realpage,actions,position,spread)
end
end
return actions
end
-function commands.referencepagestate(actions)
- if not actions then
- actions = references.currentset
- end
+local function referencepagestate(position,detail,spread)
+ local actions = references.currentset
if not actions then
- context(0)
+ return 0
else
if not actions.pagestate then
- references.analyze(actions) -- delayed unless explicitly asked for
--- print("NO STATE",actions.reference,actions.pagestate)
+ references.analyze(actions,position,spread) -- delayed unless explicitly asked for
+ end
+ local pagestate = actions.pagestate
+ if detail then
+ return pagestate
+ elseif pagestate == 4 then
+ return 2 -- compatible
+ elseif pagestate == 5 then
+ return 3 -- compatible
+ else
+ return pagestate
end
- context(actions.pagestate)
end
end
-function commands.referencerealpage(actions)
+implement {
+ name = "referencepagestate",
+ actions = { referencepagestate, context },
+ arguments = "string"
+}
+
+implement {
+ name = "referencepagedetail",
+ actions = { referencepagestate, context },
+ arguments = { "string", "boolean", "boolean" }
+}
+
+local function referencerealpage(actions)
actions = actions or references.currentset
- context(not actions and 0 or actions.realpage or setreferencerealpage(actions))
+ return not actions and 0 or actions.realpage or setreferencerealpage(actions)
end
+implement {
+ name = "referencerealpage",
+ actions = { referencerealpage, context },
+ arguments = "string"
+}
+
local plist, nofrealpages
local function realpageofpage(p) -- the last one counts !
@@ -2281,6 +2621,102 @@ function specials.section(var,actions)
end
end
+-- experimental:
+
+local p_splitter = lpeg.splitat(":")
+local p_lower = lpeg.patterns.utf8lower
+
+-- We can cache lowercased titles which saves a lot of time, but then
+-- we can better have a global cache with weak keys.
+
+-- local lowercache = table.setmetatableindex(function(t,k)
+-- local v = lpegmatch(p_lower,k)
+-- t[k] = v
+-- return v
+-- end)
+
+local lowercache = false
+
+local function locate(list,askedkind,askedname,pattern)
+ local kinds = lists.kinds
+ local names = lists.names
+ if askedkind and not kinds[askedkind] then
+ return false
+ end
+ if askedname and not names[askedname] then
+ return false
+ end
+ for i=1,#list do
+ local entry = list[i]
+ local metadata = entry.metadata
+ if metadata then
+ local found = false
+ if askedname then
+ local name = metadata.name
+ if name then
+ found = name == askedname
+ end
+ elseif askedkind then
+ local kind = metadata.kind
+ if kind then
+ found = kind == askedkind
+ end
+ end
+ if found then
+ local titledata = entry.titledata
+ if titledata then
+ local title = titledata.title
+ if title then
+ if lowercache then
+ found = lpegmatch(pattern,lowercache[title])
+ else
+ found = lpegmatch(pattern,lpegmatch(p_lower,title))
+ end
+ if found then
+ return {
+ inner = pattern,
+ kind = "inner",
+ reference = pattern,
+ i = entry,
+ p = "",
+ r = entry.references.realpage,
+ }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function functions.match(var,actions)
+ if not var.outer then
+ local operation = var.operation
+ if operation and operation ~= "" then
+ local operation = lpegmatch(p_lower,operation)
+ local list = lists.collected
+ local names = false
+ local kinds = false
+ local where, what = lpegmatch(p_splitter,operation)
+ if where and what then
+ local pattern = lpeg.finder(what)
+ return
+ locate(list,false,where,pattern)
+ or locate(list,where,false,pattern)
+ or { error = "no match" }
+ else
+ local pattern = lpeg.finder(operation)
+ -- todo: don't look at section and float in last pass
+ return
+ locate(list,"section",false,pattern)
+ or locate(list,"float",false,pattern)
+ or locate(list,false,false,pattern)
+ or { error = "no match" }
+ end
+ end
+ end
+end
+
-- needs a better split ^^^
-- done differently now:
@@ -2289,24 +2725,36 @@ function references.export(usedname) end
function references.import(usedname) end
function references.load (usedname) end
-commands.exportreferences = references.export
+implement { name = "exportreferences", actions =references.export }
-- better done here .... we don't insert/remove, just use a pointer
local prefixstack = { "" }
local prefixlevel = 1
-function commands.pushreferenceprefix(prefix)
+local function pushreferenceprefix(prefix)
prefixlevel = prefixlevel + 1
prefixstack[prefixlevel] = prefix
- context(prefix)
+ return prefix
end
-function commands.popreferenceprefix()
+local function popreferenceprefix()
prefixlevel = prefixlevel - 1
if prefixlevel > 0 then
- context(prefixstack[prefixlevel])
+ return prefixstack[prefixlevel]
else
report_references("unable to pop referenceprefix")
+ return ""
end
end
+
+implement {
+ name = "pushreferenceprefix",
+ actions = { pushreferenceprefix, context }, -- we can use setmacro
+ arguments = "string",
+}
+
+implement {
+ name = "popreferenceprefix",
+ actions = { popreferenceprefix, context }, -- we can use setmacro
+}