diff options
Diffstat (limited to 'tex')
32 files changed, 1757 insertions, 1252 deletions
diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 28d46ee93..7d16f193e 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -186695,4 +186695,3 @@ characters.data={ unicodeslot=0xE01EF, }, } - diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index 20a06246e..df1d5f965 100644 --- a/tex/context/base/cont-new.mkii +++ b/tex/context/base/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2011.09.27 20:05} +\newcontextversion{2011.10.01 10:48} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 41106bfc6..e016a0439 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2011.09.27 20:05} +\newcontextversion{2011.10.01 10:48} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex 1347294c2..cc6037196 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png Binary files differindex 4fe6a22e5..b60bce49d 100644 --- a/tex/context/base/context-version.png +++ b/tex/context/base/context-version.png diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 454c8fcae..6992af5ef 100644 --- a/tex/context/base/context.mkii +++ b/tex/context/base/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2011.09.27 20:05} +\edef\contextversion{2011.10.01 10:48} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 0a44b2efb..5ff6de2ce 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2011.09.27 20:05} +\edef\contextversion{2011.10.01 10:48} %D For those who want to use this: @@ -186,6 +186,8 @@ \loadmarkfile{lang-def} \loadmarkfile{lang-wrd} % can be optional +\loadmkvifile{file-job} % why so late? + \loadmarkfile{symb-ini} \loadmarkfile{sort-ini} @@ -210,7 +212,7 @@ \loadmarkfile{strc-ren} \loadmarkfile{strc-xml} \loadmarkfile{strc-def} % might happen later -\loadmarkfile{strc-ref} +\loadmkvifile{strc-ref} \loadmarkfile{strc-reg} \loadmarkfile{strc-lev} % experiment @@ -259,7 +261,7 @@ %loadmarkfile{page-mar} % also commented code in anch-pgr.mkiv \loadmarkfile{typo-mar} -\loadmkvifile{file-job} % why so late? +% \loadmkvifile{file-job} % why so late? \loadmarkfile{buff-ini} \loadmarkfile{buff-ver} diff --git a/tex/context/base/core-def.mkiv b/tex/context/base/core-def.mkiv index b341dd91b..9022044d7 100644 --- a/tex/context/base/core-def.mkiv +++ b/tex/context/base/core-def.mkiv @@ -67,17 +67,9 @@ % temporary here: -\ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \dospecialin } \else \let\in \dospecialin \fi -\ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \dospecialat } \else \let\at \dospecialat \fi -\ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\dospecialabout} \else \let\about\dospecialabout \fi -\ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \dospecialfrom } \else \let\from \dospecialfrom \fi -\ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \dospecialabout} \else \let\over \dospecialabout \fi - \unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg} -% for the moment here - -\enablemode[*nofonts] +% might move to \everydump or even disappear: \nonknuthmode diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua index 1c0680ad8..f94b102bc 100644 --- a/tex/context/base/core-two.lua +++ b/tex/context/base/core-two.lua @@ -140,13 +140,13 @@ jobpasses.inlist = inlist -- interface -function commands.gettwopassdata (id) local r = get (id) if r then context(r) end end -function commands.getfirsttwopassdata(id) local r = first(id) if r then context(r) end end -function commands.getlasttwopassdata (id) local r = last (id) if r then context(r) end end -function commands.findtwopassdata (id) local r = find (id) if r then context(r) end end -function commands.gettwopassdatalist (id) local r = list (id) if r then context(r) end end -function commands.counttwopassdata (id) local r = count(id) if r then context(r) end end -function commands.checktwopassdata (id) local r = check(id) if r then context(r) end end +function commands.gettwopassdata (id) local r = get (id) if r then context(r) end end +function commands.getfirsttwopassdata(id) local r = first(id) if r then context(r) end end +function commands.getlasttwopassdata (id) local r = last (id) if r then context(r) end end +function commands.findtwopassdata (id,n) local r = find (id,n) if r then context(r) end end +function commands.gettwopassdatalist (id) local r = list (id) if r then context(r) end end +function commands.counttwopassdata (id) local r = count(id) if r then context(r) end end +function commands.checktwopassdata (id) local r = check(id) if r then context(r) end end commands.definetwopasslist = jobpasses.define commands.savetwopassdata = jobpasses.save diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua index 02411f13d..ca699d297 100644 --- a/tex/context/base/core-uti.lua +++ b/tex/context/base/core-uti.lua @@ -19,9 +19,11 @@ saves much runtime but at the cost of more memory usage.</p> local format, match = string.format, string.match local next, type, tostring = next, type, tostring +local concat = table.concat local definetable = utilities.tables.definetable local accesstable = utilities.tables.accesstable +local migratetable = utilities.tables.migratetable local serialize = table.serialize local packers = utilities.packers local allocate = utilities.storage.allocate @@ -32,7 +34,7 @@ local report_jobcontrol = logs.reporter("jobcontrol") job = job or { } local job = job -job.version = 1.14 +job.version = 1.15 -- some day we will implement loading of other jobs and then we need -- job.jobs @@ -66,7 +68,7 @@ end -- as an example we implement variables -local tobesaved, collected, checksums = allocate(), allocate(), allocate() +local tobesaved, collected, checksums = allocate(), allocate(), allocate() local jobvariables = { collected = collected, @@ -125,9 +127,9 @@ local jobpacker = packers.new(packlist,1.01) job.pack = true -local _save_, _load_ = { }, { } -- registers timing +local _save_, _load_, _others_ = { }, { }, { } -- registers timing -function job.save(filename) +function job.save(filename) -- we could return a table but it can get pretty large statistics.starttiming(_save_) local f = io.open(filename,'w') if f then @@ -135,9 +137,13 @@ function job.save(filename) f:write("-- ",comment[c],"\n") end f:write("\n") + f:write("local utilitydata = { }\n") + f:write("\n") for l=1,#savelist do - local list = savelist[l] - local target, data, finalizer = list[1], list[2], list[4] + local list = savelist[l] + local target = format("utilitydata.%s",list[1]) + local data = list[2] + local finalizer = list[4] if type(finalizer) == "function" then finalizer() end @@ -149,15 +155,17 @@ function job.save(filename) end if job.pack then packers.strip(jobpacker) - f:write(serialize(jobpacker,"job.packed",true,true),"\n") + f:write(serialize(jobpacker,"utilitydata.job.packed",true,true),"\n") end + f:write("\n") + f:write("return utilitydata\n") + f:write("\n") f:close() end statistics.stoptiming(_save_) end -function job.load(filename) - statistics.starttiming(_load_) +local function load(filename) local data = io.loaddata(filename) if data and data ~= "" then local version = tonumber(match(data,"^-- version: ([%d%.]+)")) @@ -165,24 +173,51 @@ function job.load(filename) report_jobcontrol("version mismatch with jobfile: %s <> %s", version or "?", job.version) else local data = loadstring(data) - if data then - data() - end - for l=1,#savelist do - local list = savelist[l] - local target, initializer = list[1], list[3] - local result = mark(accesstable(target)) - packers.unpack(result,job.packed,true) - if type(initializer) == "function" then - initializer(result) - end + return data and data() + end + end +end + +function job.load(filename) + statistics.starttiming(_load_) + local utilitydata = load(filename) + if utilitydata then + local jobpacker = utilitydata.job.packed + for l=1,#savelist do + local list = savelist[l] + local target = list[1] + local initializer = list[3] + local result = accesstable(target,utilitydata) + packers.unpack(result,jobpacker,true) + migratetable(target,mark(result)) + if type(initializer) == "function" then + initializer(result) end - job.packed = nil end end statistics.stoptiming(_load_) end +function job.loadother(filename) + statistics.starttiming(_load_) + _others_[#_others_+1] = file.nameonly(filename) + local utilitydata = load(filename) + if utilitydata then + local jobpacker = utilitydata.job.packed + local unpacked = { } + for l=1,#savelist do + local list = savelist[l] + local target = list[1] + local result = accesstable(target,utilitydata) + packers.unpack(result,jobpacker,true) + migratetable(target,result,unpacked) + end + unpacked.job.packed = nil -- nicer in inspecting + return unpacked + end + statistics.stoptiming(_load_) +end + -- eventually this will end up in strc-ini statistics.register("startup time", function() @@ -190,8 +225,12 @@ statistics.register("startup time", function() end) statistics.register("jobdata time",function() - if statistics.elapsedindeed(_save_) or statistics.elapsedindeed(_load_) then - return format("%s seconds saving, %s seconds loading", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_)) + if statistics.elapsedindeed(_save_) or statistics.elapsedindeed(_load_) or #_others_ > 0 then + if #_others_ > 0 then + return format("%s seconds saving, %s seconds loading, other files: %s", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_),concat(_others_," ")) + else + return format("%s seconds saving, %s seconds loading", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_)) + end end end) diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua index 2004cdb85..56bd1d92d 100644 --- a/tex/context/base/file-job.lua +++ b/tex/context/base/file-job.lua @@ -31,6 +31,7 @@ local v_project = variables.project local v_environment = variables.environment local v_product = variables.product local v_component = variables.component +local c_prefix = variables.prefix -- main code .. there is some overlap .. here we have loc:// @@ -346,11 +347,16 @@ local treestack = { } local top = tree.branches local root = tree +local project_stack = { } +local product_stack = { } +local component_stack = { } +local environment_stack = { } + local stacks = { - [v_project ] = { }, - [v_product ] = { }, - [v_component ] = { }, - [v_environment] = { }, + [v_project ] = project_stack, + [v_product ] = product_stack, + [v_component ] = component_stack, + [v_environment] = environment_stack, } -- @@ -396,6 +402,12 @@ end luatex.registerstopactions(logtree) +job.structure = job.structure or { } +job.structure.collected = job.structure.collected or { } +job.structure.tobesaved = root + +job.register('job.structure.collected',root) + -- component: small unit, either or not components itself -- product : combination of components @@ -467,6 +479,29 @@ local function topofstack(what) return stack and stack[#stack] or environment.jobname end +local function currentcomponent() -- only when in product + local product = product_stack[#product_stack] + if product and product ~= "" then + local component = component_stack[1] + if component and component ~= "" then + return component + end + end +end + +local function justacomponent() + local product = product_stack[#product_stack] + if not product or product == "" then + local component = component_stack[1] + if component and component ~= "" then + return component + end + end +end + +resolvers.jobs.currentcomponent = currentcomponent +resolvers.jobs.justacomponent = justacomponent + local done = { } local tolerant = false -- too messy, mkii user with the wrong sructure should adapt @@ -530,20 +565,21 @@ function commands.useenvironment(name) process(v_environment,name) end function commands.useproduct (name) process(v_product, name) end function commands.usecomponent (name) process(v_component, name) end --- -- todo: setsystemmode to currenttype +-- todo: setsystemmode to currenttype +-- todo: make start/stop commands at the tex end local start = { - [v_project] = context.starttext, - [v_product] = context.starttext, - [v_component] = context.starttext, - [v_environment] = nil, + [v_project] = context.startprojectindeed, + [v_product] = context.startproductindeed, + [v_component] = context.startcomponentindeed, + [v_environment] = context.startenvironmentindeed, } local stop = { - [v_project] = function() context.stoptext() context.signalendofinput(v_project) end, - [v_product] = function() context.stoptext() context.signalendofinput(v_product) end, - [v_component] = function() context.stoptext() context.signalendofinput(v_component) end, - [v_environment] = function() context.signalendofinput(v_environment) end, + [v_project] = context.stopprojectindeed, + [v_product] = context.stopproductindeed, + [v_component] = context.stopcomponentindeed, + [v_environment] = context.stopenvironmentindeed, } local function gotonextlevel(what,name) -- todo: something with suffix name diff --git a/tex/context/base/file-job.mkvi b/tex/context/base/file-job.mkvi index 47509754b..0213ff910 100644 --- a/tex/context/base/file-job.mkvi +++ b/tex/context/base/file-job.mkvi @@ -107,35 +107,35 @@ \unexpanded\def\processfileonce #name{\ctxcommand{processfileonce("#name")}} \unexpanded\def\processfilenone #name{\ctxcommand{processfilenone("#name")}} -\unexpanded\def\project {\doifnextoptionalelse\useproject \redoproject} -\unexpanded\def\product {\doifnextoptionalelse\useproduct \redoproduct} -\unexpanded\def\component {\doifnextoptionalelse\usecomponent \redocomponent} -\unexpanded\def\environment {\doifnextoptionalelse\useenvironment\redoenvironment} - -\def\redoproject #name {\ctxcommand{useproject ("#name")}} -\def\redoproduct #name {\ctxcommand{useproduct ("#name")}} -\def\redocomponent #name {\ctxcommand{usecomponent ("#name")}} -\def\redoenvironment #name {\ctxcommand{useenvironment("#name")}} - -\unexpanded\def\startproject {\doifnextoptionalelse\dostartproject \redostartproject} -\unexpanded\def\startproduct {\doifnextoptionalelse\dostartproduct \redostartproduct} -\unexpanded\def\startcomponent {\doifnextoptionalelse\dostartcomponent \redostartcomponent} -\unexpanded\def\startenvironment {\doifnextoptionalelse\dostartenvironment\redostartenvironment} - -\def\redostartproject #name {\ctxcommand{startproject ("#name")}} -\def\redostartproduct #name {\ctxcommand{startproduct ("#name")}} -\def\redostartcomponent #name {\ctxcommand{startcomponent ("#name")}} -\def\redostartenvironment #name {\ctxcommand{startenvironment("#name")}} - -\unexpanded\def\useproject [#name]{\ctxcommand{useproject ("#name")}} -\unexpanded\def\useproduct [#name]{\ctxcommand{useproduct ("#name")}} -\unexpanded\def\usecomponent [#name]{\ctxcommand{usecomponent ("#name")}} -\unexpanded\def\useenvironment [#name]{\ctxcommand{useenvironment("#name")}} - -\unexpanded\def\dostartproject [#name]{\ctxcommand{startproject ("#name")}} -\unexpanded\def\dostartproduct [#name]{\ctxcommand{startproduct ("#name")}} -\unexpanded\def\dostartcomponent [#name]{\ctxcommand{startcomponent ("#name")}} -\unexpanded\def\dostartenvironment[#name]{\ctxcommand{startenvironment("#name")}} +\unexpanded\def\project {\doifnextoptionalelse\useproject \do_project} +\unexpanded\def\product {\doifnextoptionalelse\useproduct \do_product} +\unexpanded\def\component {\doifnextoptionalelse\usecomponent \do_component} +\unexpanded\def\environment {\doifnextoptionalelse\useenvironment\do_environment} + +\def\do_project #name {\ctxcommand{useproject ("#name")}} +\def\do_product #name {\ctxcommand{useproduct ("#name")}} +\def\do_component #name {\ctxcommand{usecomponent ("#name")}} +\def\do_environment #name {\ctxcommand{useenvironment("#name")}} + +\unexpanded\def\startproject {\doifnextoptionalelse\do_startproject \redo_startproject} +\unexpanded\def\startproduct {\doifnextoptionalelse\do_startproduct \redo_startproduct} +\unexpanded\def\startcomponent {\doifnextoptionalelse\do_startcomponent \redo_startcomponent} +\unexpanded\def\startenvironment {\doifnextoptionalelse\do_startenvironment\redo_startenvironment} + +\def\redo_startproject #name {\ctxcommand{startproject ("#name")}} +\def\redo_startproduct #name {\ctxcommand{startproduct ("#name")}} +\def\redo_startcomponent #name {\ctxcommand{startcomponent ("#name")}} +\def\redo_startenvironment #name {\ctxcommand{startenvironment("#name")}} + +\unexpanded\def\useproject [#name]{\do_project {#name}} +\unexpanded\def\useproduct [#name]{\do_product {#name}} +\unexpanded\def\usecomponent [#name]{\do_component {#name}} +\unexpanded\def\useenvironment [#name]{\do_environment{#name}} + +\unexpanded\def\do_startproject [#name]{\ctxcommand{startproject ("#name")}} +\unexpanded\def\do_startproduct [#name]{\ctxcommand{startproduct ("#name")}} +\unexpanded\def\do_startcomponent [#name]{\ctxcommand{startcomponent ("#name")}} +\unexpanded\def\do_startenvironment[#name]{\ctxcommand{startenvironment("#name")}} \newconditional\endofinput % hack, needed because \endinput happens one level down in the input when we write from lua @@ -203,4 +203,35 @@ \neverypar\emptytoks +%D Wrappers (the signal is a synchronization with lua hack): + +\def\startprojectindeed + {\starttext} + +\def\stopprojectindeed + {\stoptext + \signalendofinput\v!project} + +\def\startproductindeed + {\starttext} + +\def\stopproductindeed + {\stoptext + \signalendofinput\v!product} + +\def\startcomponentindeed + {\starttext + \pushreferenceprefix\currentcomponent} + +\def\stopcomponentindeed + {\popreferenceprefix + \stoptext + \signalendofinput\v!component} + +\def\startenvironmentindeed + {} + +\def\stopenvironmentindeed + {\signalendofinput\v!project} + \protect \endinput diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv index 37455551c..783d16820 100644 --- a/tex/context/base/font-ini.mkiv +++ b/tex/context/base/font-ini.mkiv @@ -2396,13 +2396,19 @@ \everyvbox{\zerostagepreloadfonts} \to \everydump -\def\firststagepreloadfonts % see core-def.mkiv - {\doifmodeelse{*nofonts} - {\writestatus\m!fonts{latin modern fonts are not preloaded}} +% \def\firststagepreloadfonts % see core-def.mkiv +% {\doifmodeelse{*nofonts} +% {\writestatus\m!fonts{latin modern fonts are not preloaded}} +% {\preloaddefaultfonts +% \writestatus\m!fonts{preloading latin modern fonts (first stage)}}} + +\def\firststagepreloadfonts % *nofonts -> *preloadfonts + {\doifmodeelse{*preloadfonts} {\preloaddefaultfonts - \writestatus\m!fonts{preloading latin modern fonts (first stage)}}} + \writestatus\m!fonts{preloading latin modern fonts (first stage)}} + {\writestatus\m!fonts{latin modern fonts are not preloaded}}} -\def\secondstagepreloadfonts % see core-def.mkiv +\def\secondstagepreloadfonts {\writestatus\m!fonts{preloading latin modern fonts (second stage)}% \preloaddefaultfonts} diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua index ece0f7de3..eb85c3dea 100644 --- a/tex/context/base/lpdf-ano.lua +++ b/tex/context/base/lpdf-ano.lua @@ -323,10 +323,15 @@ end runners["inner"] = function(var,actions) if getinnermethod() == "names" then - local vir = var.i.references - local internal = vir and vir.internal - if internal then - var.inner = "aut:" .. internal + local vi = var.i + if vi then + local vir = vi.references + if vir then + local internal = vir.internal + if internal then + var.inner = "aut:" .. internal + end + end end else var.inner = nil diff --git a/tex/context/base/mult-mes.lua b/tex/context/base/mult-mes.lua index cdd6d5ad2..473c86d35 100644 --- a/tex/context/base/mult-mes.lua +++ b/tex/context/base/mult-mes.lua @@ -1097,14 +1097,15 @@ return { no = "ulovlig referanse %s", ro = "referinta eronata %s", }, - ["references:5"] = { - en = "number of unknown references: %s", - }, + -- ["number of unknown references: %s"] = { + -- }, ["references:6"] = { en = "number of illegal references: %s", }, - ["start: '%s'"] = {}, - ["stop: '%s'"] = {}, + ["start: '%s'"] = { + }, + ["stop: '%s'"] = { + }, ["stored: preamble '%s', state '%s', order '%s'"] = { nl = "opgeslagen: preamble '%s', status '%s', volgorde '%s'", }, diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index 278a40b6e..b19ef5589 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -376,11 +376,10 @@ nodes.references = { -- todo: get rid of n (n is just a number, can be used for tracing, obsolete) -local function setreference(n,h,d,r) +local function setreference(h,d,r) topofstack = topofstack + 1 -- the preroll permits us to determine samepage (but delayed also has some advantages) -- so some part of the backend work is already done here ---~ stack[topofstack] = { n, h, d, codeinjections.prerollreference(r) } stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) } -- texattribute[attribute] = topofstack -- todo -> at tex end texcount.lastreferenceattribute = topofstack @@ -533,14 +532,14 @@ function references.inject(prefix,reference,h,d,highlight,newwindow,layer) -- to else -- check set.highlight, set.newwindow,set.layer = highlight, newwindow, layer - setreference(tex.currentgrouplevel,h,d,set) -- sets attribute / todo: for set[*].error + setreference(h,d,set) -- sets attribute / todo: for set[*].error end end function references.injectcurrentset(h,d) -- used inside doifelse local currentset = references.currentset if currentset then - setreference(tex.currentgrouplevel,h,d,currentset) -- sets attribute / todo: for set[*].error + setreference(h,d,currentset) -- sets attribute / todo: for set[*].error end end diff --git a/tex/context/base/s-mag-01.tex b/tex/context/base/s-mag-01.tex index 6591fc23a..b90dceb66 100644 --- a/tex/context/base/s-mag-01.tex +++ b/tex/context/base/s-mag-01.tex @@ -288,7 +288,7 @@ [makeup] [corner={right,bottom},location={left,top}] [frame=off, - align=normal, % left, + align=normal, width=.8\textwidth, foregroundcolor=MainColor] {\getbuffer[abstract]} diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf Binary files differindex c8c6b27a5..a924c0fa0 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf Binary files differindex e4e11892c..5cfbd901e 100644 --- a/tex/context/base/status-lua.pdf +++ b/tex/context/base/status-lua.pdf diff --git a/tex/context/base/strc-des.mkiv b/tex/context/base/strc-des.mkiv index aaec8de69..113d1e665 100644 --- a/tex/context/base/strc-des.mkiv +++ b/tex/context/base/strc-des.mkiv @@ -927,7 +927,7 @@ % macros. \def\reinstatedescriptionnumberentry#1% - {\xdef\currentdescriptionattribute {\ctxlua {tex.write(structures.references.getinternalreference(#1))}}% + {\xdef\currentdescriptionattribute {\ctxlua {structures.references.getinternalreference(#1)}}% \xdef\currentdescriptionsynchronize{\ctxlatelua{structures.lists.enhance(#1)}}} \installstructurelistprocessor{description}{\usestructurelistprocessor{number+title}} diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index 7532ac63f..cee649aa5 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -16,18 +16,17 @@ local concat = table.concat local max, min = math.max, math.min local allocate, mark = utilities.storage.allocate, utilities.storage.mark -local catcodenumbers = catcodes.numbers -local ctxcatcodes = tex.ctxcatcodes -local variables = interfaces.variables +local catcodenumbers = catcodes.numbers +local ctxcatcodes = tex.ctxcatcodes +local variables = interfaces.variables ---~ if not trackers then trackers = { register = function() end } end +local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end) +local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end) -local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end) -local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end) +local report_structure = logs.reporter("structure","sectioning") -local report_structure = logs.reporter("structure","sectioning") - -local structures, context = structures, context +local structures = structures +local context = context local helpers = structures.helpers local documents = structures.documents @@ -74,6 +73,19 @@ end documents.initialize() +-- -- -- components -- -- -- + +function documents.preset(numbers) + local nofnumbers = #numbers + data.numbers = numbers + data.depth = nofnumbers + data.ownnumbers = { } + for i=1,nofnumbers do + data.ownnumbers[i] = "" + end + sections.setnumber(nofnumbers,"-1") +end + -- -- -- sections -- -- -- local collected = allocate() @@ -209,12 +221,16 @@ end function sections.somelevel(given) -- old number - local numbers, ownnumbers, forced, status, olddepth = data.numbers, data.ownnumbers, data.forced, data.status, data.depth - local givenname = given.metadata.name + local numbers = data.numbers + local ownnumbers = data.ownnumbers + local forced = data.forced + local status = data.status + local olddepth = data.depth + local givenname = given.metadata.name local mappedlevel = levelmap[givenname] - local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-* - local directives = given.directives - local resetset = (directives and directives.resetset) or "" + local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-* + local directives = given.directives + local resetset = (directives and directives.resetset) or "" -- local resetter = sets.getall("structure:resets",data.block,resetset) -- a trick to permits userdata to overload title, ownnumber and reference -- normally these are passed as argument but nowadays we provide several @@ -334,6 +350,11 @@ function sections.somelevel(given) references.tag = references.tag or tags.getid(metadata.kind,metadata.name) + local setcomponent = structures.references.setcomponent + if setcomponent then + setcomponent(given) -- might move to the tex end + end + references.section = sections.save(given) -- given.numberdata = nil end diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua index 1e54eddec..5b2297f0f 100644 --- a/tex/context/base/strc-lst.lua +++ b/tex/context/base/strc-lst.lua @@ -19,37 +19,38 @@ local lpegmatch = lpeg.match local simple_hash_to_string, settings_to_hash = utilities.parsers.simple_hash_to_string, utilities.parsers.settings_to_hash local allocate, checked = utilities.storage.allocate, utilities.storage.checked -local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end) +local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end) -local report_lists = logs.reporter("structure","lists") +local report_lists = logs.reporter("structure","lists") -local structures = structures -local lists = structures.lists -local sections = structures.sections -local helpers = structures.helpers -local documents = structures.documents -local pages = structures.pages -local tags = structures.tags -local references = structures.references +local structures = structures +local lists = structures.lists +local sections = structures.sections +local helpers = structures.helpers +local documents = structures.documents +local pages = structures.pages +local tags = structures.tags +local references = structures.references -local collected = allocate() -local tobesaved = allocate() -local cached = allocate() -local pushed = allocate() +local collected = allocate() +local tobesaved = allocate() +local cached = allocate() +local pushed = allocate() -lists.collected = collected -lists.tobesaved = tobesaved +lists.collected = collected +lists.tobesaved = tobesaved -lists.enhancers = lists.enhancers or { } -lists.internals = allocate(lists.internals or { }) -- to be checked -lists.ordered = allocate(lists.ordered or { }) -- to be checked -lists.cached = cached -lists.pushed = pushed +lists.enhancers = lists.enhancers or { } +lists.internals = allocate(lists.internals or { }) -- to be checked +lists.ordered = allocate(lists.ordered or { }) -- to be checked +lists.cached = cached +lists.pushed = pushed -references.specials = references.specials or { } +references.specials = references.specials or { } -local variables = interfaces.variables -local matchingtilldepth, numberatdepth = sections.matchingtilldepth, sections.numberatdepth +local variables = interfaces.variables +local matchingtilldepth = sections.matchingtilldepth +local numberatdepth = sections.numberatdepth -- -- -- -- -- -- @@ -121,6 +122,12 @@ function lists.push(t) pushed[i] = p r.listindex = p end + + local setcomponent = references.setcomponent + if setcomponent then + setcomponent(t) -- might move to the tex end + end + context(p) end diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua index 9382fc2b5..95851d1f0 100644 --- a/tex/context/base/strc-pag.lua +++ b/tex/context/base/strc-pag.lua @@ -55,8 +55,8 @@ function pages.save(prefixdata,numberdata) report_pages("saving page %s.%s",realpage,userpage) end local data = { - number = userpage, - block = sections.currentblock(), + number = userpage, + block = sections.currentblock(), prefixdata = prefixdata and helpers.simplify(prefixdata), numberdata = numberdata and helpers.simplify(numberdata), } @@ -121,17 +121,29 @@ function pages.analyze(entry,pagespecification) if not references then return false, false, "no references" end - local realpage = references.realpage - if not realpage then - return false, false, "no realpage" + local pagedata = references.pagedata -- sometimes resolved (external) + if not pagedata then + local realpage = references.realpage + if realpage then + pagedata = collected[realpage] + else + return false, false, "no realpage" + end end - local pagedata = collected[realpage] if not pagedata then return false, false, "no pagedata" end - local section = references.section - if not section then - return pagedata, false, "no section" + local sectiondata = references.sectiondata -- sometimes resolved (external) + if not sectiondata then + local section = references.section + if section then + sectiondata = sections.collected[section] + else + return pagedata, false, "no section" + end + end + if not sectiondata then + return pagedata, false, "no sectiondata" end local no = variables.no -- local preferences @@ -139,16 +151,16 @@ function pages.analyze(entry,pagespecification) return pagedata, false, "current spec blocks prefix" end -- stored preferences ---~ if entry.prefix == no then ---~ return pagedata, false, "entry blocks prefix" ---~ end + -- if entry.prefix == no then + -- return pagedata, false, "entry blocks prefix" + -- end -- stored page state pagespecification = pagedata.prefixdata if pagespecification and pagespecification.prefix == no then return pagedata, false, "pagedata blocks prefix" end -- final verdict - return pagedata, sections.collected[references.section], "okay" + return pagedata, sectiondata, "okay" end function helpers.page(data,pagespec) diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index a43b83cc3..8e3a3db82 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -6,77 +6,95 @@ if not modules then modules = { } end modules ['strc-ref'] = { license = "see context related readme files" } +-- beware, this is a first step in the rewrite (just getting rid of +-- the tuo file); later all access and parsing will also move to lua + +-- the useddata and pagedata names might change +-- todo: pack exported data + local format, find, gmatch, match, concat = string.format, string.find, string.gmatch, string.match, table.concat local texcount, texsetcount = tex.count, tex.setcount local rawget, tonumber = rawget, tonumber -local lpegmatch, lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.match, lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg +local lpegmatch = lpeg.match +local copytable = table.copy -local allocate = utilities.storage.allocate -local mark = utilities.storage.mark -local setmetatableindex = table.setmetatableindex +local allocate = utilities.storage.allocate +local mark = utilities.storage.mark +local setmetatableindex = table.setmetatableindex -local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end) -local trace_analyzing = false trackers.register("structures.referencing.analyzing", function(v) trace_analyzing = v end) +local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end) +local trace_analyzing = false trackers.register("structures.referencing.analyzing", function(v) trace_analyzing = v end) +local trace_identifying = false trackers.register("structures.referencing.identifying", function(v) trace_identifying = v end) +local trace_importing = false trackers.register("structures.referencing.importing", function(v) trace_importing = v end) -local report_references = logs.reporter("structure","references") +local report_references = logs.reporter("references") +local report_unknown = logs.reporter("unknown") +local report_identifying = logs.reporter("references","identifying") +local report_importing = logs.reporter("references","importing") -local variables = interfaces.variables -local constants = interfaces.constants -local context = context +local variables = interfaces.variables +local constants = interfaces.constants +local context = context -local settings_to_array = utilities.parsers.settings_to_array -local unsetvalue = attributes.unsetvalue +local texcount = tex.count +local texconditionals = tex.conditionals --- beware, this is a first step in the rewrite (just getting rid of --- the tuo file); later all access and parsing will also move to lua +local currentcomponent = resolvers.jobs.currentcomponent +local justacomponent = resolvers.jobs.justacomponent --- the useddata and pagedata names might change --- todo: pack exported data +local logsnewline = logs.newline +local logspushtarget = logs.pushtarget +local logspoptarget = logs.poptarget + +local settings_to_array = utilities.parsers.settings_to_array +local unsetvalue = attributes.unsetvalue -local structures = structures -local helpers = structures.helpers -local sections = structures.sections -local references = structures.references -local lists = structures.lists -local counters = structures.counters +local structures = structures +local helpers = structures.helpers +local sections = structures.sections +local references = structures.references +local lists = structures.lists +local counters = structures.counters -- some might become local -references.defined = references.defined or allocate() - -local defined = references.defined -local derived = allocate() -local specials = allocate() -local runners = allocate() -local internals = allocate() -local exporters = allocate() -local imported = allocate() -local filters = allocate() -local executers = allocate() -local handlers = allocate() -local tobesaved = allocate() -local collected = allocate() -local tobereferred = allocate() -local referred = allocate() - -references.derived = derived -references.specials = specials -references.runners = runners -references.internals = internals -references.exporters = exporters -references.imported = imported -references.filters = filters -references.executers = executers -references.handlers = handlers -references.tobesaved = tobesaved -references.collected = collected -references.tobereferred = tobereferred -references.referred = referred +references.defined = references.defined or allocate() + +local defined = references.defined +local derived = allocate() +local specials = allocate() +local runners = allocate() +local internals = allocate() +local filters = allocate() +local executers = allocate() +local handlers = allocate() +local tobesaved = allocate() +local collected = allocate() +local tobereferred = allocate() +local referred = allocate() + +references.derived = derived +references.specials = specials +references.runners = runners +references.internals = internals +references.filters = filters +references.executers = executers +references.handlers = handlers +references.tobesaved = tobesaved +references.collected = collected +references.tobereferred = tobereferred +references.referred = referred + +local splitreference = references.splitreference +local splitprefix = references.splitprefix +local splitprefix = references.splitcomponent +local prefixsplitter = references.prefixsplitter +local componentsplitter = references.componentsplitter + +local currentreference = nil storage.register("structures/references/defined", references.defined, "structures.references.defined") -local currentreference = nil - local initializers = { } local finalizers = { } @@ -106,16 +124,16 @@ job.register('structures.references.collected', tobesaved, initializer, finalize local maxreferred = 1 local nofreferred = 0 -local function initializer() -- can we use a tobesaved as metatable for collected? - tobereferred = references.tobereferred - referred = references.referred - nofreferred = #referred -end +-- local function initializer() -- can we use a tobesaved as metatable for collected? +-- tobereferred = references.tobereferred +-- referred = references.referred +-- nofreferred = #referred +-- end local function initializer() -- can we use a tobesaved as metatable for collected? tobereferred = references.tobereferred referred = references.referred - setmetatableindex(referred,get) + setmetatableindex(referred,get) -- hm, what is get ? end -- We make the array sparse (maybe a finalizer should optionally return a table) because @@ -225,20 +243,30 @@ function references.currentorder(kind,name) context(orders[kind] and orders[kind][name] or lastorder) end +local function setcomponent(data) + -- we might consider doing this at the tex end, just like prefix + local component = currentcomponent() + if component then + local references = data and data.references + if references then + references.component = component + end + return component + end + -- but for the moment we do it here (experiment) +end + +references.setcomponent = setcomponent + function references.set(kind,prefix,tag,data) +-- setcomponent(data) + local pd = tobesaved[prefix] + if not pd then + pd = { } + tobesaved[prefix] = pd + end for ref in gmatch(tag,"[^,]+") do - local p, r = match(ref,"^(%-):(.-)$") - if p and r then - prefix, ref = p, r - else - prefix = "" - end if ref ~= "" then - local pd = tobesaved[prefix] - if not pd then - pd = { } - tobesaved[prefix] = pd - end pd[ref] = data context.dofinishsomereference(kind,prefix,ref) end @@ -250,166 +278,20 @@ function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do in texcount.lastdestinationattribute = references.setinternalreference(prefix,tag,nil,view) or -0x7FFFFFFF end -function references.enhance(prefix,tag,spec) +function references.enhance(prefix,tag) local l = tobesaved[prefix][tag] if l then l.references.realpage = texcount.realpageno end end --- this reference parser is just an lpeg version of the tex based one - --- local result = { } --- --- local lparent = lpegP("(") --- local rparent = lpegP(")") --- local lbrace = lpegP("{") --- local rbrace = lpegP("}") --- local dcolon = lpegP("::") --- local backslash = lpegP("\\") --- --- local reset = lpegP("") / function() result = { } end --- local b_token = backslash / function(s) result.has_tex = true return s end --- --- local o_token = 1 - rparent - rbrace - lparent - lbrace --- local a_token = 1 - rbrace --- local s_token = 1 - lparent - lbrace --- local i_token = 1 - lparent - lbrace --- local f_token = 1 - lparent - lbrace - dcolon --- --- local outer = (f_token )^1 / function (s) result.outer = s end --- local operation = lpegCs((b_token + o_token)^1) / function (s) result.operation = s end --- local arguments = lpegCs((b_token + a_token)^0) / function (s) result.arguments = s end --- local special = (s_token )^1 / function (s) result.special = s end --- local inner = (i_token )^1 / function (s) result.inner = s end --- --- local outer_reference = (outer * dcolon)^0 --- --- operation = outer_reference * operation -- special case: page(file::1) and file::page(1) --- --- local optional_arguments = (lbrace * arguments * rbrace)^0 --- local inner_reference = inner * optional_arguments --- local special_reference = special * lparent * (operation * optional_arguments + operation^0) * rparent --- --- local scanner = (reset * outer_reference * (special_reference + inner_reference)^-1 * -1) / function() return result end --- --- function references.split(str) --- return lpegmatch(scanner,str or "") --- end - --- the scanner accepts nested outer, but we don't care too much, maybe some day we will --- have both but currently the innermost wins - -local spaces = lpegP(" ")^0 -local lparent = lpegP("(") -local rparent = lpegP(")") -local lbrace = lpegP("{") -local rbrace = lpegP("}") -local dcolon = lpegP("::") -local backslash = lpegP("\\") - - lparent = spaces * lparent * spaces - rparent = spaces * rparent * spaces - lbrace = spaces * lbrace * spaces - rbrace = spaces * rbrace * spaces - dcolon = spaces * dcolon * spaces - -local endofall = spaces * lpegP(-1) - -local o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient -local a_token = 1 - rbrace -local s_token = 1 - lparent - lbrace -local i_token = 1 - lparent - lbrace - endofall -local f_token = 1 - lparent - lbrace - dcolon - -local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work -local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1)) -local operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1)) -local arguments = lpegCg(lpegCc("arguments") * lpegCs(a_token^0)) -local special = lpegCg(lpegCc("special") * lpegCs(s_token^1)) -local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1)) - - arguments = (lbrace * arguments * rbrace)^-1 - outer = (outer * dcolon)^-1 - operation = outer * operation -- special case: page(file::1) and file::page(1) - inner = inner * arguments - special = special * lparent * (operation * arguments)^-1 * rparent - -local scanner = spaces * lpegCf (lpegCt("") * outer * (special + inner)^-1 * endofall, rawset) - -local function splitreference(str) - if str and str ~= "" then - local t = lpegmatch(scanner,str) - if t then - local a = t.arguments - if a and find(a,"\\") then - t.has_tex = true - else - local o = t.arguments - if o and find(o,"\\") then - t.has_tex = true - end - end - return t - end - end -end - -references.split = splitreference - ---~ inspect(splitreference([[ ]])) ---~ inspect(splitreference([[ inner ]])) ---~ inspect(splitreference([[ special ( operation { argument, argument } ) ]])) ---~ inspect(splitreference([[ special ( operation { argument } ) ]])) ---~ inspect(splitreference([[ special ( operation { argument, \argument } ) ]])) ---~ inspect(splitreference([[ special ( operation { \argument } ) ]])) ---~ inspect(splitreference([[ special ( operation ) ]])) ---~ inspect(splitreference([[ special ( \operation ) ]])) ---~ inspect(splitreference([[ special ( o\peration ) ]])) ---~ inspect(splitreference([[ special ( ) ]])) ---~ inspect(splitreference([[ inner { argument } ]])) ---~ inspect(splitreference([[ inner { \argument } ]])) ---~ inspect(splitreference([[ inner { ar\gument } ]])) ---~ inspect(splitreference([[inner{a\rgument}]])) ---~ inspect(splitreference([[ inner { argument, argument } ]])) ---~ inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg? ---~ inspect(splitreference([[ inner { \argument, \argument } ]])) ---~ inspect(splitreference([[ outer :: ]])) ---~ inspect(splitreference([[ outer :: inner]])) ---~ inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]])) ---~ inspect(splitreference([[ outer :: special (operation { } )]])) ---~ inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]])) ---~ inspect(splitreference([[ outer :: special ( operation ) ]])) ---~ inspect(splitreference([[ outer :: special ( \operation ) ]])) ---~ inspect(splitreference([[ outer :: special ( ) ]])) ---~ inspect(splitreference([[ outer :: inner { argument } ]])) ---~ inspect(splitreference([[ special ( outer :: operation ) ]])) - ---~ inspect(splitreference([[]])) ---~ inspect(splitreference([[inner]])) ---~ inspect(splitreference([[special(operation{argument,argument})]])) ---~ inspect(splitreference([[special(operation)]])) ---~ inspect(splitreference([[special(\operation)]])) ---~ inspect(splitreference([[special()]])) ---~ inspect(splitreference([[inner{argument}]])) ---~ inspect(splitreference([[inner{\argument}]])) ---~ inspect(splitreference([[outer::]])) ---~ inspect(splitreference([[outer::inner]])) ---~ inspect(splitreference([[outer::special(operation{argument,argument})]])) ---~ inspect(splitreference([[outer::special(operation{argument,\argument})]])) ---~ inspect(splitreference([[outer::special(operation)]])) ---~ inspect(splitreference([[outer::special(\operation)]])) ---~ inspect(splitreference([[outer::special()]])) ---~ inspect(splitreference([[outer::inner{argument}]])) ---~ inspect(splitreference([[special(outer::operation)]])) - -- -- -- related to strc-ini.lua -- -- -- references.resolvers = references.resolvers or { } local resolvers = references.resolvers function resolvers.section(var) - local vi = lists.collected[var.i[2]] + local vi = var.i[3] or lists.collected[var.i[2]] if vi then var.i = vi var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1 @@ -425,7 +307,7 @@ resolvers.formula = resolvers.section resolvers.note = resolvers.section function resolvers.reference(var) - local vi = var.i[2] + local vi = var.i[2] -- check if vi then var.i = vi var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1 @@ -435,22 +317,26 @@ function resolvers.reference(var) end end -local function register_from_lists(collected,derived) +local function register_from_lists(collected,derived,pages,sections) local g = derived[""] if not g then g = { } derived[""] = g end -- global for i=1,#collected do local entry = collected[i] local m, r = entry.metadata, entry.references if m and r then - local prefix, reference = r.referenceprefix or "", r.reference or "" + local reference = r.reference or "" + local prefix = r.referenceprefix or "" + local component = r.component and r.component or "" if reference ~= "" then local kind, realpage = m.kind, r.realpage if kind and realpage then local d = derived[prefix] if not d then d = { } derived[prefix] = d end - local t = { kind, i } +local c = derived[component] if not c then c = { } derived[component] = c end + local t = { kind, i, entry } for s in gmatch(reference,"%s*([^,]+)") do if trace_referencing then report_references("list entry %s provides %s reference '%s' on realpage %s",i,kind,s,realpage) end +c[s] = c[s] or t -- share them d[s] = d[s] or t -- share them g[s] = g[s] or t -- first wins end @@ -458,6 +344,7 @@ local function register_from_lists(collected,derived) end end end +-- inspect(derived) end references.registerinitializer(function() register_from_lists(lists.collected,derived) end) @@ -502,9 +389,16 @@ references.files.data = references.files.data or { } local files = references.files.data +table.setmetatableindex(files, function(t,k) + -- we assume that it's a file anyway + local v = { k, k } + files[k] = v + return v +end) + function references.files.define(name,file,description) if name and name ~= "" then - files[name] = { file or "", description or file or ""} + files[name] = { file or "", description or file or "" } end end @@ -605,31 +499,6 @@ function references.whatfrom(name) context((urls[name] and variables.url) or (files[name] and variables.file) or variables.unknown) end ---~ function references.from(name) ---~ local u = urls[name] ---~ if u then ---~ local url, file, description = u[1], u[2], u[3] ---~ if description ~= "" then ---~ context.dofromurldescription(description) ---~ -- ok ---~ elseif file and file ~= "" then ---~ context.dofromurlliteral(url .. "/" .. file) ---~ else ---~ context(dofromurlliteral,url) ---~ end ---~ else ---~ local f = files[name] ---~ if f then ---~ local description, file = f[1], f[2] ---~ if description ~= "" then ---~ context.dofromfiledescription(description) ---~ else ---~ context.dofromfileliteral(file) ---~ end ---~ end ---~ end ---~ end - function references.from(name) local u = urls[name] if u then @@ -655,160 +524,6 @@ function references.from(name) end end --- export - -exporters.references = exporters.references or { } -exporters.lists = exporters.lists or { } - -function exporters.references.generic(data) - local useddata = {} - local entries, userdata = data.entries, data.userdata - if entries then - for k, v in next, entries do - useddata[k] = v - end - end - if userdata then - for k, v in next, userdata do - useddata[k] = v - end - end - return useddata -end - -function exporters.lists.generic(data) - local useddata = { } - local titledata, numberdata = data.titledata, data.numberdata - if titledata then - useddata.title = titledata.title - end - if numberdata then - local numbers = numberdata.numbers - local t, tn = { }, 0 - for i=1,#numbers do - local n = numbers[i] - if n ~= 0 then - tn = tn + 1 - t[tn] = n - end - end - useddata.number = concat(t,".") - end - return useddata -end - -local function referencer(data) - local references = data.references - local realpage = references.realpage - local numberdata = jobpages.tobesaved[realpage] - local specification = numberdata.specification - return { - realpage = references.realpage, - number = numberdata.number, - conversion = specification.conversion, - -- prefix = only makes sense when bywhatever - } -end - --- Exported and imported references ... not yet used but don't forget it --- and redo it. - -function references.export(usedname) - local exported = { } - local e_references, e_lists = exporters.references, exporters.lists - local g_references, g_lists = e_references.generic, e_lists.generic - -- todo: pagenumbers - -- todo: some packing - for prefix, references in next, references.tobesaved do - local pe = exported[prefix] if not pe then pe = { } exported[prefix] = pe end - for key, data in next, references do - local metadata = data.metadata - local exporter = e_references[metadata.kind] or g_references - if exporter then - pe[key] = { - metadata = { - kind = metadata.kind, - catcodes = metadata.catcodes, - coding = metadata.coding, -- we can omit "tex" - }, - useddata = exporter(data), - pagedata = referencer(data), - } - end - end - end - local pe = exported[""] if not pe then pe = { } exported[""] = pe end - for n, data in next, lists.tobesaved do - local metadata = data.metadata - local exporter = e_lists[metadata.kind] or g_lists - if exporter then - local result = { - metadata = { - kind = metadata.kind, - catcodes = metadata.catcodes, - coding = metadata.coding, -- we can omit "tex" - }, - useddata = exporter(data), - pagedata = referencer(data), - } - for key in gmatch(data.references.reference,"[^,]+") do - pe[key] = result - end - end - end - local e = { - references = exported, - version = 1.00, - } - io.savedata(file.replacesuffix(usedname or tex.jobname,"tue"),table.serialize(e,true)) -end - -function references.import(usedname) - if usedname then - local jdn = imported[usedname] - if not jdn then - local filename = files[usedname] - if filename then -- only registered files - filename = filename[1] - else - filename = usedname - end - local data = io.loaddata(file.replacesuffix(filename,"tue")) or "" - if data == "" then - interfaces.showmessage("references",24,filename) - data = nil - else - data = loadstring(data) - if data then - data = data() - end - if data then - -- version check - end - if not data then - interfaces.showmessage("references",25,filename) - end - end - if data then - interfaces.showmessage("references",26,filename) - jdn = data - jdn.filename = filename - else - jdn = { filename = filename, references = { }, version = 1.00 } - end - imported[usedname] = jdn - imported[filename] = jdn - end - return jdn - else - return nil - end -end - -function references.load(usedname) - -- gone -end - function references.define(prefix,reference,list) local d = defined[prefix] if not d then d = { } defined[prefix] = d end d[reference] = { "defined", list } @@ -907,42 +622,6 @@ end references.currentset = nil ---~ local b, e = "\\ctxlua{local jc = structures.references.currentset;", "}" ---~ local o, a = 'jc[%s].operation=[[%s]];', 'jc[%s].arguments=[[%s]];' ---~ ---~ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex ---~ local currentset = references.currentset ---~ if currentset and currentset.has_tex then ---~ local done = false ---~ for i=1,#currentset do ---~ local ci = currentset[i] ---~ local operation = ci.operation ---~ if operation then ---~ if find(operation,"\\") then -- if o_has_tex then ---~ if not done then ---~ context(b) ---~ done = true ---~ end ---~ context(o,i,operation) ---~ end ---~ end ---~ local arguments = ci.arguments ---~ if arguments then ---~ if find(arguments,"\\") then -- if a_has_tex then ---~ if not done then ---~ context(b) ---~ done = true ---~ end ---~ context(a,i,arguments) ---~ end ---~ end ---~ end ---~ if done then ---~ context(e) ---~ end ---~ end ---~ end - function commands.setreferenceoperation(k,v) references.currentset[k].operation = v end @@ -971,281 +650,741 @@ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex end end ---~ local uo = urls[outer] ---~ if uo then ---~ special, operation, argument = "url", uo[1], inner or uo[2] -- maybe more is needed ---~ else ---~ local fo = files[outer] ---~ if fo then ---~ special, operation, argument = "file", fo[1], inner -- maybe more is needed ---~ end ---~ end +local externals = { } -local prefixsplitter = lpegCs(lpegP((1-lpegP(":"))^1 * lpegP(":"))) * lpegCs(lpegP(1)^1) +-- we have prefixes but also components: +-- +-- : prefix +-- :: always external +-- ::: internal (for products) or external (for components) + +local function loadexternalreferences(name,utilitydata) + local struc = utilitydata.structures + if struc then + local external = struc.references.collected -- direct references + local lists = struc.lists.collected -- indirect references (derived) + local pages = struc.pages.collected -- pagenumber data + for prefix, set in next, external do + for reference, data in next, set do + if trace_importing then + report_importing("registering external reference: regular | %s | %s | %s",name,prefix,reference) + end + local section = reference.section + local realpage = reference.realpage + if section then + reference.sectiondata = lists[section] + end + if realpage then + reference.pagedata = pages[realpage] + end + end + end + for i=1,#lists do + local entry = lists[i] + local metadata = entry.metadata + local references = entry.references + if metadata and references then + local reference = references.reference + if reference and reference ~= "" then + local kind = metadata.kind + local realpage = references.realpage + if kind and realpage then + references.pagedata = pages[realpage] + local prefix = references.referenceprefix or "" + local target = external[prefix] + if not target then + target = { } + external[prefix] = target + end + for s in gmatch(reference,"%s*([^,]+)") do + if trace_importing then + report_importing("registering external reference: %s | %s | %s | %s",kind,name,prefix,s) + end + target[s] = target[s] or entry + end + end + end + end + end + externals[name] = external + return external + end +end --- todo: add lots of tracing here +table.setmetatableindex(externals,function(t,k) -- either or not automatically + local filename = files[k][1] -- filename + local fullname = file.replacesuffix(filename,"tuc") + if lfs.isfile(fullname) then -- todo: use other locator + local utilitydata = job.loadother(fullname) + if utilitydata then + local external = loadexternalreferences(k,utilitydata) + t[k] = external or false + return external + end + end + t[k] = false + return false +end) -local n = 0 +local productdata = { + productreferences = { }, + componentreferences = { }, + components = { }, +} -local function identify(prefix,reference) - local set = resolve(prefix,reference) - local bug = false - texcount.referencehastexstate = set.has_tex and 1 or 0 - n = n + 1 - set.n = n - for i=1,#set do - local var = set[i] - local special, inner, outer, arguments, operation = var.special, var.inner, var.outer, var.arguments, var.operation - if special then - local s = specials[special] - if s then - if outer then - if operation then - -- special(outer::operation) - var.kind = "special outer with operation" - else - -- special() - var.kind = "special outer" - end - var.f = outer - elseif operation then - if arguments then - -- special(operation{argument,argument}) - var.kind = "special operation with arguments" - else - -- special(operation) - var.kind = "special operation" - end - else - -- special() - var.kind = "special" +local function loadproductreferences(productname,componentname,utilitydata) + local struc = utilitydata.structures + if struc then + local productreferences = struc.references.collected -- direct references + local lists = struc.lists.collected -- indirect references (derived) + local pages = struc.pages.collected -- pagenumber data + -- we use indirect tables to save room but as they are eventually + -- just references we resolve them to data here (the mechanisms + -- that use this data check for indirectness) + for prefix, set in next, productreferences do + for reference, data in next, set do + if trace_importing then + report_importing("registering product reference: regular | %s | %s | %s",productname,prefix,reference) + end + local section = reference.section + local realpage = reference.realpage + if section then + reference.sectiondata = lists[section] + end + if realpage then + reference.pagedata = pages[realpage] end - else - var.error = "unknown special" end - elseif outer then - local e = references.import(outer) - if e then - if inner then - local r = e.references - if r then - r = r[prefix] - if r then - r = r[inner] - if r then - if arguments then - -- outer::inner{argument} - var.kind = "outer with inner with arguments" - else - -- outer::inner - var.kind = "outer with inner" - end - var.i = { "reference", r } - resolvers.reference(var) - var.f = outer - var.e = true -- external + end + -- + local componentreferences = { } + for i=1,#lists do + local entry = lists[i] + local metadata = entry.metadata + local references = entry.references + if metadata and references then + local reference = references.reference + if reference and reference ~= "" then + local kind = metadata.kind + local realpage = references.realpage + if kind and realpage then + references.pagedata = pages[realpage] + local prefix = references.referenceprefix or "" + local component = references.component + local ctarget, ptarget + if component and component == componentname then + -- skip + else + -- one level up + local external = componentreferences[component] + if not external then + external = { } + componentreferences[component] = external + end + if component == prefix then + prefix = "" + end + ctarget = external[prefix] + if not ctarget then + ctarget = { } + external[prefix] = ctarget end end - end - if not r then - r = e.derived - if r then - r = r[prefix] - if r then - r = r[inner] - if r then - -- outer::inner - if arguments then - -- outer::inner{argument} - var.kind = "outer with inner with arguments" - else - -- outer::inner - var.kind = "outer with inner" - end - var.i = r - resolvers[r[1]](var) - var.f = outer + ptarget = productreferences[prefix] + if not ptarget then + ptarget = { } + productreferences[prefix] = ptarget + end + for s in gmatch(reference,"%s*([^,]+)") do + if ptarget then + if trace_importing then + report_importing("registering product reference: %s | %s | %s | %s",kind,productname,prefix,s) end + ptarget[s] = ptarget[s] or entry end - end - end - if not r then - var.error = "unknown outer" - end - elseif special then - local s = specials[special] - if s then - if operation then - if arguments then - -- outer::special(operation{argument,argument}) - var.kind = "outer with special and operation and arguments" - else - -- outer::special(operation) - var.kind = "outer with special and operation" + if ctarget then + if trace_importing then + report_importing("registering component reference: %s | %s | %s | %s",kind,productname,prefix,s) + end + ctarget[s] = ctarget[s] or entry end - else - -- outer::special() - var.kind = "outer with special" end - var.f = outer - else - var.error = "unknown outer with special" end - else - -- outer:: - var.kind = "outer" - var.f = outer end - else - if inner then - if arguments then - -- outer::inner{argument} - var.kind = "outer with inner with arguments" - else - -- outer::inner - var.kind = "outer with inner" + end + end + productdata.productreferences = productreferences -- not yet used + productdata.componentreferences = componentreferences + end +end + +local function loadproductvariables(product,component,utilitydata) + local struc = utilitydata.structures + if struc then + local lists = struc.lists and struc.lists.collected + if lists then + local pages = struc.pages and struc.pages.collected + for i=1,#lists do + local li = lists[i] + if li.metadata.kind == "section" and li.references.component == component then + local firstsection = li + if firstsection.numberdata then + local numbers = firstsection.numberdata.numbers + if numbers then + if trace_importing then + report_importing("initializing section number to %s",concat(numbers,":")) + end + productdata.firstsection = firstsection + structures.documents.preset(numbers) + end end - var.i = { "reference", inner } - resolvers.reference(var) - var.f = outer - elseif special then - local s = specials[special] - if s then - if operation then - if arguments then - -- outer::special(operation{argument,argument}) - var.kind = "outer with special and operation and arguments" - else - -- outer::special(operation) - var.kind = "outer with special and operation" + if pages and firstsection.references then + local firstpage = pages[firstsection.references.realpage] + local number = firstpage and firstpage.number + if number then + if trace_importing then + report_importing("initializing page number to %s",number) end - else - -- outer::special() - var.kind = "outer with special" + productdata.firstpage = firstpage + counters.set("userpage",1,number) end - var.f = outer - else - var.error = "unknown outer with special" end + break + end + end + end + end +end + +local function componentlist(tree,target) + local branches = tree and tree.branches + if branches then + for i=1,#branches do + local branch = branches[i] + local type = branch.type + if type == "component" then + if target then + target[#target+1] = branch.name else - -- outer:: - var.kind = "outer" - var.f = outer + target = { branch.name } + end + elseif type == "product" or type == "component" then + target = componentlist(branch,target) + end + end + end + return target +end + +local function loadproductcomponents(product,component,utilitydata) + local job = utilitydata.job + productdata.components = componentlist(job and job.structure and job.structure.collected) or { } +end + +function structures.references.loadpresets(product,component) -- we can consider a special components hash + if product and component and product~= "" and component ~= "" and not productdata.product then -- maybe: productdata.filename ~= filename + productdata.product = product + productdata.component = component + local fullname = file.replacesuffix(product,"tuc") + if lfs.isfile(fullname) then -- todo: use other locator + local utilitydata = job.loadother(fullname) + if utilitydata then + if trace_importing then + report_importing("loading presets for component %s from product %s",component,product) end + loadproductvariables (product,component,utilitydata) + loadproductreferences(product,component,utilitydata) + loadproductcomponents(product,component,utilitydata) + -- inspect(productdata) end + end + end +end + +structures.references.productdata = productdata + +local useproduct = commands.useproduct + +if useproduct then + + function commands.useproduct(product) + useproduct(product) + if texconditionals.autocrossfilereferences then + local component = justacomponent() + if component then + if trace_referencing then + report_references("loading presets for component '%s' from product '%s'",component,product) + end + structures.references.loadpresets(product,component) + end + end + end + +end + +-- productdata.firstsection.numberdata.numbers +-- productdata.firstpage.number + +local function report_identify_special(set,var,i,type) + local reference = set.reference + local prefix = set.prefix or "" + local special = var.special + local error = var.error + local kind = var.kind + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, special: %s, error: %s",type,reference,i,prefix,special,error) + else + report_identifying("type %s: %s, n: %s, prefix: %s, special: %s, kind: %s",type,reference,i,prefix,special,kind) + end +end + +local function report_identify_arguments(set,var,i,type) + local reference = set.reference + local prefix = set.prefix or "" + local arguments = var.arguments + local error = var.error + local kind = var.kind + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, arguments: %s, error: %s",type,reference,i,prefix,arguments,error) + else + report_identifying("type %s: %s, n: %s, prefix: %s, arguments: %s, kind: %s",type,reference,i,prefix,arguments,kind) + end +end + +local function report_identify_outer(set,var,i,type) + local reference = set.reference + local prefix = set.prefix or "" + local outer = var.outer + local error = var.error + local kind = var.kind + if outer then + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, outer: %s, error: %s",type,reference,i,prefix,outer,error) + else + report_identifying("type %s: %s, n: %s, prefix: %s, outer: %s, kind: %s",type,reference,i,prefix,outer,kind) + end + else + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, error: %s",type,reference,i,prefix,error) else + report_identifying("type %s: %s, n: %s, prefix: %s, kind: %s",type,reference,i,prefix,kind) + end + end +end + +local function identify_special(set,var,i) + local special = var.special + local s = specials[special] + if s then + local outer = var.outer + local operation = var.operation + local arguments = var.arguments + if outer then + if operation then + -- special(outer::operation) + var.kind = "special outer with operation" + else + -- special() + var.kind = "special outer" + end + var.f = outer + elseif operation then if arguments then - local s = specials[inner] - if s then - -- inner{argument} - var.kind = "special with arguments" - else - var.error = "unknown inner or special" - end + -- special(operation{argument,argument}) + var.kind = "special operation with arguments" else - -- inner ... we could move the prefix logic into the parser so that we have 'm for each entry - -- foo:bar -> foo == prefix (first we try the global one) - -- -:bar -> ignore prefix - local p, i = prefix, nil - local splitprefix, splitinner = lpegmatch(prefixsplitter,inner) - -- these are taken from other anonymous references - if splitprefix and splitinner then - if splitprefix == "-" then - i = collected[""] - i = i and i[splitinner] - if i then - p = "" - end - else - i = collected[splitprefix] - i = i and i[splitinner] - if i then - p = splitprefix - end - end - end - -- todo: strict here - if not i then - i = collected[prefix] - i = i and i[inner] - if i then - p = prefix - end + -- special(operation) + var.kind = "special operation" + end + else + -- special() + var.kind = "special" + end + if trace_identifying then + report_identify_special(set,var,i,"1a") + end + else + var.error = "unknown special" + end + return var +end + +local function identify_arguments(set,var,i) + local s = specials[var.inner] + if s then + -- inner{argument} + var.kind = "special with arguments" + else + var.error = "unknown inner or special" + end + if trace_identifying then + report_identify_arguments(set,var,i,"3a") + end + return var +end + +local function identify_inner(set,var,prefix,collected,derived,tobesaved) + local inner = var.inner + local outer = var.outer + -- inner ... we could move the prefix logic into the parser so that we have 'm for each entry + -- foo:bar -> foo == prefix (first we try the global one) + -- -:bar -> ignore prefix + local p, i = prefix, nil + local splitprefix, splitinner = lpegmatch(prefixsplitter,inner) + -- these are taken from other anonymous references + if splitprefix and splitinner then + if splitprefix == "-" then + i = collected[""] + i = i and i[splitinner] + if i then + p = "" + end + else + i = collected[splitprefix] + i = i and i[splitinner] + if i then + p = splitprefix + end + end + end + -- todo: strict here + if not i then + i = collected[prefix] + i = i and i[inner] + if i then + p = prefix + end + end + if not i and prefix ~= "" then + i = collected[""] + i = i and i[inner] + if i then + p = "" + end + end + if i then + var.i = { "reference", i } + resolvers.reference(var) + var.kind = "inner" + var.p = p + elseif derived then + -- these are taken from other data structures (like lists) + if splitprefix and splitinner then + if splitprefix == "-" then + i = derived[""] + i = i and i[splitinner] + if i then + p = "" end - if not i and prefix ~= "" then - i = collected[""] - i = i and i[inner] - if i then - p = "" - end + else + i = derived[splitprefix] + i = i and i[splitinner] + if i then + p = splitprefix end + end + end + if not i then + i = derived[prefix] + i = i and i[inner] + if i then + p = prefix + end + end + if not i and prefix ~= "" then + i = derived[""] + i = i and i[inner] + if i then + p = "" + end + end + if i then + var.kind = "inner" + var.i = i + resolvers[i[1]](var) + var.p = p + else + -- no prefixes here + local s = specials[inner] + if s then + var.kind = "special" + else + i = (collected and collected[""] and collected[""][inner]) or + (derived and derived [""] and derived [""][inner]) or + (tobesaved and tobesaved[""] and tobesaved[""][inner]) if i then + var.kind = "inner" var.i = { "reference", i } resolvers.reference(var) - var.kind = "inner" - var.p = p + var.p = "" else - -- these are taken from other data structures (like lists) - if splitprefix and splitinner then - if splitprefix == "-" then - i = derived[""] - i = i and i[splitinner] - if i then - p = "" - end - else - i = derived[splitprefix] - i = i and i[splitinner] - if i then - p = splitprefix - end - end - end - if not i then - i = derived[prefix] - i = i and i[inner] - if i then - p = prefix + var.error = "unknown inner or special" + end + end + end + end + return var +end + +local function identify_outer(set,var,i) + local outer = var.outer + local inner = var.inner + local external = externals[outer] + if external then + local v = copytable(var) + v = identify_inner(set,v,nil,external) + if v.i and not v.error then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2a") + end + return v + end + v = copytable(var) + local v = identify_inner(set,v,v.outer,external) + if v.i and not v.error then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2b") + end + return v + end + end + local external = productdata.componentreferences[outer] + if external then + local v = identify_inner(set,copytable(var),nil,external) + if v.i and not v.error then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2c") + end + return v + end + end + local external = productdata.productreferences[outer] + if external then + local vi = external[inner] + if vi then + var.kind = "outer with inner" + var.i = vi + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"2d") + end + return var + end + end + -- the rest + local special = var.special + local arguments = var.arguments + local operation = var.operation + if inner then + if arguments then + -- outer::inner{argument} + var.kind = "outer with inner with arguments" + else + -- outer::inner + var.kind = "outer with inner" + end + var.i = { "reference", inner } + resolvers.reference(var) + var.f = outer + if trace_identifying then + report_identify_outer(set,var,i,"2e") + end + elseif special then + local s = specials[special] + if s then + if operation then + if arguments then + -- outer::special(operation{argument,argument}) + var.kind = "outer with special and operation and arguments" + else + -- outer::special(operation) + var.kind = "outer with special and operation" + end + else + -- outer::special() + var.kind = "outer with special" + end + var.f = outer + else + var.error = "unknown outer with special" + end + if trace_identifying then + report_identify_outer(set,var,i,"2f") + end + else + -- outer:: + var.kind = "outer" + var.f = outer + if trace_identifying then + report_identify_outer(set,var,i,"2g") + end + end + return var +end + +local function identify_inner_or_outer(set,var,i) + -- here we fall back on product data + local inner = var.inner + if inner and inner ~= "" then + local v = identify_inner(set,copytable(var),prefix,collected,derived,tobesaved) + if v.i and not v.error then + v.kind = "inner" -- check this + if trace_identifying then + report_identify_outer(set,v,i,"4a") + end + return v + end + local componentreferences = productdata.componentreferences + local productreferences = productdata.productreferences + local components = productdata.components + if components and componentreferences then + -- for component, data in next, productdata.componentreferences do -- better do this in order of processing: + for i=1,#components do + local component = components[i] + local data = componentreferences[component] + if data then + local d = data[""] + local vi = d and d[inner] + if vi then + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"4b") end + return var end - if not i and prefix ~= "" then - i = derived[""] - i = i and i[inner] - if i then - p = "" - end + end + end + end + local component, inner = lpegmatch(componentsplitter,inner) + if component then + local data = componentreferences and componentreferences[component] + if data then + local d = data[""] + local vi = d and d[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"4c") end - if i then - var.kind = "inner" - var.i = i - resolvers[i[1]](var) - var.p = p - else - -- no prefixes here - local s = specials[inner] - if s then - var.kind = "special" - else - i = (collected[""] and collected[""][inner]) or - (derived [""] and derived [""][inner]) or - (tobesaved[""] and tobesaved[""][inner]) - if i then - var.kind = "inner" - var.i = { "reference", i } - resolvers.reference(var) - var.p = "" - else - var.error = "unknown inner or special" - end - end + return var + end + end + local data = productreferences and productreferences[component] + if data then + local vi = data[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"4d") end + return var end end end - bug = bug or var.error + var.error = "unknown inner" + else + var.error = "no inner" + end + if trace_identifying then + report_identify_outer(set,var,i,"4e") + end + return var +end + +local function identify_inner_component(set,var,i) + -- we're in a product (maybe ignore when same as component) + local component = var.component + identify_inner(set,var,component,collected,derived,tobesaved) + if trace_identifying then + report_identify_outer(set,var,i,"5a") + end + return var +end + +local function identify_outer_component(set,var,i) + local component = var.component + local inner = var.inner + local data = productdata.componentreferences[component] + if data then + local d = data[""] + local vi = d and d[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"6a") + end + return var + end + end + local data = productdata.productreferences[component] + if data then + local vi = data[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"6b") + end + return var + end + end + var.error = "unknown component" + if trace_identifying then + report_identify_outer(set,var,i,"6c") + end + return var +end + +local nofidentified = 0 + +local function identify(prefix,reference) + local set = resolve(prefix,reference) + local bug = false + texcount.referencehastexstate = set.has_tex and 1 or 0 + nofidentified = nofidentified + 1 + set.n = nofidentified + for i=1,#set do + local var = set[i] + if var.special then + var = identify_special(set,var,i) + elseif var.outer then + var = identify_outer(set,var,i) + elseif var.arguments then + var = identify_arguments(set,var,i) + elseif not var.component then + var = identify_inner_or_outer(set,var,i) + elseif currentcomponent() then + var = identify_inner_component(set,var,i) + else + var = identify_outer_component(set,var,i) + end set[i] = var + bug = bug or var.error end ---~ references.analyze(set) references.currentset = mark(set) -- mark, else in api doc if trace_analyzing then report_references(table.serialize(set,reference)) @@ -1281,13 +1420,20 @@ end function references.reportproblems() -- might become local if nofunknowns > 0 then - interfaces.showmessage("references",5,nofunknowns) -- 5 = unknown, 6 = illegal - -- -- we need a proper logger specific for the log file - -- texio.write_nl("log",format("%s unknown references",nofunknowns)) - -- for k, v in table.sortedpairs(unknowns) do - -- texio.write_nl("log",format("%s (n=%s)",k,v)) - -- end - -- texio.write_nl("log","") + statistics.register("cross referencing", function() + return format("%s identified, %s unknown",nofidentified,nofunknowns) + end) + logspushtarget("logfile") + logsnewline() + report_references("start problematic references") + logsnewline() + for k, v in table.sortedpairs(unknowns) do + report_unknown("%4i: %s",v,k) + end + logsnewline() + report_references("stop problematic references") + logsnewline() + logspoptarget() end end @@ -1316,14 +1462,14 @@ directives.register("references.linkmethod", function(v) -- page mixed names references.setinnermethod(v) end) -function references.setinternalreference(prefix,tag,internal,view) +function references.setinternalreference(prefix,tag,internal,view) -- needs checking if innermethod == "page" then return unsetvalue else local t, tn = { }, 0 -- maybe add to current if tag then if prefix and prefix ~= "" then - prefix = prefix .. ":" + prefix = prefix .. ":" -- watch out, : here for ref in gmatch(tag,"[^,]+") do tn = tn + 1 t[tn] = prefix .. ref @@ -1377,8 +1523,8 @@ function references.filter(name,...) -- number page title ... if name == "realpage" then local cs = references.analyze() -- normally already analyzed but also sets state context(cs.realpage or 0) -- todo, return and in command namespace - else - local kind = data.metadata and data.metadata.kind + else -- assumes data is table + local kind = type(data) == "table" and data.metadata and data.metadata.kind if kind then local filter = filters[kind] or filters.generic filter = filter and (filter[name] or filter.unknown or filters.generic[name] or filters.generic.unknown) @@ -1423,7 +1569,6 @@ function filters.generic.number(data,what,prefixspec) -- todo: spec and then no if data then local numberdata = data.numberdata if numberdata then ---~ print(table.serialize(prefixspec)) helpers.prefix(data,prefixspec) sections.typesetnumber(numberdata,"number",numberdata) else @@ -1439,7 +1584,7 @@ filters.generic.default = filters.generic.text function filters.generic.page(data,prefixspec,pagespec) local pagedata = data.pagedata - if pagedata then -- imported + if pagedata then local number, conversion = pagedata.number, pagedata.conversion if not number then -- error @@ -1514,17 +1659,17 @@ filters.float = { default = filters.generic.number } filters.description = { default = filters.generic.number } filters.item = { default = filters.generic.number } -function references.sectiontitle(n) - helpers.sectiontitle(lists.collected[tonumber(n) or 0]) -end +-- function references.sectiontitle(n) +-- helpers.sectiontitle(lists.collected[tonumber(n) or 0]) +-- end -function references.sectionnumber(n) - helpers.sectionnumber(lists.collected[tonumber(n) or 0]) -end +-- function references.sectionnumber(n) +-- helpers.sectionnumber(lists.collected[tonumber(n) or 0]) +-- end -function references.sectionpage(n,prefixspec,pagespec) - helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec) -end +-- function references.sectionpage(n,prefixspec,pagespec) +-- helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec) +-- end -- analyze @@ -1543,11 +1688,11 @@ local function checkedpagestate(n,page) if not p then return 0 elseif p > r then - return 3 + return 3 -- after elseif p < r then - return 2 + return 2 -- before else - return 1 + return 1 -- same end end @@ -1593,6 +1738,8 @@ function references.analyze(actions) local realpage = actions.realpage or setreferencerealpage(actions) if realpage == 0 then actions.pagestate = 0 + elseif actions.external then + actions.pagestate = 0 else actions.pagestate = checkedpagestate(actions.n,realpage) end @@ -1753,3 +1900,9 @@ end -- needs a better split ^^^ commands.filterreference = references.filter + +-- done differently now: + +function references.export(usedname) end +function references.import(usedname) end +function references.load (usedname) end diff --git a/tex/context/base/strc-ref.mkiv b/tex/context/base/strc-ref.mkvi index 88ed25819..40f03a6d6 100644 --- a/tex/context/base/strc-ref.mkiv +++ b/tex/context/base/strc-ref.mkvi @@ -27,6 +27,7 @@ \writestatus{loading}{ConTeXt Structure Macros / Cross Referencing} +\registerctxluafile{strc-rsc}{1.001} \registerctxluafile{strc-ref}{1.001} \registerctxluafile{node-ref}{1.001} @@ -93,17 +94,17 @@ %D \reference[here]{some text} %D \stoptyping -\unexpanded\def\textreference {\dosingleargument\dotextreference} -\unexpanded\def\pagereference {\dosingleargument\dopagereference} -\unexpanded\def\reference {\dosingleargument\doreference } -\unexpanded\def\setreference {\dodoubleargument\dosetreference } +\unexpanded\def\textreference {\dosingleargument\do_text_reference} +\unexpanded\def\pagereference {\dosingleargument\do_page_reference} +\unexpanded\def\reference {\dosingleargument\do_full_reference} +\unexpanded\def\setreference {\dodoubleargument\do_set_reference } %D These are implemented in a low level form as: -\def\dotextreference [#1]{\dodosetreference\s!text{#1}{}} -\def\dopagereference [#1]{\dodosetreference\s!page{#1}{}{}} -\def\doreference [#1]{\dodosetreference\s!full{#1}{}} -\def\dosetreference[#1][#2]{\dodosetreference\s!user{#1}{#2}{}} +\def\do_text_reference [#labels]{\do_do_set_reference\s!text{#labels}{}} +\def\do_page_reference [#labels]{\do_do_set_reference\s!page{#labels}{}{}} +\def\do_full_reference [#labels]{\do_do_set_reference\s!full{#labels}{}} +\def\do_set_reference[#labels][#settings]{\do_do_set_reference\s!user{#labels}{#settings}{}} %D Actually there is not much difference between a text and a %D full reference, but it's the concept that counts. The low @@ -112,40 +113,40 @@ \newcount\lastreferenceattribute \newcount\lastdestinationattribute -\def\dofinishfullreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2")}}} -\def\dofinishtextreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2",{})}}} +\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label")}}} +\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label",{})}}} \let\dofinishpagereference\dofinishfullreference \let\dofinishuserreference\dofinishfullreference -\def\dofinishsomereference#1{\executeifdefined{dofinish#1reference}\gobbletwoarguments} +\def\dofinishsomereference#kind{\executeifdefined{dofinish#{kind}reference}\gobbletwoarguments} -\def\dodosetreference +\def\do_do_set_reference {\ifreferencing - \expandafter\dododosetreference + \expandafter\do_do_do_set_reference \else \expandafter\gobblefourarguments \fi} -\def\dododosetreference#1#2#3#4% kind labels userdata text -> todo: userdata +\def\do_do_do_set_reference#kind#labels#userdata#text% labels userdata text -> todo: userdata {\ifreferencing % we could have a more efficient one for page references but for the moment % we don't care too much - \edef\currentreferencekind{#1}% - \edef\currentreferencelabels{#2}% - \edef\currentreferenceuserdata{#3}% + \edef\currentreferencekind {#kind}% + \edef\currentreferencelabels {#labels}% + \edef\currentreferenceuserdata {#userdata}% \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion} \ifx\currentreferencelabels\empty \else \ifx\currentreferenceexpansion\s!xml \xmlstartraw - \xdef\currentreferencedata{#4}% data, no text else conflict + \xdef\currentreferencedata{#text}% data, no text else conflict \xmlstopraw \globallet\currentreferencecoding\s!xml \else \ifx\currentreferenceexpansion\v!yes - \xdef\currentreferencedata{#4}% + \xdef\currentreferencedata{#text}% \else - \xdef\currentreferencedata{\detokenize{#4}}% + \xdef\currentreferencedata{\detokenize{#text}}% \fi \globallet\currentreferencecoding\s!tex \fi @@ -159,10 +160,10 @@ section = structures.sections.currentid(), }, metadata = { % we could assume page to have no metadata - kind = "#1", + kind = "#kind", \ifx\currentreferencekind\s!page\else catcodes = \the\catcodetable, - xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text + xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument"\else nil\fi, % only useful when text \fi }, \ifx\currentreferencedata\empty\else @@ -171,7 +172,7 @@ }, \fi \ifx\currentreferenceuserdata\empty\else - userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es) + userdata = structures.helpers.touserdata(\!!bs\detokenize{#userdata}\!!es) \fi },"\interactionparameter\c!focus") }% @@ -181,14 +182,14 @@ \fi \fi} -\def\defaultreferencepage#1{[[[#1]]]} -\def\defaultreferencetext#1{[[[#1]]]} +\def\defaultreferencepage#text{[[[#text]]]} +\def\defaultreferencetext#text{[[[#text]]]} %D For internal usage: -\def\dosetsimplepagereference#1% label +\def\dosetsimplepagereference#label% {\iflocation - \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#1", + \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#label", { references = { % block = "\currentsectionblock", @@ -204,20 +205,14 @@ \xdef\currentdestinationattribute{\number\attributeunsetvalue}% \fi} -\def\dogetsimplepagereference#1% +\def\dogetsimplepagereference#label% {\iflocation - \ctxlua{structures.references.inject("\referenceprefix","#1",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \xdef\currentreferenceattribute{\number\lastreferenceattribute}% \else \xdef\currentreferenceattribute{\number\attributeunsetvalue}% \fi} -%D These macros depend on three other ones, -%D \type {\makesectionformat}, that generated \type -%D {\sectionformat}, \type {\pagenumber}. The not yet used -%D argument \type{#1} is a tag that specifies the type of -%D reference. - %D \macros %D {everyreference} %D @@ -230,7 +225,7 @@ %D different alphabet and needs accented entries in registers. \appendtoks - \cleanupfeatures + \cleanupfeatures \to \everyreference %D We did not yet discuss prefixing. Especially in interactive @@ -257,8 +252,7 @@ %D \NC \NC $\star$ \NC \NC\NR %D \stoptabulate -\def\usereferences[#1]% not yet - {\writestatus\m!system{references from other files are handled automatically}} +\unexpanded\def\usereferences[#filename]{} % obsolete %D As mentioned we will also use the cross reference mechanism %D for navigational purposes. The main reason for this is that @@ -319,9 +313,7 @@ %D are references to a file or \URL. The brace delimited %D references for instance refer to a \JAVASCRIPT. The last %D example shows that we can pass arguments to the actions. - -\newif\ifreferencefound - +%D %D Now we've come to the testing step. As we can see below, %D this macro does bit more than testing: it also resolves %D the reference. This means that whenever we test for the @@ -381,16 +373,16 @@ %D true. \unexpanded\def\definereference - {\dodoubleempty\dodefinereference} + {\dodoubleempty\do_define_reference} -\def\dodefinereference[#1][#2]% - {\ctxlua{structures.references.define("\referenceprefix","#1",\!!bs\detokenize{#2}\!!es)}} +\def\do_define_reference[#name][#specification]% + {\ctxlua{structures.references.define("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}} -\def\resetreference[#1]% - {\ctxlua{structures.references.reset("\referenceprefix","#1")}} +\unexpanded\def\resetreference[#name]% + {\ctxlua{structures.references.reset("\referenceprefix","#name")}} -\def\setpagereference#1#2% name, specification - {\ctxlua{structures.references.define("","#1",\!!bs\v!page(\luaescapestring{#2})\!!es)}} +\def\setpagereference#name#specification% hm,. low level ? + {\ctxlua{structures.references.define("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}} %D Chained references are defined as: %D @@ -422,13 +414,14 @@ \def\expandtexincurrentreference % will happen in lua some time {\ifcase\referencehastexstate\else\ctxlua{structures.references.expandcurrent()}\fi} -\def\expandreferenceoperation#1#2{\ctxcommand{setreferenceoperation(#1,\!!bs#2\!!es)}} -\def\expandreferencearguments#1#2{\ctxcommand{setreferencearguments(#1,\!!bs#2\!!es)}} +\def\expandreferenceoperation#tag#content{\ctxcommand{setreferenceoperation(#tag,\!!bs#content\!!es)}} +\def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}} -\def\doifreferencefoundelse#1#2#3% - {\ctxlua{structures.references.doifelse("\referenceprefix","#1",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% - {\expandtexincurrentreference#2}% - {#3}} +\def\doifreferencefoundelse#labels#yes#nop% + {\ctxlua{structures.references.doifelse("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% + {\expandtexincurrentreference + #yes}% + {#nop}} %D The tester only splits the reference in components but does %D not look into them. The following macro does a preroll and @@ -437,9 +430,6 @@ %D one wants to use the pagestate the next macro seldom needs to %D be called. -% \def\analyzecurrentreference -% {\ctxlua{structures.references.analyze()}} - %D The inner case is simple. Only two cases have to be taken %D care of: %D @@ -462,13 +452,6 @@ %D An unknown reference is reported on the screen, in the log %D file and, when enabled, in the left margin of the text. -% \def\unknownreference#1% -% {\iftrialtypesetting \else -% \ifinpagebody \else -% \doifconcepttracing{\doifsomething{#1}{\inleft{\infofont\doboundtext{#1}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}% -% \fi -% \fi} - \let\unknownreference\gobbleoneargument %D When a reference is not found, we typeset a placeholder @@ -543,29 +526,29 @@ \def\setnextinternalreference {\global\advance\locationcount\plusone} -\def\setnextinternalreferences#1#2% plural - {\ctxlua{structures.references.setnextinternal("#1","#2")}} +\def\setnextinternalreferences#kind#name% plural + {\ctxlua{structures.references.setnextinternal("#kind","#name")}} -\def\getinternalorderreference#1#2% - {\ctxlua{structures.references.currentorder("#1","#2")}} +\def\getinternalorderreference#kind#name% + {\ctxlua{structures.references.currentorder("#kind","#name")}} -\def\thisissomeinternal#1#2% tag reference (only for old time sake) +\def\thisissomeinternal#kind#name% only for old time sake {\begingroup - \ctxlua{structures.references.setinternalreference("","#1:#2")}% + \ctxlua{structures.references.setinternalreference("","#kind:#name")}% \hbox attr \destinationattribute\lastdestinationattribute{}% \endgroup} \newconditional\preferpagereferences -\def\gotosomeinternal#1#2#3#4% +\def\gotosomeinternal#kind#name#target#text% {\ifconditional\preferpagereferences - \directgoto{#4}[page(#3)]% + \directgoto{#text}[page(#target)]% \else - \directgoto{#4}[#1:#2]% + \directgoto{#text}[#kind:#name]% \fi} -\def\gotonextinternal#1#2% - {\directgoto{#1}[internal(#2)]} +\def\gotonextinternal#text#target% + {\directgoto{#text}[internal(#target)]} %D In this module we define three system references: one for %D handling navigational, viewer specific, commands, another @@ -586,10 +569,6 @@ %D \goto{some text}[\v!action(PreviousJump] %D \stoptyping -% compatibility hack - -\def\setglobalsystemreference#1#2#3{\definereference[#2][\v!action(#3)]} - \newif\ifreferencing \referencingtrue %D One can also activate an automatic prefix mechanism. By @@ -608,16 +587,13 @@ %D document). By setting the \type{interaction} variable, one %D can influences the way interactive references are set. -\newconstant\autocrossfilereferences % not yet supported in mkiv -\newconstant\referencefilecaseswap % not yet supported in mkiv - \newtoks \everysetupreferencing \unexpanded\def\setupreferencing - {\dosingleargument\dosetupreferencing} + {\dosingleargument\do_setup_referencing} -\def\dosetupreferencing[#1]% - {\getparameters[\??rf][\c!prefix=\s!unknown,#1]% +\def\do_setup_referencing[#settings]% + {\getparameters[\??rf][\c!prefix=\s!unknown,#settings]% \the\everysetupreferencing} \appendtoks @@ -627,65 +603,29 @@ \v!start=>\referencingtrue]% \to \everysetupreferencing -% \newconstant \referencecontentmode -% -% \appendtoks -% \processaction -% [\@@rfinteraction] -% [ \v!all=>\referencecontentmode\zerocount, -% \v!label=>\referencecontentmode\plusone, -% \v!text=>\referencecontentmode\plustwo, -% \v!symbol=>\referencecontentmode\plusthree]% -% \to \everysetupreferencing - -\appendtoks - \autocrossfilereferences\zerocount - \processaction - [\@@rfautofile] % not yet in mkiv - [ \v!yes=>\autocrossfilereferences\plusone, - \v!page=>\autocrossfilereferences\plustwo]% -\to \everysetupreferencing - -\appendtoks - \referencefilecaseswap\zerocount - \processaction[\@@rfconvertfile] % not yet in mkiv - [ \v!yes=>\referencefilecaseswap\plusone, - \v!big=>\referencefilecaseswap\plusone, - \v!small=>\referencefilecaseswap\plustwo]% -\to \everysetupreferencing +\newconditional\autocrossfilereferences \appendtoks - \setupreferenceprefix[\@@rfprefix]% - \doifelse\@@rfglobal\v!yes - {\settrue \autoglobalfilereferences}% - {\setfalse\autoglobalfilereferences}% + \doifelse\@@rfautofile\v!yes\settrue\setfalse\autocrossfilereferences \to \everysetupreferencing -% \appendtoks\ctxlua{structures.references.export("whatever")}\to\everystoptext -% \starttext -% \chapter[test]{test} -% test \in{IN}[more] and \in{IN}[test] or \at{AT}[more] and \at{AT}[test]\par -% test \in{IN}[whatever::more] and \in{IN}[whatever::test] or \at{AT}[whatever::more] and \at{AT}[whatever::test] \page -% reference\reference[more]{oeps} -% \stoptext - \def\exportreferences {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}} \appendtoks - \exportreferences + \exportreferences \to \everygoodbye \def\incrementreferenceprefix{+} \def\decrementreferenceprefix{-} -\unexpanded\def\setupreferenceprefix[#1]% - {\edef\@@rfprefix{#1}% +\unexpanded\def\setupreferenceprefix[#prefix]% + {\edef\@@rfprefix{#prefix}% \ifx\@@rfprefix\empty \let\referenceprefix\empty \else\ifx\@@rfprefix\incrementreferenceprefix \advance\prefixcounter \plusone % should be global - \edef\referenceprefix{\the\prefixcounter:}% + \edef\referenceprefix{\the\prefixcounter}% \let\@@rfprefix\s!unknown \else\ifx\@@rfprefix\decrementreferenceprefix \let\referenceprefix\empty @@ -693,60 +633,18 @@ \else\ifx\@@rfprefix\s!unknown % forget about it \else - \edef\referenceprefix{\@@rfprefix:}% + \edef\referenceprefix{\@@rfprefix}% expanded ! \fi\fi\fi\fi} -\unexpanded\def\setupglobalreferenceprefix[#1]% - {\xdef\referenceprefix{#1:}} +\unexpanded\def\setupglobalreferenceprefix[#prefix]% + {\xdef\referenceprefix{#prefix}} -%D The most straightforward way of retrieving references is -%D using \type{\ref}. Consider the reference: -%D -%D \startbuffer -%D \reference[my ref]{{Look}{Here}{I am}} -%D \stopbuffer -%D -%D \typebuffer -%D -%D \getbuffer -%D -%D We can ask for upto five reference components: -%D -%D \startbuffer -%D user page reference: \ref[p][my ref] -%D text reference: \ref[t][my ref] -%D real page reference: \ref[r][my ref] -%D sub text reference: \ref[s][my ref] -%D extra text reference: \ref[e][my ref] -%D \stopbuffer -%D -%D \typebuffer -%D -%D And get back: -%D -%D \startlines -%D \getbuffer -%D \stoplines -%D -%D This is a cheap compatibility hack. Don't use this command -%D as there will be more advanced access to user data. - -\def\ref{\dodoubleargument\doref} +\unexpanded\def\pushreferenceprefix#prefix% + {\pushmacro\referenceprefix + \xdef\referenceprefix{#prefix}} -\def\reftypep{\currentreferencepage} -\def\reftypet{\currentreferencetext} -\def\reftyper{\currentreferencepage} -\def\reftypes{\currentreferencetext} -\def\reftypee{\currentreferencetext} - -\def\doref[#1][#2]% - {\ifsecondargument - \doifreferencefoundelse{#2} - {\executeifdefined{reftype#1}\reftypep} - {\dummyreference}% - \else - \dummyreference - \fi} +\unexpanded\def\popreferenceprefix + {\popmacro\referenceprefix} %D We can typeset a reference using \type{\in}, \type{\at} and %D \type{\about} and goto specific locations using @@ -792,20 +690,28 @@ %D and~\type{[} becomes active (and when asked for, typeset %D in a different color and typeface). -% \unexpanded\def\in {\mathortext\donormalmathin \dospecialin} -% \unexpanded\def\at {\mathortext\donormalmathat \dospecialat} -% \unexpanded\def\about{\mathortext\donormalmathabout\dospecialabout} -% \unexpanded\def\from {\mathortext\donormalmathfrom \dospecialfrom} -% \unexpanded\def\over {\mathortext\donormalmathover \dospecialabout} +% \unexpanded\def\in {\mathortext\donormalmathin \reference_in} +% \unexpanded\def\at {\mathortext\donormalmathat \reference_at} +% \unexpanded\def\about{\mathortext\donormalmathabout\reference_about} +% \unexpanded\def\from {\mathortext\donormalmathfrom \reference_from} +% \unexpanded\def\over {\mathortext\donormalmathover \reference_about} + +% \definecommand in {\reference_in} +% \definecommand at {\reference_at} +% \definecommand about {\reference_about} +% \definecommand from {\reference_from} +% \definecommand over {\reference_about} % needed here, else math problems -% \definecommand in {\dospecialin} -% \definecommand at {\dospecialat} -% \definecommand about {\dospecialabout} -% \definecommand from {\dospecialfrom} -% \definecommand over {\dospecialabout} % needed here, else math problems +\appendtoks + \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \reference_in } \else \let\in \reference_in \fi + \ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \reference_at } \else \let\at \reference_at \fi + \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\reference_about} \else \let\about\reference_about \fi + \ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \reference_from } \else \let\from \reference_from \fi + \ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \reference_about} \else \let\over \reference_about \fi +\to \everydump - \def\filterreference #1{\ctxcommand{filterreference("#1")}} -\unexpanded\def\getreferenceentry#1{\ctxcommand{filterreference("#1")}} + \def\filterreference #key{\ctxcommand{filterreference("#key")}} % no checking, expanded +\unexpanded\def\getreferenceentry#key{\ctxcommand{filterreference("#key")}} % no checking, unexpanded \def\currentreferencenumber {\filterreference{number}} \def\currentreferencepage {\filterreference{page}} @@ -814,15 +720,32 @@ \def\currentreferencedefault {\filterreference{default}} \def\currentreferencerealpage{\filterreference{realpage}} -\unexpanded\def\dospecialabout[#1]% +%D The most straightforward way of retrieving references is +%D using \type{\ref}. + +\unexpanded\def\getreference % checking, unexpanded + {\dodoubleargument\do_get_reference} + +\def\do_get_reference[#key][#label]% #key = number page title text default realpage ... + {\ifsecondargument + \doifreferencefoundelse{#label}{\ctxcommand{filterreference("#key")}}\dummyreference + \else + \dummyreference + \fi} + +\let\ref\getreference + +%D Special cases: + +\unexpanded\def\reference_about[#label]% {\dontleavehmode \begingroup \let\crlf\space \let\\\space \postponenotes \@@rfleft - \doifreferencefoundelse{#1} - {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#1]}% not so efficient (dup lookup) + \doifreferencefoundelse{#label} + {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#label]}% not so efficient (dup lookup) {}% todo \@@rfright \endgroup} @@ -834,57 +757,42 @@ %D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending %D on the direction to go. -% 1 = whatever -% 2 = forward, following page -% 3 = backward, preceding page -% 4 = forward, same page -% 5 = backward, same page - -% Yet untested: - -\unexpanded\def\somewhere#1#2#3[#4]% #3 gobbles space around #2 % todo - {\doifreferencefoundelse{#4}% kind of inefficient as \goto also analyzes - {\goto{\ifcase\referencepagestate\relax#1/#2\or#2\or#1\or#2\fi}[#4]} - {[#1/#2]}} - -\unexpanded\def\atpage[#1]% todo - {\doifreferencefoundelse{#1}% kind of inefficient as \goto also analyzes - {\goto{\ifcase\referencepagestate\relax - \labeltexts\v!page\dummyreference - \or - \labeltexts\v!atpage\currentreferencepage - \or - \labeltexts\v!atpage\currentreferencepage - \or - \labeltexts\v!atpage\currentreferencepage - \or - \labeltext\v!hereafter - \or - \labeltext\v!hencefore - \fi}[#1]} - {[?]}} +% 0 = unknown +% 1 = same +% 2 = before +% 3 = after + +\def\do_by_reference_page_state#unknown#before#current#after% + {\ifcase\referencepagestate\relax#unknown\or#current\or#before\or#after\fi} + +\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward + {\doifreferencefoundelse{#label}% usage needs checking (useless) + {\goto{\do_by_reference_page_state{#label}{#backward}{}{#foreward}}[#label]} + {[#label]}} + +\unexpanded\def\atpage[#label]% todo + {\doifreferencefoundelse{#label}% kind of inefficient as \goto also analyzes + {\goto + {\do_by_reference_page_state + {\labeltexts\v!page\dummyreference}% + {\labeltext\v!hencefore}% + {\labeltexts\v!atpage\currentreferencepage}% + {\labeltext\v!hereafter}}% + [#label]} + {[#label]}} \unexpanded\def\referencesymbol {\hbox{\strut\high {\setupsymbolset[\interactionparameter\c!symbolset]% - \symbol - [\ifcase\referencepagestate\relax - \v!somewhere - \or % same - \v!nowhere - \or % before - \v!previous - \or % after - \v!next% - \fi]}}} + \symbol[\do_by_reference_page_state\v!somewhere\v!nowhere\v!previous\v!next]}}} %D The other alternatives just conform their names: only the %D label, only the text, or the label and the text. % \dounknownreference -> \dummyreference -\def\symbolreference[#1]% for old times sake - {\goto{\referencesymbol}[#1]} +\def\symbolreference[#label]% for old times sake + {\goto{\referencesymbol}[#label]} % \referencecontentmode 0=all 1=label 2=text 3=symbol @@ -898,15 +806,6 @@ \let\leftofreference \empty \let\rightofreference \empty -% \setvalue{\??rf\c!interaction\v!all}% -% {\leftofreference -% \the\leftreferencetoks -% \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing -% \currentreferencecontent -% \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing -% \the\rightreferencetoks -% \rightofreference} - \setvalue{\??rf\c!interaction\v!all}% {\the\leftreferencetoks \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing @@ -946,41 +845,41 @@ \glet\rightofreference\relax \to \everyresetinatreference -\def\dostartgotoreference +\def\start_goto_reference {\dontleavehmode \begingroup} -\def\dostopgotoreference +\def\stop_goto_reference {\the\everyresetinatreference \endgroup} -\def\dopickupgotoreference - {\dodoublegroupempty\dodopickupgotoreference} +\def\pickup_goto_reference + {\dodoublegroupempty\do_pickup_goto_reference} -\def\dodopickupgotoreference#1#2#3[#4]% #3 gobbles spaces (really needed) +\def\do_pickup_goto_reference#left#right#dummy[#label]% #dummy gobbles spaces (really needed) {\leftreferencetoks \iffirstargument - {#1}% + {#left}% \else \defaultleftreferencetoks \let\leftofreferencecontent\empty \fi \rightreferencetoks \ifsecondargument - {#2}% + {#right}% \else \defaultrightreferencetoks \let\rightofreferencecontent\empty \fi % inefficient: double resolve - \doifreferencefoundelse{#4} % we need to resolve the text - {\goto{\referencesequence}[#4]} + \doifreferencefoundelse{#label} % we need to resolve the text + {\goto{\referencesequence}[#label]} {\let\currentreferencecontent\dummyreference - \goto{\referencesequence}[#4]}% - \dostopgotoreference} + \goto{\referencesequence}[#label]}% + \stop_goto_reference} -\unexpanded\def\dospecialin{\dostartgotoreference\let\currentreferencecontent\currentreferencedefault\dopickupgotoreference} -\unexpanded\def\dospecialat{\dostartgotoreference\let\currentreferencecontent\currentreferencepage \dopickupgotoreference} +\unexpanded\def\reference_in{\start_goto_reference\let\currentreferencecontent\currentreferencedefault\pickup_goto_reference} +\unexpanded\def\reference_at{\start_goto_reference\let\currentreferencecontent\currentreferencepage \pickup_goto_reference} %D \macros %D {definereferenceformat} @@ -1028,7 +927,7 @@ \installcommandhandler \??re {referenceformat} \??re \appendtoks - \setuevalue\currentreferenceformat{\doexecutereferenceformat{\currentreferenceformat}}% + \setuevalue\currentreferenceformat{\execute_reference_format{\currentreferenceformat}}% \to \everydefinereferenceformat \setupreferenceformat @@ -1042,9 +941,9 @@ \c!setups=, \c!color=] -\unexpanded\def\doexecutereferenceformat#1% - {\dostartgotoreference - \edef\currentreferenceformat{#1}% +\unexpanded\def\execute_reference_format#name% + {\start_goto_reference + \edef\currentreferenceformat{#name}% \gdef\leftofreference {\referenceformatparameter\c!left }% \gdef\rightofreference {\referenceformatparameter\c!right }% \edef\currentreferenceformatlabel {\referenceformatparameter\c!label }% @@ -1084,7 +983,7 @@ % \let\leftofreferencecontent \empty \let\rightofreferencecontent\empty - \dopickupgotoreference} + \pickup_goto_reference} \def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key @@ -1133,10 +1032,22 @@ \newconditional\uselocationstrut \settrue\uselocationstrut -\def\extrareferencearguments{\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\currentviewerlayer"} +\def\extrareferencearguments + {\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\currentviewerlayer"} -\unexpanded\def\directgoto{\ifconditional\uselocationstrut\expandafter\dodirectgoto\else\expandafter\dodirectgotohtdp\fi} -\unexpanded\def\goto {\ifconditional\uselocationstrut\expandafter\dogoto \else\expandafter\dogotohtdp \fi} +\unexpanded\def\directgoto + {\ifconditional\uselocationstrut + \expandafter\dodirectgoto + \else + \expandafter\dodirectgotohtdp + \fi} + +\unexpanded\def\goto + {\ifconditional\uselocationstrut + \expandafter\dogoto + \else + \expandafter\dogotohtdp + \fi} % The unbox trick is needed in order to permit \par inside a reference. Otherwise % the reference attribute migrates to the outer boxes. @@ -1148,51 +1059,51 @@ \def\revivesavedreferenceattribute % sometimes handy as no test etc needed {\attribute\referenceattribute\lastsavedreferenceattribute} -\def\dodirectgoto#1[#2]% no test for valid references +\def\dodirectgoto#content[#label]% no test for valid references {\dontleavehmode \begingroup \attribute\referenceattribute\attributeunsetvalue \global\lastsavedreferenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \setlocationattributes \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute \dostarttagged\t!link\empty % not here - #1% + #content% \dostoptagged \else - #1% + #content% \fi \endgroup} -\def\dodirectgotohtdp#1[#2]% no test for valid references +\def\dodirectgotohtdp#content[#label]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% + \ctxlua{structures.references.inject("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% \setlocationattributes \attribute\referenceattribute\lastreferenceattribute \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - #1% + #content% \dostoptagged \else - #1% + #content% \fi \endgroup} -\def\dogoto#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok +\def\dogoto#content#dummy[#label]% #dummy gobbles spaces {\dontleavehmode \begingroup %\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% \setlocationattributes @@ -1200,113 +1111,115 @@ \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - #1% + #content% \dostoptagged}% - {#1}% + {#content}% \else - #1% + #content% \fi %\egroup\unhbox\referencebox} \endgroup} -\def\dogotohtdp#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok +\def\dogotohtdp#content#dummy[#label]% dummy gobbles spaces {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% \setlocationattributes \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - #1% + #content% \dostoptagged}% - {#1}% + {#content}% \else - #1% + #content% \fi \endgroup} -\unexpanded\def\directgotobox#1[#2]% no test for valid references +\unexpanded\def\directgotobox#content[#label]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% + \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% \setlocationattributes \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#1}% + \hbox attr \referenceattribute \lastreferenceattribute {#content}% \dostoptagged \else - #1% + #content% \fi \endgroup} -\unexpanded\def\directgotospecbox#1#2[#3]% no test for valid references +\unexpanded\def\directgotospecbox#resolver#content[#label]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}% - \setlocationcolorspec{#1}% #1=\resolver; no consequence for strut + \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \setlocationcolorspec{#resolver}% no consequence for strut \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#2}% + \hbox attr \referenceattribute \lastreferenceattribute {#content}% \dostoptagged \else - #2% + #content% \fi \endgroup} -\unexpanded\def\directgotodumbbox#1[#2]% no test for valid references +\unexpanded\def\directgotodumbbox#content[#label]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% + \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#1}% + \hbox attr \referenceattribute \lastreferenceattribute {#content}% \dostoptagged \else - #1% + #content% \fi \endgroup} -\unexpanded\def\gotobox#1[#2]% no test for valid references +\unexpanded\def\gotobox#content[#label]% no test for valid references {\dontleavehmode \begingroup \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#2",\extrareferencearguments)}% + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% {\expandtexincurrentreference \ctxlua{structures.references.injectcurrentset(nil,nil)}% \setlocationattributes \global\lastsavedreferenceattribute\lastreferenceattribute \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#1}% + \hbox attr \referenceattribute \lastreferenceattribute {#content}% \dostoptagged}% - {#1}% + {#content}% \else - #1% + #content% \fi \endgroup} -\unexpanded\def\gotowdhtbox#1#2[#3]% fast variant for overlays +\unexpanded\def\gotowdhtbox#width#height[#label]% fast variant for overlays {\dontleavehmode \begingroup - \setbox\scratchbox\emptyhbox\wd\scratchbox#1\ht\scratchbox#2% + \setbox\scratchbox\emptyhbox + \wd\scratchbox#width% + \ht\scratchbox#height% \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue - \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% {\ctxlua{structures.references.injectcurrentset(nil,nil)}% \global\lastsavedreferenceattribute\lastreferenceattribute \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} @@ -1362,20 +1275,20 @@ %D specified. This is logical when one keeps in mind that a %D valid \URL\ can also be a mail address. -\unexpanded\def\usefile{\dotripleargument\dousefile} % so that they can be used in expanded arguments -\unexpanded\def\useurl {\doquadrupleempty\douseurl } % so that they can be used in expanded arguments +\unexpanded\def\useurl {\doquadrupleempty\do_use_url } % so that they can be used in expanded arguments +\unexpanded\def\usefile{\dotripleargument\do_use_file} % so that they can be used in expanded arguments \let\useURL \useurl \let\useexternaldocument\usefile -\def\douseurl[#1][#2][#3][#4]% - {\ctxlua{structures.references.urls.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es,\!!bs\detokenize{#4}\!!es)}} +\def\do_use_url[#label][#url][#file][#description]% + {\ctxlua{structures.references.urls.define("#label",\!!bs\detokenize{#url}\!!es,\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}} -\def\dousefile[#1][#2][#3]% - {\ctxlua{structures.references.files.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}} +\def\do_use_file[#label][#file][#description]% + {\ctxlua{structures.references.files.define("#label",\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}} -\def\doifurldefinedelse #1{\ctxcommand{doifurldefinedelse ("#1")}} -\def\doiffiledefinedelse#1{\ctxcommand{doiffiledefinedelse("#1")}} +\def\doifurldefinedelse #label{\ctxcommand{doifurldefinedelse ("#label")}} +\def\doiffiledefinedelse#label{\ctxcommand{doiffiledefinedelse("#label")}} %D \macros %D {url,setupurl} @@ -1397,12 +1310,12 @@ \unexpanded\def\setupurl {\dodoubleargument\getparameters[\??ur]} -\unexpanded\def\url[#1]% +\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua) {\dontleavehmode \begingroup \dosetfontattribute\??ur\c!style \dosetcolorattribute\??ur\c!color - \hyphenatedurl{\ctxlua{structures.references.urls.get("#1","\@@uralternative","\@@urspace")}}% + \hyphenatedurl{\ctxlua{structures.references.urls.get("#label","\@@uralternative","\@@urspace")}}% \endgroup} % # fails @@ -1447,20 +1360,20 @@ %D We keep this for compatibility reasons, hence the hackery. -\unexpanded\def\dospecialfrom - {\dosingleempty\dodospecialfrom} +\unexpanded\def\reference_from + {\dosingleempty\do_do_special_from} -\def\dodospecialfrom[#1]% +\def\do_do_special_from[#label]% {\dontleavehmode - \goto{\ctxlua{structures.references.from("#1")}}[fileorurl(#1)]} + \goto{\ctxlua{structures.references.from("#label")}}[fileorurl(#label)]} -\def\dofromurldescription#1% - {#1} +\def\dofromurldescription#content% called at the lua end + {#content} -\def\dofromurlliteral#1% +\def\dofromurlliteral#content% called at the lua end {\dosetfontattribute \??ur\c!style \dosetcolorattribute\??ur\c!color - \hyphenatedurl{#1}} + \hyphenatedurl{#content}} \let\dofromfiledescription\dofromurldescription \let\dofromfileliteral \dofromurlliteral % maybe some day setupfile that inherits from url @@ -1494,17 +1407,17 @@ {\dodoubleargument\getparameters[\??pr]} \unexpanded\def\defineprogram - {\dotripleargument\dodefineprogram} + {\dotripleargument\do_define_program} -\def\dodefineprogram[#1][#2][#3]% - {\ctxlua{structures.references.programs.define("#1","#2","#3")}} +\def\do_define_program[#name][#program][#description]% + {\ctxlua{structures.references.programs.define("#name","#program","#description")}} -\def\program[#1]% incompatible, more consistent, hardy used anyway +\def\program[#name]% incompatible, more consistent, hardy used anyway {\dontleavehmode \begingroup \dosetfontattribute\??pr\c!style \dosetcolorattribute\??pr\c!color - \ctxlua{structures.references.programs.get("#1","\@@pralternative","\@@prspace")}% + \ctxlua{structures.references.programs.get("#name","\@@pralternative","\@@prspace")}% \endgroup} %D As we can see, we directly use the special reference @@ -1541,13 +1454,13 @@ %D \showsetup{gotopage} \unexpanded\def\definepage - {\dodoubleargument\dodefinepage} + {\dodoubleargument\do_define_page} -\def\dodefinepage[#1][#2]% - {\definereference[#1][page(#1)]} +\def\do_define_page[#name][#target]% + {\definereference[#name][page(#target)]} -\def\gotopage#1[#2]% - {\goto{#1}[\v!page(#2)]} +\def\gotopage#text[#target]% + {\goto{#text}[\v!page(#target)]} %D The previous definitions are somewhat obsolete so we don't %D use it here. @@ -1591,9 +1504,9 @@ %D to, that is, when one clicks on the title. \def\coupledocument - {\doquadrupleempty\docoupledocument} + {\doquadrupleempty\do_couple_document} -\def\docoupledocument[#1][#2][#3][#4]% [name] [file] [sections] [description] +\def\do_couple_document[#name][#file][#sections][#description]% {\ifthirdargument % this will be done differently (when it's needed) \fi} @@ -1610,9 +1523,9 @@ %D %D Only when \type {text} is not empty, a space is inserted. -\def\dotextprefix#1% +\def\dotextprefix#text% {\begingroup - \setbox\scratchbox\hbox{#1}% to be solved some day + \setbox\scratchbox\hbox{#text}% to be solved some day \ifdim\wd\scratchbox>\zeropoint \unhbox\scratchbox \doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new @@ -1745,49 +1658,38 @@ % \stop \blank % \stoptext -\unexpanded\def\setupreferencestructureprefix - {\dotripleargument\dosetupreferencestructureprefix} +% todo: parameterhandler -\def\getreferencestructureprefix#1#2#3% +\def\getreferencestructureprefix#kind#name#category% {{ - prefix = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefix", - separatorset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixseparatorset", - conversion = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversion", - conversionset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversionset", - set = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixset", - segments = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixsegments", - connector = \!!bs\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconnector\!!es, + prefix = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix", + separatorset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset", + conversion = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversion", + conversionset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversionset", + set = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset", + segments = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments", + connector = \!!bs\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector\!!es, }} \unexpanded\def\setupreferencestructureprefix - {\dotripleempty\dosetupreferencestructureprefix} + {\dotripleempty\do_setup_reference_structure_prefix} -\def\dosetupreferencestructureprefix[#1][#2][#3]% +\def\do_setup_reference_structure_prefix[#kind][#category][#settings]% {\ifthirdargument - \getparameters[\??rf:\c!prefix:#1:#2][#3]% + \getparameters[\??rf:\c!prefix:#kind:#category][#settings]% \else\ifsecondargument - \getparameters[\??rf:\c!prefix::#1][#2]% + \getparameters[\??rf:\c!prefix::#kind][#category]% \fi\fi} -\def\referencestructureprefixparameter#1#2#3#4% kind name category parameter - {\ifcsname\??rf:\c!prefix:#2:#3#4\endcsname - \csname\??rf:\c!prefix:#2:#3#4\endcsname - \else\ifcsname\??rf:\c!prefix:#1:#3#4\endcsname - \csname\??rf:\c!prefix:#1:#3#4\endcsname - \else\ifcsname\??rf:\c!prefix::#3#4\endcsname - \csname\??rf:\c!prefix::#3#4\endcsname +\def\referencestructureprefixparameter#kind#name#category#parameter% + {\ifcsname\??rf:\c!prefix:#name:#category#parameter\endcsname + \csname\??rf:\c!prefix:#name:#category#parameter\endcsname + \else\ifcsname\??rf:\c!prefix:#kind:#category#parameter\endcsname + \csname \??rf:\c!prefix:#kind:#category#parameter\endcsname + \else\ifcsname\??rf:\c!prefix::#category#parameter\endcsname + \csname \??rf:\c!prefix::#category#parameter\endcsname \fi\fi\fi} -% \def\getreferencestructureprefixspec#1% we can save one call by moving this to the lua end -% {\getreferencestructureprefix -% {\ctxlua{structures.references.getcurrentmetadata("kind")}} -% {\ctxlua{structures.references.getcurrentmetadata("name")}} -% {#1}} -% \def\currentreferencedefault -% {\ctxlua{structures.references.filter("default",\getreferencestructureprefixspec\v!default)}} -% -% this is shortcut for: - \def\currentreferencedefault {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}} diff --git a/tex/context/base/strc-rsc.lua b/tex/context/base/strc-rsc.lua new file mode 100644 index 000000000..aa969569a --- /dev/null +++ b/tex/context/base/strc-rsc.lua @@ -0,0 +1,154 @@ +if not modules then modules = { } end modules ['strc-rsc'] = { + version = 1.001, + comment = "companion to strc-ref.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- The scanner is in a separate module so that we can test without too +-- many dependencies. + +-- The scanner accepts nested outer, but we don't care too much, maybe +-- some day we will have both but currently the innermost wins. + +local lpegmatch, lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.match, lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg +local find = string.find + +local spaces = lpegP(" ")^0 +local lparent = lpegP("(") +local rparent = lpegP(")") +local lbrace = lpegP("{") +local rbrace = lpegP("}") +local tcolon = lpegP(":::") -- component or outer +local dcolon = lpegP("::") -- outer +local scolon = lpegP(":") -- prefix +local backslash = lpegP("\\") + + lparent = spaces * lparent * spaces + rparent = spaces * rparent * spaces + lbrace = spaces * lbrace * spaces + rbrace = spaces * rbrace * spaces + tcolon = spaces * tcolon * spaces + dcolon = spaces * dcolon * spaces + +local endofall = spaces * lpegP(-1) + +local o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient +local a_token = 1 - rbrace +local s_token = 1 - lparent - lbrace +local i_token = 1 - lparent - lbrace - endofall +local f_token = 1 - lparent - lbrace - dcolon +local c_token = 1 - lparent - lbrace - tcolon + +local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work +local component = lpegCg(lpegCc("component") * lpegCs(c_token^1)) +local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1)) +local operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1)) +local arguments = lpegCg(lpegCc("arguments") * lpegCs(a_token^0)) +local special = lpegCg(lpegCc("special") * lpegCs(s_token^1)) +local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1)) + + arguments = (lbrace * arguments * rbrace)^-1 + component = component * tcolon + outer = outer * dcolon + operation = outer^-1 * operation -- special case: page(file::1) and file::page(1) + inner = inner * arguments + special = special * lparent * (operation * arguments)^-1 * rparent + +local referencesplitter = spaces * lpegCf (lpegCt("") * (component + outer)^-1 * (special + inner)^-1 * endofall, rawset) +local prefixsplitter = lpegCs(lpegP((1-scolon)^1 * scolon)) * #-scolon * lpegCs(lpegP(1)^1) +local componentsplitter = lpegCs(lpegP((1-scolon)^1)) * scolon * #-scolon * lpegCs(lpegP(1)^1) + +prefixsplitter = componentsplitter + +local function splitreference(str) + if str and str ~= "" then + local t = lpegmatch(referencesplitter,str) + if t then + local a = t.arguments + if a and find(a,"\\") then + t.has_tex = true + else + local o = t.arguments + if o and find(o,"\\") then + t.has_tex = true + end + end + return t + end + end +end + +local function splitprefix(str) + return lpegmatch(prefixsplitter,str) +end + +local function splitcomponent(str) + return lpegmatch(componentsplitter,str) +end + +-- register in the right namespace + +structures = structures or { } +structures.references = structures.references or { } +local references = structures.references + +references.referencesplitter = referencesplitter +references.splitreference = splitreference +references.prefixsplitter = prefixsplitter +references.splitprefix = splitprefix +references.componentsplitter = componentsplitter +references.splitcomponent = splitcomponent + +-- test code: + +-- inspect(splitreference([[component:::inner]])) +-- print(splitprefix([[component:::inner]])) +-- print(splitprefix([[component:inner]])) + +-- inspect(splitreference([[ ]])) +-- inspect(splitreference([[ inner ]])) +-- inspect(splitreference([[ special ( operation { argument, argument } ) ]])) +-- inspect(splitreference([[ special ( operation { argument } ) ]])) +-- inspect(splitreference([[ special ( operation { argument, \argument } ) ]])) +-- inspect(splitreference([[ special ( operation { \argument } ) ]])) +-- inspect(splitreference([[ special ( operation ) ]])) +-- inspect(splitreference([[ special ( \operation ) ]])) +-- inspect(splitreference([[ special ( o\peration ) ]])) +-- inspect(splitreference([[ special ( ) ]])) +-- inspect(splitreference([[ inner { argument } ]])) +-- inspect(splitreference([[ inner { \argument } ]])) +-- inspect(splitreference([[ inner { ar\gument } ]])) +-- inspect(splitreference([[inner{a\rgument}]])) +-- inspect(splitreference([[ inner { argument, argument } ]])) +-- inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg? +-- inspect(splitreference([[ inner { \argument, \argument } ]])) +-- inspect(splitreference([[ outer :: ]])) +-- inspect(splitreference([[ outer :: inner]])) +-- inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]])) +-- inspect(splitreference([[ outer :: special (operation { } )]])) +-- inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]])) +-- inspect(splitreference([[ outer :: special ( operation ) ]])) +-- inspect(splitreference([[ outer :: special ( \operation ) ]])) +-- inspect(splitreference([[ outer :: special ( ) ]])) +-- inspect(splitreference([[ outer :: inner { argument } ]])) +-- inspect(splitreference([[ special ( outer :: operation ) ]])) + +-- inspect(splitreference([[]])) +-- inspect(splitreference([[inner]])) +-- inspect(splitreference([[special(operation{argument,argument})]])) +-- inspect(splitreference([[special(operation)]])) +-- inspect(splitreference([[special(\operation)]])) +-- inspect(splitreference([[special()]])) +-- inspect(splitreference([[inner{argument}]])) +-- inspect(splitreference([[inner{\argument}]])) +-- inspect(splitreference([[outer::]])) +-- inspect(splitreference([[outer::inner]])) +-- inspect(splitreference([[outer::special(operation{argument,argument})]])) +-- inspect(splitreference([[outer::special(operation{argument,\argument})]])) +-- inspect(splitreference([[outer::special(operation)]])) +-- inspect(splitreference([[outer::special(\operation)]])) +-- inspect(splitreference([[outer::special()]])) +-- inspect(splitreference([[outer::inner{argument}]])) +-- inspect(splitreference([[special(outer::operation)]])) diff --git a/tex/context/base/tabl-tsp.mkiv b/tex/context/base/tabl-tsp.mkiv index 47984a8be..f43ff8138 100644 --- a/tex/context/base/tabl-tsp.mkiv +++ b/tex/context/base/tabl-tsp.mkiv @@ -148,7 +148,8 @@ \def\dochecksplitofffloat#1% box {\ifinsidesplitfloat - \ifdim\ht#1=\zeropoint + % \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow + \ifcase\ht#1\relax \global\setfalse\somenextplitofffloat \else \global\settrue \somenextplitofffloat diff --git a/tex/context/base/type-one.mkii b/tex/context/base/type-one.mkii index b8a582d83..e98f6864a 100644 --- a/tex/context/base/type-one.mkii +++ b/tex/context/base/type-one.mkii @@ -2748,4 +2748,128 @@ \stoptypescriptcollection +\starttypescriptcollection[dejavu] + + \definetypescriptprefix [e:ec] [t1] + \definetypescriptprefix [e:qx] [qx] + \definetypescriptprefix [e:t2a] [t2a] + + \starttypescript [serif] [dejavu] [ec,qx,t2a] + \definefontsynonym [DejaVuSerif] [DejaVuSerif-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerif-Italic] [DejaVuSerif-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerif-Bold] [DejaVuSerif-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerif-BoldItalic] [DejaVuSerif-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [serif] [dejavu-condensed] [ec,qx,t2a] + \definefontsynonym [DejaVuSerifCondensed] [DejaVuSerifCondensed-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerifCondensed-Italic] [DejaVuSerifCondensed-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerifCondensed-Bold] [DejaVuSerifCondensed-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerifCondensed-BoldItalic] [DejaVuSerifCondensed-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [sans] [dejavu] [ec,qx,t2a] + \definefontsynonym [DejaVuSans] [DejaVuSans-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSans-Italic] [DejaVuSans-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSans-Bold] [DejaVuSans-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSans-BoldItalic] [DejaVuSans-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [sans] [dejavu-condensed] [ec,qx,t2a] + \definefontsynonym [DejaVuSansCondensed] [DejaVuSansCondensed-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansCondensed-Italic] [DejaVuSansCondensed-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansCondensed-Bold] [DejaVuSansCondensed-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansCondensed-BoldItalic] [DejaVuSansCondensed-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [mono] [dejavu,dejavu-condensed] [ec,qx,t2a] + \definefontsynonym [DejaVuSansMono] [DejaVuSansMono-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansMono-Italic] [DejaVuSansMono-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansMono-Bold] [DejaVuSansMono-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansMono-BoldItalic] [DejaVuSansMono-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [serif] [dejavu] [name] + \definefontsynonym [Serif] [DejaVuSerif] + \definefontsynonym [SerifItalic] [DejaVuSerif-Italic] + \definefontsynonym [SerifBold] [DejaVuSerif-Bold] + \definefontsynonym [SerifBoldItalic] [DejaVuSerif-BoldItalic] + + \definefontsynonym [SerifSlanted] [SerifItalic] + \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic] + \definefontsynonym [SerifCaps] [Serif] + \stoptypescript + + \starttypescript [serif] [dejavu-condensed] [name] + \definefontsynonym [Serif] [DejaVuSerifCondensed] + \definefontsynonym [SerifItalic] [DejaVuSerifCondensed-Italic] + \definefontsynonym [SerifBold] [DejaVuSerifCondensed-Bold] + \definefontsynonym [SerifBoldItalic] [DejaVuSerifCondensed-BoldItalic] + + \definefontsynonym [SerifSlanted] [SerifItalic] + \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic] + \definefontsynonym [SerifCaps] [Serif] + \stoptypescript + + \starttypescript [sans] [dejavu] [name] + \definefontsynonym [Sans] [DejaVuSans] + \definefontsynonym [SansItalic] [DejaVuSans-Italic] + \definefontsynonym [SansBold] [DejaVuSans-Bold] + \definefontsynonym [SansBoldItalic] [DejaVuSans-BoldItalic] + + \definefontsynonym [SansSlanted] [SansItalic] + \definefontsynonym [SansBoldSlanted] [SansBoldItalic] + \definefontsynonym [SansCaps] [Sans] + \stoptypescript + + \starttypescript [sans] [dejavu-condensed] [name] + \definefontsynonym [Sans] [DejaVuSansCondensed] + \definefontsynonym [SansItalic] [DejaVuSansCondensed-Italic] + \definefontsynonym [SansBold] [DejaVuSansCondensed-Bold] + \definefontsynonym [SansBoldItalic] [DejaVuSansCondensed-BoldItalic] + + \definefontsynonym [SansSlanted] [SansItalic] + \definefontsynonym [SansBoldSlanted] [SansBoldItalic] + \definefontsynonym [SansCaps] [Sans] + \stoptypescript + + \starttypescript [mono] [dejavu,dejavu-condensed] [name] + \definefontsynonym [Mono] [DejaVuSansMono] + \definefontsynonym [MonoItalic] [DejaVuSansMono-Italic] + \definefontsynonym [MonoBold] [DejaVuSansMono-Bold] + \definefontsynonym [MonoBoldItalic] [DejaVuSansMono-BoldItalic] + + \definefontsynonym [MonoSlanted] [MonoItalic] + \definefontsynonym [MonoBoldSlanted] [MonoBoldItalic] + \definefontsynonym [MonoCaps] [Mono] + \stoptypescript + + \starttypescript [dejavu] [ec,qx,t2a] + \definetypeface [dejavu] [rm] [serif] [dejavu] [default] [encoding=\typescripttwo] + \definetypeface [dejavu] [ss] [sans] [dejavu] [default] [encoding=\typescripttwo] + \definetypeface [dejavu] [tt] [mono] [dejavu] [default] [encoding=\typescripttwo] + \definetypeface [dejavu] [mm] [math] [xits] [default] [rscale=auto] + \loadmapfile [dejavu-truetype.map] + \stoptypescript + + \starttypescript [dejavu-condensed] [ec,qx,t2a] + \definetypeface [dejavu-condensed] [rm] [serif] [dejavu-condensed] [default] [encoding=\typescripttwo] + \definetypeface [dejavu-condensed] [ss] [sans] [dejavu-condensed] [default] [encoding=\typescripttwo] + \definetypeface [dejavu-condensed] [tt] [mono] [dejavu-condensed] [default] [encoding=\typescripttwo] + \definetypeface [dejavu-condensed] [mm] [math] [xits] [default] [rscale=auto] + \loadmapfile [dejavu-truetype.map] + \stoptypescript + +\stoptypescriptcollection + \endinput diff --git a/tex/context/base/util-pck.lua b/tex/context/base/util-pck.lua index c802a09ed..d964c7a23 100644 --- a/tex/context/base/util-pck.lua +++ b/tex/context/base/util-pck.lua @@ -62,34 +62,38 @@ packers.simplehashed = simplehashed --~ end local function pack(t,keys,hash,index) - for k,v in next, t do - if type(v) == "table" then - pack(v,keys,hash,index) - if keys[k] then - local h = hashed(v) - local i = hash[h] - if not i then - i = #index + 1 - index[i] = v - hash[h] = i + if t then + for k,v in next, t do + if type(v) == "table" then + pack(v,keys,hash,index) + if keys[k] then + local h = hashed(v) + local i = hash[h] + if not i then + i = #index + 1 + index[i] = v + hash[h] = i + end + t[k] = i end - t[k] = i end end end end local function unpack(t,keys,index) - for k,v in next, t do - if keys[k] and type(v) == "number" then - local iv = index[v] - if iv then - v = iv - t[k] = v + if t then + for k, v in next, t do + if keys[k] and type(v) == "number" then + local iv = index[v] + if iv then + v = iv + t[k] = v + end + end + if type(v) == "table" then + unpack(v,keys,index) end - end - if type(v) == "table" then - unpack(v,keys,index) end end end diff --git a/tex/context/base/util-sto.lua b/tex/context/base/util-sto.lua index 8710f78af..4c0052f0e 100644 --- a/tex/context/base/util-sto.lua +++ b/tex/context/base/util-sto.lua @@ -14,8 +14,8 @@ local storage = utilities.storage function storage.mark(t) if not t then - texio.write_nl("fatal error: storage '%s' cannot be marked",t) - os.exit() + texio.write_nl("fatal error: storage cannot be marked") + return -- os.exit() end local m = getmetatable(t) if not m then @@ -44,8 +44,8 @@ end function storage.checked(t) if not t then - texio.write_nl("fatal error: storage '%s' has not been allocated",t) - os.exit() + texio.write_nl("fatal error: storage has not been allocated") + return -- os.exit() end return t end diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index 3610c24dd..28a6b8cc5 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -29,14 +29,31 @@ function tables.definetable(target) -- defines undefined tables return concat(t,"\n") end -function tables.accesstable(target) - local t = _G +function tables.accesstable(target,root) + local t = root or _G for name in gmatch(target,"([^%.]+)") do t = t[name] + if not t then + return + end end return t end +function tables.migratetable(target,v,root) + local t = root or _G + local names = string.split(target,".") + for i=1,#names-1 do + local name = names[i] + t[name] = t[name] or { } + t = t[name] + if not t then + return + end + end + t[names[#names]] = v +end + function tables.removevalue(t,value) -- todo: n if value then for i=1,#t do diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index b60a0b79b..ab366de23 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 09/27/11 20:05:02 +-- merge date : 10/01/11 10:48:20 do -- begin closure to overcome local limits and interference |