From dbbbbfac3d158709a07af8c26e68284d1b0ea202 Mon Sep 17 00:00:00 2001 From: Marius Date: Mon, 11 Apr 2011 18:00:19 +0300 Subject: beta 2011.04.11 16:45 --- metapost/context/base/mp-mlib.mp | 18 +- metapost/context/base/mp-tool.mp | 1 + scripts/context/lua/mtxrun.lua | 306 +++++++--- scripts/context/stubs/mswin/mtxrun.lua | 306 +++++++--- scripts/context/stubs/unix/mtxrun | 306 +++++++--- tex/context/base/anch-pos.lua | 20 +- tex/context/base/attr-col.lua | 19 +- tex/context/base/attr-eff.lua | 36 +- tex/context/base/attr-ini.mkiv | 1 + tex/context/base/attr-lay.lua | 7 +- tex/context/base/attr-neg.lua | 32 +- tex/context/base/back-exp.lua | 798 +++++++++++++++++-------- tex/context/base/back-exp.mkiv | 27 +- tex/context/base/back-ini.lua | 40 +- tex/context/base/back-pdf.lua | 2 + tex/context/base/buff-ver.lua | 33 +- tex/context/base/buff-ver.mkiv | 16 +- tex/context/base/char-ini.lua | 64 +- tex/context/base/cldf-ini.lua | 58 +- tex/context/base/cldf-ini.mkiv | 3 + tex/context/base/cldf-int.lua | 55 +- tex/context/base/cldf-int.mkiv | 12 +- tex/context/base/cont-new.mkii | 2 +- tex/context/base/cont-new.mkiv | 2 +- tex/context/base/context.mkii | 2 +- tex/context/base/context.mkiv | 2 +- tex/context/base/core-con.lua | 173 +++++- tex/context/base/core-con.mkiv | 241 ++++---- tex/context/base/core-env.lua | 114 ++-- tex/context/base/core-two.lua | 11 +- tex/context/base/core-uti.lua | 32 +- tex/context/base/data-env.lua | 26 +- tex/context/base/data-res.lua | 30 +- tex/context/base/data-tmp.lua | 6 +- tex/context/base/font-col.lua | 4 +- tex/context/base/font-col.mkiv | 4 +- tex/context/base/font-con.lua | 27 +- tex/context/base/font-ctx.lua | 40 +- tex/context/base/font-def.lua | 23 +- tex/context/base/font-enc.lua | 6 +- tex/context/base/font-gds.lua | 73 ++- tex/context/base/font-ini.mkiv | 2 +- tex/context/base/font-log.lua | 2 +- tex/context/base/font-mis.lua | 2 +- tex/context/base/font-ota.lua | 9 +- tex/context/base/font-otc.lua | 304 +++++----- tex/context/base/font-otd.lua | 18 +- tex/context/base/font-otf.lua | 122 ++-- tex/context/base/font-otn.lua | 56 +- tex/context/base/font-ott.lua | 43 +- tex/context/base/font-vf.lua | 29 +- tex/context/base/grph-fil.lua | 9 +- tex/context/base/grph-inc.lua | 29 +- tex/context/base/l-dimen.lua | 434 -------------- tex/context/base/l-file.lua | 2 - tex/context/base/l-md5.lua | 6 +- tex/context/base/l-table.lua | 52 +- tex/context/base/lang-def.lua | 32 +- tex/context/base/lang-def.mkiv | 35 -- tex/context/base/lang-ini.lua | 13 +- tex/context/base/lang-lab.lua | 1 - tex/context/base/lang-url.lua | 6 +- tex/context/base/lang-url.mkiv | 2 +- tex/context/base/luat-bas.mkiv | 2 - tex/context/base/luat-lib.mkiv | 3 +- tex/context/base/luat-mac.lua | 12 +- tex/context/base/lxml-aux.lua | 41 +- tex/context/base/lxml-lpt.lua | 13 +- tex/context/base/math-tag.lua | 10 +- tex/context/base/math-vfu.lua | 31 +- tex/context/base/mlib-pps.lua | 74 +-- tex/context/base/mult-ini.lua | 51 +- tex/context/base/node-aux.lua | 25 +- tex/context/base/node-fnt.lua | 72 ++- tex/context/base/node-ref.lua | 2 +- tex/context/base/node-spl.lua | 2 +- tex/context/base/pack-obj.lua | 9 +- tex/context/base/regi-ini.lua | 9 +- tex/context/base/s-inf-03.mkiv | 352 +++++++++++ tex/context/base/scrn-ini.lua | 9 + tex/context/base/sort-ini.lua | 11 +- tex/context/base/sort-lan.lua | 2 +- tex/context/base/spac-ali.mkiv | 4 +- tex/context/base/spac-grd.mkiv | 9 +- tex/context/base/spac-ver.mkiv | 3 - tex/context/base/status-files.pdf | Bin 23594 -> 23588 bytes tex/context/base/status-lua.pdf | Bin 0 -> 154910 bytes tex/context/base/strc-blk.lua | 20 +- tex/context/base/strc-doc.lua | 16 +- tex/context/base/strc-ini.lua | 9 +- tex/context/base/strc-lst.lua | 19 +- tex/context/base/strc-lst.mkiv | 8 +- tex/context/base/strc-mar.lua | 21 +- tex/context/base/strc-num.lua | 28 +- tex/context/base/strc-pag.lua | 4 +- tex/context/base/strc-ref.lua | 35 +- tex/context/base/strc-ref.mkiv | 60 +- tex/context/base/strc-reg.lua | 16 +- tex/context/base/strc-ren.mkiv | 8 +- tex/context/base/strc-syn.lua | 16 +- tex/context/base/strc-syn.mkiv | 11 + tex/context/base/strc-tag.lua | 29 +- tex/context/base/strc-tag.mkiv | 4 + tex/context/base/supp-box.lua | 4 +- tex/context/base/supp-fil.lua | 4 +- tex/context/base/trac-log.lua | 8 +- tex/context/base/util-deb.lua | 2 +- tex/context/base/util-dim.lua | 436 ++++++++++++++ tex/context/base/util-prs.lua | 16 +- tex/context/base/util-seq.lua | 4 +- tex/context/base/util-sto.lua | 85 ++- tex/context/base/util-tab.lua | 19 +- tex/context/base/x-set-11.mkiv | 27 +- tex/context/base/x-set-12.mkiv | 166 ++--- tex/generic/context/luatex-basics-gen.lua | 6 + tex/generic/context/luatex-fonts-demo-vf-1.lua | 4 +- tex/generic/context/luatex-fonts-merged.lua | 299 +++++---- tex/generic/context/luatex-test.tex | 4 + 118 files changed, 3965 insertions(+), 2355 deletions(-) delete mode 100644 tex/context/base/l-dimen.lua create mode 100644 tex/context/base/s-inf-03.mkiv create mode 100644 tex/context/base/status-lua.pdf create mode 100644 tex/context/base/util-dim.lua diff --git a/metapost/context/base/mp-mlib.mp b/metapost/context/base/mp-mlib.mp index e812df61e..11f096c18 100644 --- a/metapost/context/base/mp-mlib.mp +++ b/metapost/context/base/mp-mlib.mp @@ -31,6 +31,20 @@ newinternal lightentransparent ; lightentransparent := 10 ; newinternal differencetransparent ; differencetransparent := 11 ; newinternal exclusiontransparent ; exclusiontransparent := 12 ; +vardef transparency_alternative_to_number(expr name) = + if string name : + if expandafter known scantokens(name & "transparent") : + scantokens(name & "transparent") + else : + 0 + fi + elseif name < 13 : + name + else : + 0 + fi +enddef ; + def spotcolor(expr n, v) = 1 withprescript "sp_name=" & n @@ -47,12 +61,12 @@ enddef ; def transparent(expr alternative, transparency)(text c) = c - withprescript "tr_alternative=" & decimal alternative + withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative) withprescript "tr_transparency=" & decimal transparency enddef ; def withtransparency(expr alternative, transparency) = - withprescript "tr_alternative=" & decimal alternative + withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative) withprescript "tr_transparency=" & decimal transparency enddef ; diff --git a/metapost/context/base/mp-tool.mp b/metapost/context/base/mp-tool.mp index 1a748baf9..7f047fefc 100644 --- a/metapost/context/base/mp-tool.mp +++ b/metapost/context/base/mp-tool.mp @@ -251,6 +251,7 @@ def newtransform text v = forsuffixes i=v : save i ; transform i ; endfor ; endd def newpath text v = forsuffixes i=v : save i ; path i ; endfor ; enddef ; def newpicture text v = forsuffixes i=v : save i ; picture i ; endfor ; enddef ; def newstring text v = forsuffixes i=v : save i ; string i ; endfor ; enddef ; +def newpair text v = forsuffixes i=v : save i ; pair i ; endfor ; enddef ; %D Sometimes we don't want parts of the graphics add to the %D bounding box. One way of doing this is to save the bounding diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 6a3df03d0..e0fc8d823 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -971,10 +971,6 @@ function table.fromhash(t) return hsh end -table.serialize_functions = true -table.serialize_compact = true -table.serialize_inline = true - local noquotes, hexify, handle, reduce, compact, inline, functions local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key @@ -1257,15 +1253,36 @@ end -- replacing handle by a direct t[#t+1] = ... (plus test) is not much -- faster (0.03 on 1.00 for zapfino.tma) -local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) - noquotes = _noquotes - hexify = _hexify - handle = _handle or print - reduce = _reduce or false - compact = table.serialize_compact - inline = compact and table.serialize_inline - functions = table.serialize_functions +local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) -- I might drop the _'s some day. local tname = type(name) + if tname == "table" then + noquotes = name.noquotes + hexify = name.hexify + handle = name.handle or print + reduce = name.reduce or false + functions = name.functions + compact = name.compact + inline = name.inline and compact + name = name.name + tname = type(name) + if functions == nil then + functions = true + end + if compact == nil then + compact = true + end + if inline == nil then + inline = compact + end + else + noquotes = _noquotes + hexify = _hexify + handle = _handle or print + reduce = _reduce or false + compact = true + inline = true + functions = true + end if tname == "string" then if name == "return" then handle("return {") @@ -1324,12 +1341,11 @@ end -- -- so this is on the todo list -table.tofile_maxtab = 2*1024 +local maxtab = 2*1024 function table.tofile(filename,root,name,reduce,noquotes,hexify) local f = io.open(filename,'w') if f then - local maxtab = table.tofile_maxtab if maxtab > 1 then local t, n = { }, 0 local function flush(s) @@ -1532,8 +1548,12 @@ function table.sequenced(t,sep,simple) -- hash only return concat(s, sep or " | ") end -function table.print(...) - table.tohandle(print,...) +function table.print(t,...) + if type(t) ~= "table" then + print(tostring(t)) + else + table.tohandle(print,t,...) + end end -- -- -- obsolete but we keep them for a while and might comment them later -- -- -- @@ -2535,8 +2555,6 @@ function file.collapsepath(str,anchor) end end -file.collapse_path = file.collapsepath - function file.robustname(str,strict) str = gsub(str,"[^%a%d%/%-%.\\]+","-") @@ -2651,14 +2669,12 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end -file.needs_updating_threshold = 1 - -function file.needs_updating(oldname,newname) -- size modification access change +function file.needs_updating(oldname,newname,threshold) -- size modification access change local oldtime = lfs.attributes(oldname, modification) local newtime = lfs.attributes(newname, modification) if newtime >= oldtime then return false - elseif oldtime - newtime < file.needs_updating_threshold then + elseif oldtime - newtime < (threshold or 1) then return false else return true @@ -3666,7 +3682,7 @@ local tables = utilities.tables local format, gmatch = string.format, string.gmatch local concat, insert, remove = table.concat, table.insert, table.remove -local setmetatable, tonumber, tostring = setmetatable, tonumber, tostring +local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring function tables.definetable(target) -- defines undefined tables local composed, t, n = nil, { }, 0 @@ -3731,12 +3747,6 @@ function tables.insertaftervalue(t,value,extra) insert(t,#t+1,extra) end -local _empty_table_ = { __index = function(t,k) return "" end } - -function table.setemptymetatable(t) - setmetatable(t,_empty_table_) -end - -- experimental local function toxml(t,d,result) @@ -3753,9 +3763,14 @@ local function toxml(t,d,result) end end -function table.toxml(t,name) - local result = { "" } - toxml( { [name or "root"] = t }, "", result) +function table.toxml(t,name,nobanner) + local noroot = name == false + local result = (nobanner or noroot) and { } or { "" } + if noroot then + toxml( t, "", result) + else + toxml( { [name or "root"] = t }, "", result) + end return concat(result,"\n") end @@ -3816,20 +3831,6 @@ function storage.checked(t) return t end -function setmetatablekey(t,key,value) - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m[key] = value -end - -function getmetatablekey(t,key,value) - local m = getmetatable(t) - return m and m[key] -end - function storage.setinitializer(data,initialize) local m = getmetatable(data) or { } @@ -3852,6 +3853,77 @@ function storage.sparse(t) return t end +-- table namespace ? + +local function f_empty () return "" end -- t,k +local function f_self (t,k) t[k] = k return k end +local function f_ignore() end -- t,k,v + +local t_empty = { __index = empty } +local t_self = { __index = self } +local t_ignore = { __newindex = ignore } + +function table.setmetatableindex(t,f) + local m = getmetatable(t) + if m then + if f == "empty" then + m.__index = f_empty + elseif f == "key" then + m.__index = f_self + else + m.__index = f + end + else + if f == "empty" then + setmetatable(t, t_empty) + elseif f == "key" then + setmetatable(t, t_self) + else + setmetatable(t,{ __index = f }) + end + end +end + +function table.setmetatablenewindex(t,f) + local m = getmetatable(t) + if m then + if f == "ignore" then + m.__newindex = f_ignore + else + m.__newindex = f + end + else + if f == "ignore" then + setmetatable(t, t_ignore) + else + setmetatable(t,{ __newindex = f }) + end + end +end + +function table.setmetatablecall(t,f) + local m = getmetatable(t) + if m then + m.__call = f + else + setmetatable(t,{ __call = f }) + end +end + +function table.setmetatablekey(t,key,value) + local m = getmetatable(t) + if not m then + m = { } + setmetatable(t,m) + end + m[key] = value +end + +function table.getmetatablekey(t,key,value) + local m = getmetatable(t) + return m and m[key] +end + end -- of closure @@ -4047,18 +4119,20 @@ if not modules then modules = { } end modules ['util-prs'] = { license = "see context related readme files" } +local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg +local lpegmatch = lpeg.match +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type, next = tostring, type, next + utilities = utilities or {} utilities.parsers = utilities.parsers or { } local parsers = utilities.parsers parsers.patterns = parsers.patterns or { } --- we could use a Cf Cg construct +local setmetatableindex = table.setmetatableindex +local sortedhash = table.sortedhash -local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg -local lpegmatch = lpeg.match -local concat, format, gmatch = table.concat, string.format, string.gmatch -local tostring, type, next, setmetatable = tostring, type, next, setmetatable -local sortedhash = table.sortedhash +-- we could use a Cf Cg construct local escape, left, right = P("\\"), P('{'), P('}') @@ -4257,7 +4331,7 @@ function parsers.getparameters(self,class,parentclass,settings) sp = { } self[parentclass] = sp end - setmetatable(sc, { __index = sp }) + setmetatableindex(sc,sp) end end parsers.settings_to_hash(settings,sc) @@ -4474,7 +4548,7 @@ end local is_node = node and node.is_node -function inspect(i) +function inspect(i) -- global function local ti = type(i) if ti == "table" then table.print(i,"table") @@ -5044,6 +5118,8 @@ local escapedpattern = string.escapedpattern local texcount = tex and tex.count local next, type = next, type +local setmetatableindex = table.setmetatableindex + --[[ldx--

This is a prelude to a more extensive logging module. We no longer provide based logging a sparsing is relatively easy anyway.

@@ -5064,11 +5140,11 @@ wiki : http://contextgarden.net local function ignore() end -setmetatable(logs, { __index = function(t,k) t[k] = ignore ; return ignore end }) +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) -local report, subreport, status, settarget, setformatter +local report, subreport, status, settarget, setformats, settranslations -local direct, subdirect, writer +local direct, subdirect, writer, pushtarget, poptarget if tex and tex.jobname or tex.formatname then @@ -7308,6 +7384,8 @@ local type, next, tonumber, tostring, setmetatable, loadstring = type, next, ton local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local setmetatableindex = table.setmetatableindex + -- beware, this is not xpath ... e.g. position is different (currently) and -- we have reverse-sibling as reversed preceding sibling @@ -7380,8 +7458,8 @@ local function fallback (t, name) return fn end -setmetatable(finalizers.xml, { __index = fallback }) -setmetatable(finalizers.tex, { __index = fallback }) +setmetatableindex(finalizers.xml, fallback) +setmetatableindex(finalizers.tex, fallback) xml.defaultprotocol = "xml" @@ -8078,14 +8156,13 @@ xml.nodesettostring = nodesettostring local lpath -- we have a harmless kind of circular reference +local lshowoptions = { name = false, functions = false } + local function lshow(parsed) if type(parsed) == "string" then parsed = lpath(parsed) end - local s = table.serialize_functions -- ugly - table.serialize_functions = false -- ugly - report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,false)) - table.serialize_functions = s -- ugly + report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,lshowoptions)) end xml.lshow = lshow @@ -8679,8 +8756,8 @@ local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name local xmlinheritedconvert = xml.inheritedconvert local xmlapplylpath = xml.applylpath -local type = type -local insert, remove = table.insert, table.remove +local type, setmetatable, getmetatable = type, setmetatable, getmetatable +local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy local gmatch, gsub = string.gmatch, string.gsub local function report(what,pattern,c,e) @@ -8889,6 +8966,41 @@ function xml.replace(root,pattern,whatever) end end +local function wrap(e,wrapper) + local t = { + rn = e.rn, + tg = e.tg, + ns = e.ns, + at = e.at, + dt = e.dt, + __p__ = e, + } + setmetatable(t,getmetatable(e)) + e.rn = wrapper.rn or e.rn or "" + e.tg = wrapper.tg or e.tg or "" + e.ns = wrapper.ns or e.ns or "" + e.at = fastcopy(wrapper.at) + e.dt = { t } +end + +function xml.wrap(root,pattern,whatever) + if whatever then + local wrapper = xmltoelement(whatever,root) + local collected = xmlapplylpath(root,pattern) + if collected then + for c=1,#collected do + local e = collected[c] + if trace_manipulations then + report('wrapping',pattern,c,e) + end + wrap(e,wrapper) + end + end + else + wrap(root,xmltoelement(pattern)) + end +end + local function inject_element(root,pattern,whatever,prepend) local element = root and xmltoelement(whatever,root) local collected = element and xmlapplylpath(root,pattern) @@ -8959,7 +9071,7 @@ local function include(xmldata,pattern,attribute,recursive,loaddata) local ekat = ek.at local epdt = ek.__p__.dt if not attribute or attribute == "" then - name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- ckeck, probably always tab or str + name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str end if not name then for a in gmatch(attribute or "href","([^|]+)") do @@ -10039,17 +10151,23 @@ if not modules then modules = { } end modules ['data-env'] = { license = "see context related readme files", } -local allocate = utilities.storage.allocate local lower, gsub = string.lower, string.gsub -local fileextname = file.extname - local resolvers = resolvers -local formats = allocate() resolvers.formats = formats -local suffixes = allocate() resolvers.suffixes = suffixes -local dangerous = allocate() resolvers.dangerous = dangerous -local suffixmap = allocate() resolvers.suffixmap = suffixmap +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local fileextname = file.extname + +local formats = allocate() +local suffixes = allocate() +local dangerous = allocate() +local suffixmap = allocate() + +resolvers.formats = formats +resolvers.suffixes = suffixes +resolvers.dangerous = dangerous +resolvers.suffixmap = suffixmap local relations = allocate { -- todo: handlers also here core = { @@ -10261,9 +10379,9 @@ local function simplified(t,k) return rawget(t,lower(gsub(k," ",""))) end -setmetatablekey(formats, "__index", simplified) -setmetatablekey(suffixes, "__index", simplified) -setmetatablekey(suffixmap, "__index", simplified) +setmetatableindex(formats, simplified) +setmetatableindex(suffixes, simplified) +setmetatableindex(suffixmap, simplified) -- A few accessors, mostly for command line tool. @@ -10611,6 +10729,8 @@ function caches.is_writable(filepath,filename) return file.is_writable(tmaname) end +local saveoptions = { name = "return", reduce = true } + function caches.savedata(filepath,filename,data,raw) local tmaname, tmcname = caches.setluanames(filepath,filename) local reduce, simplify = true, true @@ -10619,9 +10739,9 @@ function caches.savedata(filepath,filename,data,raw) end data.cache_uuid = os.uuid() if caches.direct then - file.savedata(tmaname, table.serialize(data,'return',false,true,false)) -- no hex + file.savedata(tmaname,table.serialize(data,saveoptions)) else - table.tofile(tmaname, data,'return',false,true,false) -- maybe not the last true + table.tofile(tmaname,data,saveoptions) end utilities.lua.compile(tmaname,tmcname) end @@ -10865,15 +10985,20 @@ if not modules then modules = { } end modules ['data-res'] = { local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys -local next, type, rawget, setmetatable, getmetatable = next, type, rawget, setmetatable, getmetatable +local next, type, rawget = next, type, rawget local os = os local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join -local collapsepath, joinpath = file.collapsepath, file.joinpath -local allocate = utilities.storage.allocate +local filedirname = file.dirname +local filebasename = file.basename +local fileextname = file.extname +local filejoin = file.join +local collapsepath = file.collapsepath +local joinpath = file.joinpath +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end) @@ -11010,7 +11135,8 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp force_suffixes = true, } - setmetatable(variables, { __index = function(t,k) + setmetatableindex(variables,function(t,k) + local v for i=1,#order do v = order[i][k] if v ~= nil then @@ -11023,10 +11149,10 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) - setmetatable(environment, { __index = function(t,k) - v = osgetenv(k) + setmetatableindex(environment, function(t,k) + local v = osgetenv(k) if v == nil then v = variables[k] end @@ -11036,9 +11162,9 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp v = resolvers.repath(v) -- for taco who has a : separated osfontdir t[k] = v return v - end } ) + end) - setmetatable(expansions, { __index = function(t,k) + setmetatableindex(expansions, function(t,k) local v = environment[k] if type(v) == "string" then v = lpegmatch(variableresolver,v) @@ -11046,7 +11172,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) return newinstance @@ -11552,7 +11678,7 @@ function resolvers.registerfilehash(name,content,someerror) end end -function isreadable(name) +local function isreadable(name) local readable = lfs.isfile(name) -- not file.is_readable(name) asit can be a dir if trace_detail then if readable then diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 6a3df03d0..e0fc8d823 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -971,10 +971,6 @@ function table.fromhash(t) return hsh end -table.serialize_functions = true -table.serialize_compact = true -table.serialize_inline = true - local noquotes, hexify, handle, reduce, compact, inline, functions local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key @@ -1257,15 +1253,36 @@ end -- replacing handle by a direct t[#t+1] = ... (plus test) is not much -- faster (0.03 on 1.00 for zapfino.tma) -local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) - noquotes = _noquotes - hexify = _hexify - handle = _handle or print - reduce = _reduce or false - compact = table.serialize_compact - inline = compact and table.serialize_inline - functions = table.serialize_functions +local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) -- I might drop the _'s some day. local tname = type(name) + if tname == "table" then + noquotes = name.noquotes + hexify = name.hexify + handle = name.handle or print + reduce = name.reduce or false + functions = name.functions + compact = name.compact + inline = name.inline and compact + name = name.name + tname = type(name) + if functions == nil then + functions = true + end + if compact == nil then + compact = true + end + if inline == nil then + inline = compact + end + else + noquotes = _noquotes + hexify = _hexify + handle = _handle or print + reduce = _reduce or false + compact = true + inline = true + functions = true + end if tname == "string" then if name == "return" then handle("return {") @@ -1324,12 +1341,11 @@ end -- -- so this is on the todo list -table.tofile_maxtab = 2*1024 +local maxtab = 2*1024 function table.tofile(filename,root,name,reduce,noquotes,hexify) local f = io.open(filename,'w') if f then - local maxtab = table.tofile_maxtab if maxtab > 1 then local t, n = { }, 0 local function flush(s) @@ -1532,8 +1548,12 @@ function table.sequenced(t,sep,simple) -- hash only return concat(s, sep or " | ") end -function table.print(...) - table.tohandle(print,...) +function table.print(t,...) + if type(t) ~= "table" then + print(tostring(t)) + else + table.tohandle(print,t,...) + end end -- -- -- obsolete but we keep them for a while and might comment them later -- -- -- @@ -2535,8 +2555,6 @@ function file.collapsepath(str,anchor) end end -file.collapse_path = file.collapsepath - function file.robustname(str,strict) str = gsub(str,"[^%a%d%/%-%.\\]+","-") @@ -2651,14 +2669,12 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end -file.needs_updating_threshold = 1 - -function file.needs_updating(oldname,newname) -- size modification access change +function file.needs_updating(oldname,newname,threshold) -- size modification access change local oldtime = lfs.attributes(oldname, modification) local newtime = lfs.attributes(newname, modification) if newtime >= oldtime then return false - elseif oldtime - newtime < file.needs_updating_threshold then + elseif oldtime - newtime < (threshold or 1) then return false else return true @@ -3666,7 +3682,7 @@ local tables = utilities.tables local format, gmatch = string.format, string.gmatch local concat, insert, remove = table.concat, table.insert, table.remove -local setmetatable, tonumber, tostring = setmetatable, tonumber, tostring +local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring function tables.definetable(target) -- defines undefined tables local composed, t, n = nil, { }, 0 @@ -3731,12 +3747,6 @@ function tables.insertaftervalue(t,value,extra) insert(t,#t+1,extra) end -local _empty_table_ = { __index = function(t,k) return "" end } - -function table.setemptymetatable(t) - setmetatable(t,_empty_table_) -end - -- experimental local function toxml(t,d,result) @@ -3753,9 +3763,14 @@ local function toxml(t,d,result) end end -function table.toxml(t,name) - local result = { "" } - toxml( { [name or "root"] = t }, "", result) +function table.toxml(t,name,nobanner) + local noroot = name == false + local result = (nobanner or noroot) and { } or { "" } + if noroot then + toxml( t, "", result) + else + toxml( { [name or "root"] = t }, "", result) + end return concat(result,"\n") end @@ -3816,20 +3831,6 @@ function storage.checked(t) return t end -function setmetatablekey(t,key,value) - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m[key] = value -end - -function getmetatablekey(t,key,value) - local m = getmetatable(t) - return m and m[key] -end - function storage.setinitializer(data,initialize) local m = getmetatable(data) or { } @@ -3852,6 +3853,77 @@ function storage.sparse(t) return t end +-- table namespace ? + +local function f_empty () return "" end -- t,k +local function f_self (t,k) t[k] = k return k end +local function f_ignore() end -- t,k,v + +local t_empty = { __index = empty } +local t_self = { __index = self } +local t_ignore = { __newindex = ignore } + +function table.setmetatableindex(t,f) + local m = getmetatable(t) + if m then + if f == "empty" then + m.__index = f_empty + elseif f == "key" then + m.__index = f_self + else + m.__index = f + end + else + if f == "empty" then + setmetatable(t, t_empty) + elseif f == "key" then + setmetatable(t, t_self) + else + setmetatable(t,{ __index = f }) + end + end +end + +function table.setmetatablenewindex(t,f) + local m = getmetatable(t) + if m then + if f == "ignore" then + m.__newindex = f_ignore + else + m.__newindex = f + end + else + if f == "ignore" then + setmetatable(t, t_ignore) + else + setmetatable(t,{ __newindex = f }) + end + end +end + +function table.setmetatablecall(t,f) + local m = getmetatable(t) + if m then + m.__call = f + else + setmetatable(t,{ __call = f }) + end +end + +function table.setmetatablekey(t,key,value) + local m = getmetatable(t) + if not m then + m = { } + setmetatable(t,m) + end + m[key] = value +end + +function table.getmetatablekey(t,key,value) + local m = getmetatable(t) + return m and m[key] +end + end -- of closure @@ -4047,18 +4119,20 @@ if not modules then modules = { } end modules ['util-prs'] = { license = "see context related readme files" } +local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg +local lpegmatch = lpeg.match +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type, next = tostring, type, next + utilities = utilities or {} utilities.parsers = utilities.parsers or { } local parsers = utilities.parsers parsers.patterns = parsers.patterns or { } --- we could use a Cf Cg construct +local setmetatableindex = table.setmetatableindex +local sortedhash = table.sortedhash -local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg -local lpegmatch = lpeg.match -local concat, format, gmatch = table.concat, string.format, string.gmatch -local tostring, type, next, setmetatable = tostring, type, next, setmetatable -local sortedhash = table.sortedhash +-- we could use a Cf Cg construct local escape, left, right = P("\\"), P('{'), P('}') @@ -4257,7 +4331,7 @@ function parsers.getparameters(self,class,parentclass,settings) sp = { } self[parentclass] = sp end - setmetatable(sc, { __index = sp }) + setmetatableindex(sc,sp) end end parsers.settings_to_hash(settings,sc) @@ -4474,7 +4548,7 @@ end local is_node = node and node.is_node -function inspect(i) +function inspect(i) -- global function local ti = type(i) if ti == "table" then table.print(i,"table") @@ -5044,6 +5118,8 @@ local escapedpattern = string.escapedpattern local texcount = tex and tex.count local next, type = next, type +local setmetatableindex = table.setmetatableindex + --[[ldx--

This is a prelude to a more extensive logging module. We no longer provide based logging a sparsing is relatively easy anyway.

@@ -5064,11 +5140,11 @@ wiki : http://contextgarden.net local function ignore() end -setmetatable(logs, { __index = function(t,k) t[k] = ignore ; return ignore end }) +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) -local report, subreport, status, settarget, setformatter +local report, subreport, status, settarget, setformats, settranslations -local direct, subdirect, writer +local direct, subdirect, writer, pushtarget, poptarget if tex and tex.jobname or tex.formatname then @@ -7308,6 +7384,8 @@ local type, next, tonumber, tostring, setmetatable, loadstring = type, next, ton local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local setmetatableindex = table.setmetatableindex + -- beware, this is not xpath ... e.g. position is different (currently) and -- we have reverse-sibling as reversed preceding sibling @@ -7380,8 +7458,8 @@ local function fallback (t, name) return fn end -setmetatable(finalizers.xml, { __index = fallback }) -setmetatable(finalizers.tex, { __index = fallback }) +setmetatableindex(finalizers.xml, fallback) +setmetatableindex(finalizers.tex, fallback) xml.defaultprotocol = "xml" @@ -8078,14 +8156,13 @@ xml.nodesettostring = nodesettostring local lpath -- we have a harmless kind of circular reference +local lshowoptions = { name = false, functions = false } + local function lshow(parsed) if type(parsed) == "string" then parsed = lpath(parsed) end - local s = table.serialize_functions -- ugly - table.serialize_functions = false -- ugly - report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,false)) - table.serialize_functions = s -- ugly + report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,lshowoptions)) end xml.lshow = lshow @@ -8679,8 +8756,8 @@ local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name local xmlinheritedconvert = xml.inheritedconvert local xmlapplylpath = xml.applylpath -local type = type -local insert, remove = table.insert, table.remove +local type, setmetatable, getmetatable = type, setmetatable, getmetatable +local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy local gmatch, gsub = string.gmatch, string.gsub local function report(what,pattern,c,e) @@ -8889,6 +8966,41 @@ function xml.replace(root,pattern,whatever) end end +local function wrap(e,wrapper) + local t = { + rn = e.rn, + tg = e.tg, + ns = e.ns, + at = e.at, + dt = e.dt, + __p__ = e, + } + setmetatable(t,getmetatable(e)) + e.rn = wrapper.rn or e.rn or "" + e.tg = wrapper.tg or e.tg or "" + e.ns = wrapper.ns or e.ns or "" + e.at = fastcopy(wrapper.at) + e.dt = { t } +end + +function xml.wrap(root,pattern,whatever) + if whatever then + local wrapper = xmltoelement(whatever,root) + local collected = xmlapplylpath(root,pattern) + if collected then + for c=1,#collected do + local e = collected[c] + if trace_manipulations then + report('wrapping',pattern,c,e) + end + wrap(e,wrapper) + end + end + else + wrap(root,xmltoelement(pattern)) + end +end + local function inject_element(root,pattern,whatever,prepend) local element = root and xmltoelement(whatever,root) local collected = element and xmlapplylpath(root,pattern) @@ -8959,7 +9071,7 @@ local function include(xmldata,pattern,attribute,recursive,loaddata) local ekat = ek.at local epdt = ek.__p__.dt if not attribute or attribute == "" then - name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- ckeck, probably always tab or str + name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str end if not name then for a in gmatch(attribute or "href","([^|]+)") do @@ -10039,17 +10151,23 @@ if not modules then modules = { } end modules ['data-env'] = { license = "see context related readme files", } -local allocate = utilities.storage.allocate local lower, gsub = string.lower, string.gsub -local fileextname = file.extname - local resolvers = resolvers -local formats = allocate() resolvers.formats = formats -local suffixes = allocate() resolvers.suffixes = suffixes -local dangerous = allocate() resolvers.dangerous = dangerous -local suffixmap = allocate() resolvers.suffixmap = suffixmap +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local fileextname = file.extname + +local formats = allocate() +local suffixes = allocate() +local dangerous = allocate() +local suffixmap = allocate() + +resolvers.formats = formats +resolvers.suffixes = suffixes +resolvers.dangerous = dangerous +resolvers.suffixmap = suffixmap local relations = allocate { -- todo: handlers also here core = { @@ -10261,9 +10379,9 @@ local function simplified(t,k) return rawget(t,lower(gsub(k," ",""))) end -setmetatablekey(formats, "__index", simplified) -setmetatablekey(suffixes, "__index", simplified) -setmetatablekey(suffixmap, "__index", simplified) +setmetatableindex(formats, simplified) +setmetatableindex(suffixes, simplified) +setmetatableindex(suffixmap, simplified) -- A few accessors, mostly for command line tool. @@ -10611,6 +10729,8 @@ function caches.is_writable(filepath,filename) return file.is_writable(tmaname) end +local saveoptions = { name = "return", reduce = true } + function caches.savedata(filepath,filename,data,raw) local tmaname, tmcname = caches.setluanames(filepath,filename) local reduce, simplify = true, true @@ -10619,9 +10739,9 @@ function caches.savedata(filepath,filename,data,raw) end data.cache_uuid = os.uuid() if caches.direct then - file.savedata(tmaname, table.serialize(data,'return',false,true,false)) -- no hex + file.savedata(tmaname,table.serialize(data,saveoptions)) else - table.tofile(tmaname, data,'return',false,true,false) -- maybe not the last true + table.tofile(tmaname,data,saveoptions) end utilities.lua.compile(tmaname,tmcname) end @@ -10865,15 +10985,20 @@ if not modules then modules = { } end modules ['data-res'] = { local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys -local next, type, rawget, setmetatable, getmetatable = next, type, rawget, setmetatable, getmetatable +local next, type, rawget = next, type, rawget local os = os local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join -local collapsepath, joinpath = file.collapsepath, file.joinpath -local allocate = utilities.storage.allocate +local filedirname = file.dirname +local filebasename = file.basename +local fileextname = file.extname +local filejoin = file.join +local collapsepath = file.collapsepath +local joinpath = file.joinpath +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end) @@ -11010,7 +11135,8 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp force_suffixes = true, } - setmetatable(variables, { __index = function(t,k) + setmetatableindex(variables,function(t,k) + local v for i=1,#order do v = order[i][k] if v ~= nil then @@ -11023,10 +11149,10 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) - setmetatable(environment, { __index = function(t,k) - v = osgetenv(k) + setmetatableindex(environment, function(t,k) + local v = osgetenv(k) if v == nil then v = variables[k] end @@ -11036,9 +11162,9 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp v = resolvers.repath(v) -- for taco who has a : separated osfontdir t[k] = v return v - end } ) + end) - setmetatable(expansions, { __index = function(t,k) + setmetatableindex(expansions, function(t,k) local v = environment[k] if type(v) == "string" then v = lpegmatch(variableresolver,v) @@ -11046,7 +11172,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) return newinstance @@ -11552,7 +11678,7 @@ function resolvers.registerfilehash(name,content,someerror) end end -function isreadable(name) +local function isreadable(name) local readable = lfs.isfile(name) -- not file.is_readable(name) asit can be a dir if trace_detail then if readable then diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 6a3df03d0..e0fc8d823 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -971,10 +971,6 @@ function table.fromhash(t) return hsh end -table.serialize_functions = true -table.serialize_compact = true -table.serialize_inline = true - local noquotes, hexify, handle, reduce, compact, inline, functions local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key @@ -1257,15 +1253,36 @@ end -- replacing handle by a direct t[#t+1] = ... (plus test) is not much -- faster (0.03 on 1.00 for zapfino.tma) -local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) - noquotes = _noquotes - hexify = _hexify - handle = _handle or print - reduce = _reduce or false - compact = table.serialize_compact - inline = compact and table.serialize_inline - functions = table.serialize_functions +local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) -- I might drop the _'s some day. local tname = type(name) + if tname == "table" then + noquotes = name.noquotes + hexify = name.hexify + handle = name.handle or print + reduce = name.reduce or false + functions = name.functions + compact = name.compact + inline = name.inline and compact + name = name.name + tname = type(name) + if functions == nil then + functions = true + end + if compact == nil then + compact = true + end + if inline == nil then + inline = compact + end + else + noquotes = _noquotes + hexify = _hexify + handle = _handle or print + reduce = _reduce or false + compact = true + inline = true + functions = true + end if tname == "string" then if name == "return" then handle("return {") @@ -1324,12 +1341,11 @@ end -- -- so this is on the todo list -table.tofile_maxtab = 2*1024 +local maxtab = 2*1024 function table.tofile(filename,root,name,reduce,noquotes,hexify) local f = io.open(filename,'w') if f then - local maxtab = table.tofile_maxtab if maxtab > 1 then local t, n = { }, 0 local function flush(s) @@ -1532,8 +1548,12 @@ function table.sequenced(t,sep,simple) -- hash only return concat(s, sep or " | ") end -function table.print(...) - table.tohandle(print,...) +function table.print(t,...) + if type(t) ~= "table" then + print(tostring(t)) + else + table.tohandle(print,t,...) + end end -- -- -- obsolete but we keep them for a while and might comment them later -- -- -- @@ -2535,8 +2555,6 @@ function file.collapsepath(str,anchor) end end -file.collapse_path = file.collapsepath - function file.robustname(str,strict) str = gsub(str,"[^%a%d%/%-%.\\]+","-") @@ -2651,14 +2669,12 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end -file.needs_updating_threshold = 1 - -function file.needs_updating(oldname,newname) -- size modification access change +function file.needs_updating(oldname,newname,threshold) -- size modification access change local oldtime = lfs.attributes(oldname, modification) local newtime = lfs.attributes(newname, modification) if newtime >= oldtime then return false - elseif oldtime - newtime < file.needs_updating_threshold then + elseif oldtime - newtime < (threshold or 1) then return false else return true @@ -3666,7 +3682,7 @@ local tables = utilities.tables local format, gmatch = string.format, string.gmatch local concat, insert, remove = table.concat, table.insert, table.remove -local setmetatable, tonumber, tostring = setmetatable, tonumber, tostring +local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring function tables.definetable(target) -- defines undefined tables local composed, t, n = nil, { }, 0 @@ -3731,12 +3747,6 @@ function tables.insertaftervalue(t,value,extra) insert(t,#t+1,extra) end -local _empty_table_ = { __index = function(t,k) return "" end } - -function table.setemptymetatable(t) - setmetatable(t,_empty_table_) -end - -- experimental local function toxml(t,d,result) @@ -3753,9 +3763,14 @@ local function toxml(t,d,result) end end -function table.toxml(t,name) - local result = { "" } - toxml( { [name or "root"] = t }, "", result) +function table.toxml(t,name,nobanner) + local noroot = name == false + local result = (nobanner or noroot) and { } or { "" } + if noroot then + toxml( t, "", result) + else + toxml( { [name or "root"] = t }, "", result) + end return concat(result,"\n") end @@ -3816,20 +3831,6 @@ function storage.checked(t) return t end -function setmetatablekey(t,key,value) - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m[key] = value -end - -function getmetatablekey(t,key,value) - local m = getmetatable(t) - return m and m[key] -end - function storage.setinitializer(data,initialize) local m = getmetatable(data) or { } @@ -3852,6 +3853,77 @@ function storage.sparse(t) return t end +-- table namespace ? + +local function f_empty () return "" end -- t,k +local function f_self (t,k) t[k] = k return k end +local function f_ignore() end -- t,k,v + +local t_empty = { __index = empty } +local t_self = { __index = self } +local t_ignore = { __newindex = ignore } + +function table.setmetatableindex(t,f) + local m = getmetatable(t) + if m then + if f == "empty" then + m.__index = f_empty + elseif f == "key" then + m.__index = f_self + else + m.__index = f + end + else + if f == "empty" then + setmetatable(t, t_empty) + elseif f == "key" then + setmetatable(t, t_self) + else + setmetatable(t,{ __index = f }) + end + end +end + +function table.setmetatablenewindex(t,f) + local m = getmetatable(t) + if m then + if f == "ignore" then + m.__newindex = f_ignore + else + m.__newindex = f + end + else + if f == "ignore" then + setmetatable(t, t_ignore) + else + setmetatable(t,{ __newindex = f }) + end + end +end + +function table.setmetatablecall(t,f) + local m = getmetatable(t) + if m then + m.__call = f + else + setmetatable(t,{ __call = f }) + end +end + +function table.setmetatablekey(t,key,value) + local m = getmetatable(t) + if not m then + m = { } + setmetatable(t,m) + end + m[key] = value +end + +function table.getmetatablekey(t,key,value) + local m = getmetatable(t) + return m and m[key] +end + end -- of closure @@ -4047,18 +4119,20 @@ if not modules then modules = { } end modules ['util-prs'] = { license = "see context related readme files" } +local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg +local lpegmatch = lpeg.match +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type, next = tostring, type, next + utilities = utilities or {} utilities.parsers = utilities.parsers or { } local parsers = utilities.parsers parsers.patterns = parsers.patterns or { } --- we could use a Cf Cg construct +local setmetatableindex = table.setmetatableindex +local sortedhash = table.sortedhash -local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg -local lpegmatch = lpeg.match -local concat, format, gmatch = table.concat, string.format, string.gmatch -local tostring, type, next, setmetatable = tostring, type, next, setmetatable -local sortedhash = table.sortedhash +-- we could use a Cf Cg construct local escape, left, right = P("\\"), P('{'), P('}') @@ -4257,7 +4331,7 @@ function parsers.getparameters(self,class,parentclass,settings) sp = { } self[parentclass] = sp end - setmetatable(sc, { __index = sp }) + setmetatableindex(sc,sp) end end parsers.settings_to_hash(settings,sc) @@ -4474,7 +4548,7 @@ end local is_node = node and node.is_node -function inspect(i) +function inspect(i) -- global function local ti = type(i) if ti == "table" then table.print(i,"table") @@ -5044,6 +5118,8 @@ local escapedpattern = string.escapedpattern local texcount = tex and tex.count local next, type = next, type +local setmetatableindex = table.setmetatableindex + --[[ldx--

This is a prelude to a more extensive logging module. We no longer provide based logging a sparsing is relatively easy anyway.

@@ -5064,11 +5140,11 @@ wiki : http://contextgarden.net local function ignore() end -setmetatable(logs, { __index = function(t,k) t[k] = ignore ; return ignore end }) +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) -local report, subreport, status, settarget, setformatter +local report, subreport, status, settarget, setformats, settranslations -local direct, subdirect, writer +local direct, subdirect, writer, pushtarget, poptarget if tex and tex.jobname or tex.formatname then @@ -7308,6 +7384,8 @@ local type, next, tonumber, tostring, setmetatable, loadstring = type, next, ton local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local setmetatableindex = table.setmetatableindex + -- beware, this is not xpath ... e.g. position is different (currently) and -- we have reverse-sibling as reversed preceding sibling @@ -7380,8 +7458,8 @@ local function fallback (t, name) return fn end -setmetatable(finalizers.xml, { __index = fallback }) -setmetatable(finalizers.tex, { __index = fallback }) +setmetatableindex(finalizers.xml, fallback) +setmetatableindex(finalizers.tex, fallback) xml.defaultprotocol = "xml" @@ -8078,14 +8156,13 @@ xml.nodesettostring = nodesettostring local lpath -- we have a harmless kind of circular reference +local lshowoptions = { name = false, functions = false } + local function lshow(parsed) if type(parsed) == "string" then parsed = lpath(parsed) end - local s = table.serialize_functions -- ugly - table.serialize_functions = false -- ugly - report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,false)) - table.serialize_functions = s -- ugly + report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,lshowoptions)) end xml.lshow = lshow @@ -8679,8 +8756,8 @@ local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name local xmlinheritedconvert = xml.inheritedconvert local xmlapplylpath = xml.applylpath -local type = type -local insert, remove = table.insert, table.remove +local type, setmetatable, getmetatable = type, setmetatable, getmetatable +local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy local gmatch, gsub = string.gmatch, string.gsub local function report(what,pattern,c,e) @@ -8889,6 +8966,41 @@ function xml.replace(root,pattern,whatever) end end +local function wrap(e,wrapper) + local t = { + rn = e.rn, + tg = e.tg, + ns = e.ns, + at = e.at, + dt = e.dt, + __p__ = e, + } + setmetatable(t,getmetatable(e)) + e.rn = wrapper.rn or e.rn or "" + e.tg = wrapper.tg or e.tg or "" + e.ns = wrapper.ns or e.ns or "" + e.at = fastcopy(wrapper.at) + e.dt = { t } +end + +function xml.wrap(root,pattern,whatever) + if whatever then + local wrapper = xmltoelement(whatever,root) + local collected = xmlapplylpath(root,pattern) + if collected then + for c=1,#collected do + local e = collected[c] + if trace_manipulations then + report('wrapping',pattern,c,e) + end + wrap(e,wrapper) + end + end + else + wrap(root,xmltoelement(pattern)) + end +end + local function inject_element(root,pattern,whatever,prepend) local element = root and xmltoelement(whatever,root) local collected = element and xmlapplylpath(root,pattern) @@ -8959,7 +9071,7 @@ local function include(xmldata,pattern,attribute,recursive,loaddata) local ekat = ek.at local epdt = ek.__p__.dt if not attribute or attribute == "" then - name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- ckeck, probably always tab or str + name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str end if not name then for a in gmatch(attribute or "href","([^|]+)") do @@ -10039,17 +10151,23 @@ if not modules then modules = { } end modules ['data-env'] = { license = "see context related readme files", } -local allocate = utilities.storage.allocate local lower, gsub = string.lower, string.gsub -local fileextname = file.extname - local resolvers = resolvers -local formats = allocate() resolvers.formats = formats -local suffixes = allocate() resolvers.suffixes = suffixes -local dangerous = allocate() resolvers.dangerous = dangerous -local suffixmap = allocate() resolvers.suffixmap = suffixmap +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local fileextname = file.extname + +local formats = allocate() +local suffixes = allocate() +local dangerous = allocate() +local suffixmap = allocate() + +resolvers.formats = formats +resolvers.suffixes = suffixes +resolvers.dangerous = dangerous +resolvers.suffixmap = suffixmap local relations = allocate { -- todo: handlers also here core = { @@ -10261,9 +10379,9 @@ local function simplified(t,k) return rawget(t,lower(gsub(k," ",""))) end -setmetatablekey(formats, "__index", simplified) -setmetatablekey(suffixes, "__index", simplified) -setmetatablekey(suffixmap, "__index", simplified) +setmetatableindex(formats, simplified) +setmetatableindex(suffixes, simplified) +setmetatableindex(suffixmap, simplified) -- A few accessors, mostly for command line tool. @@ -10611,6 +10729,8 @@ function caches.is_writable(filepath,filename) return file.is_writable(tmaname) end +local saveoptions = { name = "return", reduce = true } + function caches.savedata(filepath,filename,data,raw) local tmaname, tmcname = caches.setluanames(filepath,filename) local reduce, simplify = true, true @@ -10619,9 +10739,9 @@ function caches.savedata(filepath,filename,data,raw) end data.cache_uuid = os.uuid() if caches.direct then - file.savedata(tmaname, table.serialize(data,'return',false,true,false)) -- no hex + file.savedata(tmaname,table.serialize(data,saveoptions)) else - table.tofile(tmaname, data,'return',false,true,false) -- maybe not the last true + table.tofile(tmaname,data,saveoptions) end utilities.lua.compile(tmaname,tmcname) end @@ -10865,15 +10985,20 @@ if not modules then modules = { } end modules ['data-res'] = { local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys -local next, type, rawget, setmetatable, getmetatable = next, type, rawget, setmetatable, getmetatable +local next, type, rawget = next, type, rawget local os = os local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join -local collapsepath, joinpath = file.collapsepath, file.joinpath -local allocate = utilities.storage.allocate +local filedirname = file.dirname +local filebasename = file.basename +local fileextname = file.extname +local filejoin = file.join +local collapsepath = file.collapsepath +local joinpath = file.joinpath +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end) @@ -11010,7 +11135,8 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp force_suffixes = true, } - setmetatable(variables, { __index = function(t,k) + setmetatableindex(variables,function(t,k) + local v for i=1,#order do v = order[i][k] if v ~= nil then @@ -11023,10 +11149,10 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) - setmetatable(environment, { __index = function(t,k) - v = osgetenv(k) + setmetatableindex(environment, function(t,k) + local v = osgetenv(k) if v == nil then v = variables[k] end @@ -11036,9 +11162,9 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp v = resolvers.repath(v) -- for taco who has a : separated osfontdir t[k] = v return v - end } ) + end) - setmetatable(expansions, { __index = function(t,k) + setmetatableindex(expansions, function(t,k) local v = environment[k] if type(v) == "string" then v = lpegmatch(variableresolver,v) @@ -11046,7 +11172,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) return newinstance @@ -11552,7 +11678,7 @@ function resolvers.registerfilehash(name,content,someerror) end end -function isreadable(name) +local function isreadable(name) local readable = lfs.isfile(name) -- not file.is_readable(name) asit can be a dir if trace_detail then if readable then diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua index 132ad32c7..789e1aefe 100644 --- a/tex/context/base/anch-pos.lua +++ b/tex/context/base/anch-pos.lua @@ -22,7 +22,8 @@ local allocate, mark = utilities.storage.allocate, utilities.storage.mark local texsp = tex.sp ----- texsp = string.todimen -- because we cache this is much faster but no rounding -local collected, tobesaved = allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() local jobpositions = { collected = collected, @@ -36,14 +37,15 @@ _ptbs_, _pcol_ = tobesaved, collected -- global local dx, dy, nx, ny = "0pt", "0pt", 0, 0 local function initializer() - tobesaved = mark(jobpositions.tobesaved) - collected = mark(jobpositions.collected) - _ptbs_, _pcol_ = tobesaved, collected -- global - local p = collected["page:0"] -- page:1 - if p then - -- dx, nx = p[2] or "0pt", 0 - -- dy, ny = p[3] or "0pt", 0 - end + tobesaved = jobpositions.tobesaved + collected = jobpositions.collected + _ptbs_ = tobesaved -- global + _pcol_ = collected -- global + -- local p = collected["page:0"] -- page:1 + -- if p then + -- dx, nx = p[2] or "0pt", 0 + -- dy, ny = p[3] or "0pt", 0 + -- end end job.register('job.positions.collected', tobesaved, initializer) diff --git a/tex/context/base/attr-col.lua b/tex/context/base/attr-col.lua index acabe62ac..871ac3e03 100644 --- a/tex/context/base/attr-col.lua +++ b/tex/context/base/attr-col.lua @@ -13,14 +13,15 @@ local type = type local format = string.format local concat = table.concat -local allocate = utilities.storage.allocate +local attributes, nodes = attributes, nodes + +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex local report_attributes = logs.reporter("attributes","colors") local report_colors = logs.reporter("colors","support") local report_transparencies = logs.reporter("transparencies","support") -local attributes, nodes = attributes, nodes - -- todo: document this but first reimplement this as it reflects the early -- days of luatex / mkiv and we have better ways now @@ -290,8 +291,8 @@ local function reviver(data,n) end end -setmetatable(colors, { __index = extender }) -setmetatable(colors.data, { __index = reviver }) +setmetatableindex(colors, extender) +setmetatableindex(colors.data, reviver) function colors.filter(n) return concat(data[n],":",5) @@ -420,8 +421,8 @@ local function reviver(data,n) end end -setmetatable(transparencies, { __index = extender }) -setmetatable(transparencies.data, { __index = reviver }) -- register if used +setmetatableindex(transparencies, extender) +setmetatableindex(transparencies.data, reviver) -- register if used -- check if there is an identity @@ -485,8 +486,8 @@ local function reviver(data,n) end end -setmetatable(colorintents, { __index = extender }) -setmetatable(colorintents.data, { __index = reviver }) +setmetatableindex(colorintents, extender) +setmetatableindex(colorintents.data, reviver) function colorintents.register(stamp) return registered[stamp] or registered.overprint diff --git a/tex/context/base/attr-eff.lua b/tex/context/base/attr-eff.lua index 6ed64f201..023d1c51b 100644 --- a/tex/context/base/attr-eff.lua +++ b/tex/context/base/attr-eff.lua @@ -8,31 +8,33 @@ if not modules then modules = { } end modules ['attr-eff'] = { local format = string.format -local allocate = utilities.storage.allocate - local attributes, nodes = attributes, nodes -local states = attributes.states -local tasks = nodes.tasks -local nodeinjections = backends.nodeinjections -local settexattribute = tex.setattribute +local states = attributes.states +local tasks = nodes.tasks +local nodeinjections = backends.nodeinjections +local settexattribute = tex.setattribute +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -attributes.effects = attributes.effects or { } -local effects = attributes.effects +attributes.effects = attributes.effects or { } +local effects = attributes.effects -local a_effect = attributes.private('effect') +local a_effect = attributes.private('effect') -effects.data = allocate() -effects.values = effects.values or { } -effects.registered = effects.registered or { } -effects.attribute = a_effect +effects.data = allocate() +effects.values = effects.values or { } +effects.registered = effects.registered or { } +effects.attribute = a_effect storage.register("attributes/effects/registered", effects.registered, "attributes.effects.registered") storage.register("attributes/effects/values", effects.values, "attributes.effects.values") -local template = "%s:%s:%s" +local template = "%s:%s:%s" -local data, registered, values = effects.data, effects.registered, effects.values +local data = effects.data +local registered = effects.registered +local values = effects.values -- valid effects: normal inner outer both hidden (stretch,rulethickness,effect) @@ -53,8 +55,8 @@ local function reviver(data,n) return d end -setmetatable(effects, { __index = extender }) -setmetatable(effects.data, { __index = reviver }) +setmetatableindex(effects, extender) +setmetatableindex(effects.data, reviver) effects.handler = nodes.installattributehandler { name = "effect", diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv index 0d7328a12..ba6ca369f 100644 --- a/tex/context/base/attr-ini.mkiv +++ b/tex/context/base/attr-ini.mkiv @@ -88,6 +88,7 @@ \definesystemattribute [layoutcomponent] [public] \definesystemattribute [reference] [public] \definesystemattribute [destination] [public] +\definesystemattribute [internal] [public] \definesystemattribute [ruled] [public] \definesystemattribute [shifted] [public] diff --git a/tex/context/base/attr-lay.lua b/tex/context/base/attr-lay.lua index 1b652e469..ce76bb899 100644 --- a/tex/context/base/attr-lay.lua +++ b/tex/context/base/attr-lay.lua @@ -14,7 +14,8 @@ local type = type local format = string.format local insert, remove = table.insert, table.remove -local allocate = utilities.storage.allocate +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex local report_viewerlayers = logs.reporter("viewerlayers") @@ -90,8 +91,8 @@ local function reviver(data,n) end end -setmetatable(viewerlayers, { __index = extender }) -setmetatable(viewerlayers.data, { __index = reviver }) +setmetatableindex(viewerlayers, extender) +setmetatableindex(viewerlayers.data, reviver) local function initializer(...) return states.initialize(...) diff --git a/tex/context/base/attr-neg.lua b/tex/context/base/attr-neg.lua index c8f294c71..766295a16 100644 --- a/tex/context/base/attr-neg.lua +++ b/tex/context/base/attr-neg.lua @@ -11,30 +11,34 @@ if not modules then modules = { } end modules ['attr-neg'] = { local format = string.format + local attributes, nodes = attributes, nodes -local states = attributes.states -local tasks = nodes.tasks -local nodeinjections = backends.nodeinjections -local settexattribute = tex.setattribute -local variables = interfaces.variables +local states = attributes.states +local tasks = nodes.tasks +local nodeinjections = backends.nodeinjections +local settexattribute = tex.setattribute +local variables = interfaces.variables +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex --- negative / positive -attributes.negatives = attributes.negatives or { } -local negatives = attributes.negatives +attributes.negatives = attributes.negatives or { } +local negatives = attributes.negatives -local a_negative = attributes.private("negative") +local a_negative = attributes.private("negative") -negatives.data = negatives.data or { } -negatives.attribute = a_negative +negatives.data = allocate() +negatives.attribute = a_negative -negatives.registered = { +negatives.registered = allocate { [variables.positive] = 1, [variables.negative] = 2, } -local data, registered = negatives.data, negatives.registered +local data = negatives.data +local registered = negatives.registered local function extender(negatives,key) if key == "none" then @@ -56,8 +60,8 @@ local function reviver(data,n) end end -setmetatable(negatives, { __index = extender }) -setmetatable(negatives.data, { __index = reviver }) +setmetatableindex(negatives, extender) +setmetatableindex(negatives.data, reviver) negatives.handler = nodes.installattributehandler { name = "negative", diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua index b9cfcefd4..8450b36f1 100644 --- a/tex/context/base/back-exp.lua +++ b/tex/context/base/back-exp.lua @@ -15,6 +15,9 @@ if not modules then modules = { } end modules ['back-exp'] = { -- We can consider replacing attributes by the hash entry ... slower in resolving but it's still -- quite okay. +-- todo: less attributes e.g. internal only first node +-- todo: build xml tree in mem (handy for cleaning) + local nodecodes = nodes.nodecodes local traverse_nodes = node.traverse local hlist_code = nodecodes.hlist @@ -39,9 +42,9 @@ end nodes.locate = locate local next, type = next, type -local format, match, concat, rep = string.format, string.match, table.concat, string.rep +local format, match, concat, rep, sub, gsub = string.format, string.match, table.concat, string.rep, string.sub, string.gsub local lpegmatch = lpeg.match -local utfchar = utf.char +local utfchar, utfsub = utf.char, utf.sub local insert, remove = table.insert, table.remove local trace_export = false trackers.register ("structures.export", function(v) trace_export = v end) @@ -50,82 +53,91 @@ local trace_tree = false trackers.register ("structures.export.showtree", local less_state = false directives.register("structures.export.lessstate", function(v) less_state = v end) local page_breaks = false directives.register("structures.export.pagebreaks", function(v) page_breaks = v end) -local report_export = logs.reporter("backend","export") - -local nodes = nodes -local attributes = attributes -local variables = interfaces.variables - -local tasks = nodes.tasks -local fontchar = fonts.hashes.characters -local languagenames = languages.numbers - -local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes -local whatsitcodes = nodes.whatsitcodes -local listcodes = nodes.listcodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local disc_code = nodecodes.disc -local insert_code = nodecodes.insert -local whatsit_code = nodecodes.whatsit -local refximage_code = whatsitcodes.pdfrefximage - -local userskip_code = skipcodes.userskip -local rightskip_code = skipcodes.rightskip -local parfillskip_code= skipcodes.parfillskip - -local line_code = listcodes.line - -local a_tagged = attributes.private('tagged') -local a_image = attributes.private('image') - -local a_taggedalign = attributes.private("taggedalign") -local a_taggedcolumns = attributes.private("taggedcolumns") -local a_taggedrows = attributes.private("taggedrows") -local a_taggedpar = attributes.private("taggedpar") -local a_taggedpacked = attributes.private("taggedpacked") -local a_taggedsymbol = attributes.private("taggedsymbol") -local a_taggedinsert = attributes.private("taggedinsert") - -local a_reference = attributes.private('reference') - -local has_attribute = node.has_attribute -local traverse_nodes = node.traverse -local slide_nodelist = node.slide -local texattribute = tex.attribute -local unsetvalue = attributes.unsetvalue -local locate_node = nodes.locate - -local references = structures.references -local structurestags = structures.tags -local taglist = structurestags.taglist -local properties = structurestags.properties -local userdata = structurestags.userdata -- might be combines with taglist - -local version = "0.10" -local result = nil +local report_export = logs.reporter("backend","export") + +local nodes = nodes +local attributes = attributes +local variables = interfaces.variables + +local setmetatableindex = table.setmetatableindex +local tasks = nodes.tasks +local fontchar = fonts.hashes.characters +local languagenames = languages.numbers + +local nodecodes = nodes.nodecodes +local skipcodes = nodes.skipcodes +local whatsitcodes = nodes.whatsitcodes +local listcodes = nodes.listcodes + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local disc_code = nodecodes.disc +local insert_code = nodecodes.insert +local whatsit_code = nodecodes.whatsit +local refximage_code = whatsitcodes.pdfrefximage + +local userskip_code = skipcodes.userskip +local rightskip_code = skipcodes.rightskip +local parfillskip_code = skipcodes.parfillskip + +local line_code = listcodes.line + +local a_tagged = attributes.private('tagged') +local a_image = attributes.private('image') + +local a_taggedalign = attributes.private("taggedalign") +local a_taggedcolumns = attributes.private("taggedcolumns") +local a_taggedrows = attributes.private("taggedrows") +local a_taggedpar = attributes.private("taggedpar") +local a_taggedpacked = attributes.private("taggedpacked") +local a_taggedsymbol = attributes.private("taggedsymbol") +local a_taggedinsert = attributes.private("taggedinsert") +local a_taggedtag = attributes.private("taggedtag") + +local a_reference = attributes.private('reference') + +local has_attribute = node.has_attribute +local traverse_nodes = node.traverse +local slide_nodelist = node.slide +local texattribute = tex.attribute +local unsetvalue = attributes.unsetvalue +local locate_node = nodes.locate + +local references = structures.references +local structurestags = structures.tags +local taglist = structurestags.taglist +local properties = structurestags.properties +local userdata = structurestags.userdata -- might be combines with taglist +local tagdata = structurestags.data + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +-- todo: more locals (and optimize) + +local version = "0.20" +local result = nil -- todo: nofresult local entry = nil local attributehash = { } -local handle = nil -local hyphen = utfchar(0xAD) +local hyphen = utfchar(0xAD) -- todo: also emdash etc local colonsplitter = lpeg.splitat(":") local dashsplitter = lpeg.splitat("-") local threshold = 65536 local indexing = false local linedone = false local inlinedepth = 0 -local collapse = true local tree = { data = { }, depth = 0 } -- root local treestack = { } local treehash = { } local extras = { } local nofbreaks = 0 -local listhash = { } +local used = { } +local exporting = false + +setmetatableindex(used, function(t,k) if k then local v = { } t[k] = v return v end end) local last = nil local lastpar = nil @@ -136,7 +148,7 @@ local joiner_3 = " " local joiner_4 = " " local joiner_5 = " " local joiner_6 = " " -local joiner_7 = " " +local joiner_7 = "\n" local joiner_8 = " " local joiner_9 = " " local joiner_0 = " " @@ -150,9 +162,22 @@ local joiner_0 = " " -- local tagsplitter = C(precolon) * colon * C(predash) * dash * C(rest) + -- C(predash) * dash * Cc(nil) * C(rest) +local listdata = { } + +local function hashlistdata() + local c = structures.lists.collected + for i=1,#c do + local ci = c[i] + local tag = ci.references.tag + if tag then + listdata[ci.metadata.kind .. ":" .. ci.metadata.name .. "-" .. tag] = ci + end + end +end + local spaces = { } -- watch how we also moved the -1 in depth-1 to the creator -setmetatable(spaces, { __index = function(t,k) t[k] = rep(" ",k-1) return t[k] end } ) +setmetatableindex(spaces, function(t,k) t[k] = rep(" ",k-1) return t[k] end) properties.vspace = { export = "break", nature = "display" } properties.pbreak = { export = "pagebreak", nature = "display" } @@ -184,13 +209,23 @@ local function makebreaknode(node) } end -function extras.document(element,detail,n,fulltag,hash) - handle:write(" language='",languagenames[tex.count.mainlanguagenumber],"'") +local fields = { "title", "subtitle", "author", "keywords" } + +function extras.document(handle,element,detail,n,fulltag,hash) + handle:write(format(" language=%q",languagenames[tex.count.mainlanguagenumber])) if not less_state then - handle:write(" file='",tex.jobname,"'") - handle:write(" date='",os.date(),"'") - handle:write(" context='",environment.version,"'") - handle:write(" version='",version,"'") + handle:write(format(" file=%q",tex.jobname)) + handle:write(format(" date=%q",os.date())) + handle:write(format(" context=%q",environment.version)) + handle:write(format(" version=%q",version)) + local identity = interactions.general.getidentity() + for i=1,#fields do + local key = fields[i] + local value = identity[key] + if value and value ~= "" then + handle:write(format(" %s=%q",key,value)) + end + end end end @@ -206,10 +241,34 @@ function structurestags.setitemgroup(packed,symbol,di) texattribute[a_taggedsymbol] = s end +-- todo: per class + +local synonymnames, synonymnumbers = { }, { } -- can be one hash + +function structurestags.setsynonym(class,tag) + local s = synonymnumbers[tag] + if not s then + s = #synonymnames + 1 + synonymnames[s], synonymnumbers[tag] = tag, s + end + texattribute[a_taggedtag] = s +end + +local sortingnames, sortingnumbers = { }, { } -- can be one hash + +function structurestags.setsorting(class,tag) + local s = sortingnumbers[tag] + if not s then + s = #sortingnames + 1 + sortingnames[s], sortingnumbers[tag] = tag, s + end + texattribute[a_taggedtag] = s +end + local insertids = { } function structurestags.setdescriptionid(tag,n) - local nd = structures.notes.get(tag,n) + local nd = structures.notes.get(tag,n) -- todo: use listdata instead if nd then local r = nd.references texattribute[a_taggedinsert] = r.internal or unsetvalue @@ -218,7 +277,7 @@ function structurestags.setdescriptionid(tag,n) end end -function extras.descriptiontag(element,detail,n,fulltag,di) +function extras.descriptiontag(handle,element,detail,n,fulltag,di) local hash = attributehash[fulltag] if hash then local v = hash.insert @@ -229,7 +288,7 @@ function extras.descriptiontag(element,detail,n,fulltag,di) end end -function extras.descriptionsymbol(element,detail,n,fulltag,di) +function extras.descriptionsymbol(handle,element,detail,n,fulltag,di) local hash = attributehash[fulltag] if hash then local v = hash.insert @@ -240,7 +299,29 @@ function extras.descriptionsymbol(element,detail,n,fulltag,di) end end -function extras.image(element,detail,n,fulltag,di) +function extras.synonym(handle,element,detail,n,fulltag,di) + local hash = attributehash[fulltag] + if hash then + local v = hash.tag + v = v and synonymnames[v] + if v then + handle:write(" tag='",v,"'") + end + end +end + +function extras.sorting(handle,element,detail,n,fulltag,di) + local hash = attributehash[fulltag] + if hash then + local v = hash.tag + v = v and sortingnames[v] + if v then + handle:write(" tag='",v,"'") + end + end +end + +function extras.image(handle,element,detail,n,fulltag,di) local hash = attributehash[fulltag] if hash then local v = hash.imageindex @@ -270,14 +351,14 @@ end local evaluators = { } local specials = { } -evaluators.inner = function(var) +evaluators.inner = function(handle,var) local inner = var.inner if var.inner then handle:write(" location='",inner,"'") end end -evaluators.outer = function(var) +evaluators.outer = function(handle,var) local file, url = references.checkedfileorurl(var.outer,var.outer) if url then handle:write(" url='",file,"'") @@ -286,7 +367,7 @@ evaluators.outer = function(var) end end -evaluators["outer with inner"] = function(var) +evaluators["outer with inner"] = function(handle,var) local file = references.checkedfile(var.f) if file then handle:write(" file='",file,"'") @@ -297,10 +378,10 @@ evaluators["outer with inner"] = function(var) end end -evaluators.special = function(var) +evaluators.special = function(handle,var) local handler = specials[var.special] if handler then - handler(var) + handler(handle,var) end end @@ -308,21 +389,21 @@ evaluators["special outer with operation"] = evaluators.special evaluators["special operation"] = evaluators.special evaluators["special operation with arguments"] = evaluators.special -function specials.url(var) +function specials.url(handle,var) local url = references.checkedurl(var.operation) if url then handle:write(" url='",url,"'") end end -function specials.file(var) +function specials.file(handle,var) local file = references.checkedfile(var.operation) if file then handle:write(" file='",file,"'") end end -function specials.fileorurl(var) +function specials.fileorurl(handle,var) local file, url = references.checkedfileorurl(var.operation,var.operation) if url then handle:write(" url='",file,"'") @@ -331,7 +412,14 @@ function specials.fileorurl(var) end end -local function addreference(references) -- todo: specials -> exporters and then concat +function specials.internal(handle,var) + local internal = references.checkedurl(var.operation) + if internal then + handle:write(" location='aut:",internal,"'") + end +end + +local function adddestination(handle,references) -- todo: specials -> exporters and then concat if references then local reference = references.reference if reference and reference ~= "" then @@ -339,44 +427,97 @@ local function addreference(references) -- todo: specials -> exporters and then if prefix and prefix ~= "" then handle:write(" prefix='",prefix,"'") end - handle:write(" reference='",reference,"'") + handle:write(" destination='",reference,"'") for i=1,#references do local r = references[i] local e = evaluators[r.kind] if e then - e(r) + e(handle,r) end end end end end --- end of references related code -- +local function addreference(handle,references) + if references then + local reference = references.reference + if reference and reference ~= "" then + local prefix = references.prefix + if prefix and prefix ~= "" then + handle:write(" prefix='",prefix,"'") + end + handle:write(" reference='",reference,"'") + end + local internal = references.internal + if internal and internal ~= "" then + handle:write(" location='aut:",internal,"'") + end + end +end -function extras.link(element,detail,n,fulltag,di) - -- why so often +function extras.link(handle,element,detail,n,fulltag,di) + -- for instance in lists a link has nested elements and no own text local hash = attributehash[fulltag] if hash then local references = hash.reference if references then - addreference(structures.references.get(references)) + adddestination(handle,structures.references.get(references)) + end + return true + else + local data = di.data + if data then + for i=1,#data do + local di = data[i] + if di and extras.link(handle,element,detail,n,di.fulltag,di) then + return true + end + end end end end -function extras.section(element,detail,n,fulltag,di) - local hash = listhash[element] - hash = hash and hash[n] - addreference(hash and hash.references) +function extras.section(handle,element,detail,n,fulltag,di) + local data = listdata[fulltag] + if data then + addreference(handle,data.references) + return true + else + local data = di.data + if data then + for i=1,#data do + local di = data[i] + if di then + local ft = di.fulltag + if ft and extras.section(handle,element,detail,n,ft,di) then + return true + end + end + end + end + end end -function extras.float(element,detail,n,fulltag,di) - local hash = listhash[element] - hash = hash and hash[n] - addreference(hash and hash.references) +function extras.float(handle,element,detail,n,fulltag,di) + local data = listdata[fulltag] + if data then + addreference(handle,data.references) + return true + else + local data = di.data + if data then + for i=1,#data do + local di = data[i] + if di and extras.section(handle,element,detail,n,di.fulltag,di) then + return true + end + end + end + end end -function extras.itemgroup(element,detail,n,fulltag,di) +function extras.itemgroup(handle,element,detail,n,fulltag,di) local data = di.data for i=1,#data do local di = data[i] @@ -388,8 +529,6 @@ function extras.itemgroup(element,detail,n,fulltag,di) local tg = ddi.tg if tg == "itemtag" or tg == "itemcontent" then local hash = attributehash[ddi.fulltag] ---~ table.print(attributehash) ---~ print(ddi.fulltag,hash) if hash then local v = hash.packed if v and v == 1 then @@ -408,47 +547,51 @@ function extras.itemgroup(element,detail,n,fulltag,di) end end -function extras.tablecell(element,detail,n,fulltag,di) +function extras.tablecell(handle,element,detail,n,fulltag,di) local hash = attributehash[fulltag] - local v = hash.align - if not v or v == 0 then - -- normal - elseif v == 1 then - handle:write(" align='flushright'") - elseif v == 2 then - handle:write(" align='middle'") - elseif v == 3 then - handle:write(" align='flushleft'") - end - local v = hash.columns - if v and v > 1 then - handle:write(" columns='",v,"'") - end - local v = hash.rows - if v and v > 1 then - handle:write(" rows='",v,"'") + if hash then + local v = hash.align + if not v or v == 0 then + -- normal + elseif v == 1 then + handle:write(" align='flushright'") + elseif v == 2 then + handle:write(" align='middle'") + elseif v == 3 then + handle:write(" align='flushleft'") + end + local v = hash.columns + if v and v > 1 then + handle:write(" columns='",v,"'") + end + local v = hash.rows + if v and v > 1 then + handle:write(" rows='",v,"'") + end end end -function extras.tabulatecell(element,detail,n,fulltag,di) +function extras.tabulatecell(handle,element,detail,n,fulltag,di) local hash = attributehash[fulltag] - local v = hash.align - if not v or v == 0 then - -- normal - elseif v == 1 then - handle:write(" align='flushright'") - elseif v == 2 then - handle:write(" align='middle'") - elseif v == 3 then - handle:write(" align='flushleft'") + if hash then + local v = hash.align + if not v or v == 0 then + -- normal + elseif v == 1 then + handle:write(" align='flushright'") + elseif v == 2 then + handle:write(" align='middle'") + elseif v == 3 then + handle:write(" align='flushleft'") + end end end -local function emptytag(element,nature,depth) +local function emptytag(handle,element,nature,depth) handle:write("\n",spaces[depth],"<",element,"/>\n") end -local function begintag(element,nature,depth,di,empty) +local function begintag(handle,element,nature,depth,di,empty) local detail, n, fulltag = di.detail, di.n, di.fulltag if nature == "inline" then linedone = false @@ -480,7 +623,7 @@ local function begintag(element,nature,depth,di,empty) end local extra = extras[element] if extra then - extra(element,detail,n,fulltag,di) + extra(handle,element,detail,n,fulltag,di) end local u = userdata[fulltag] if u then @@ -496,9 +639,10 @@ local function begintag(element,nature,depth,di,empty) linedone = true end end + used[element][detail or ""] = nature end -local function endtag(element,nature,depth,empty) +local function endtag(handle,element,nature,depth,empty) if nature == "display" then if inlinedepth == 0 then if empty then @@ -556,7 +700,7 @@ local function push(fulltag,depth,entry) data = { }, attribute = attribute, parnumber = parnumber, - node = entry[5], + -- node = entry[5], -- will go } local treedata = tree.data treedata[#treedata+1] = t @@ -574,37 +718,29 @@ local function pop() tree = remove(treestack) end -local function flush(current,content) - if content then - if collapse then - tree.data[#tree.data+1] = content - else - handle:write(content) - end - end -end - local function flushresult(entry) local current, content = entry[1], entry[2] if not content then - -- skip + -- skip, normally this cannot happen else local newdepth, olddepth, content = #current, #treestack, concat(content) if trace_export then - report_export("%3i => %3i : handling: ",olddepth,newdepth,current[newdepth]) + report_export("%s => %s : handling: %s",olddepth,newdepth,current[newdepth]) end if olddepth <= 0 then for i=1,newdepth do if trace_export then - report_export("[1] push :",current[i]) + report_export("[1] push : %s",current[i]) end push(current[i],i,entry) end - flush(current,content) + if content then + tree.data[#tree.data+1] = content + end elseif newdepth < olddepth then for i=newdepth,olddepth-1 do if trace_export then - report_export("[2a] pop :",current[i]) + report_export("[2a] pop : %s",current[i]) end pop() end @@ -613,7 +749,7 @@ local function flushresult(entry) for i=newdepth,1,-1 do if current[i] ~= treestack[i].fulltag then -- needs checking if trace_export then - report_export("[2b] pop :",current[i]) + report_export("[2b] pop : %s",current[i]) end pop() else @@ -623,16 +759,18 @@ local function flushresult(entry) olddepth = #treestack for i=olddepth+1,newdepth do if trace_export then - report_export("[2] push :",current[i]) + report_export("[2] push : %s",current[i]) end push(current[i],i,entry) end - flush(current,content) + if content then + tree.data[#tree.data+1] = content + end elseif newdepth > olddepth then for i=olddepth,1,-1 do if current[i] ~= treestack[i].fulltag then if trace_export then - report_export("[3] pop :",current[i]) + report_export("[3] pop : %s",current[i]) end pop() else @@ -642,19 +780,23 @@ local function flushresult(entry) olddepth = #treestack for i=olddepth+1,newdepth do if trace_export then - report_export("[3] push :",current[i]) + report_export("[3] push : %s",current[i]) end push(current[i],i,entry) end - flush(current,content) + if content then + tree.data[#tree.data+1] = content + end elseif current[newdepth] == treestack[olddepth] then --move up ? -- continuation - flush(current,content) + if content then + tree.data[#tree.data+1] = content + end else for i=olddepth,1,-1 do if current[i] ~= treestack[i].fulltag then if trace_export then - report_export("[4] pop :",current[i]) + report_export("[4] pop : %s",current[i]) end pop() else @@ -664,11 +806,13 @@ local function flushresult(entry) olddepth = #treestack for i=olddepth+1,newdepth do if trace_export then - report_export("[4] push :",current[i]) + report_export("[4] push : %s",current[i]) end push(current[i],i,entry) end - flush(current,content) + if content then + tree.data[#tree.data+1] = content + end end end end @@ -692,47 +836,39 @@ local function checkinserts(data) end end -local function checkreferences(data) - local c = structures.lists.collected - for i=1,#c do -- todo: make hash from name -> n - local ci = c[i] - local name = ci.metadata.kind - local hash = listhash[name] - if not hash then - hash = { } - listhash[name] = hash - end - local tag = ci.references.tag - if tag then - hash[tag] = ci - end - end -end - -local function flushtree(data) - for i=1,#data do +local function flushtree(handle,data,nature) + local nofdata = #data + for i=1,nofdata do local di = data[i] if not di then -- collapsed elseif type(di) == "string" then +if i == nofdata and sub(di,-1) == joiner_7 then + if nature == "inline" or nature == "mixed" then + handle:write(sub(di,1,-2)) + else + handle:write(sub(di,1,-2)," ") + end +else handle:write(di) +end linedone = false elseif not di.collapsed then local element = di.element if element == "break" or element == "pagebreak" then - emptytag(element,nature,di.depth) + emptytag(handle,element,nature,di.depth) else local nature, depth = di.nature, di.depth local did = di.data local nid = #did if nid == 0 or (nid == 1 and did[1] == "") then - begintag(element,nature,depth,di,true) + begintag(handle,element,nature,depth,di,true) -- no content - endtag(element,nature,depth,true) + endtag(handle,element,nature,depth,true) else - begintag(element,nature,depth,di) - flushtree(did) - endtag(element,nature,depth) + begintag(handle,element,nature,depth,di) + flushtree(handle,did,nature) + endtag(handle,element,nature,depth) end end end @@ -750,9 +886,11 @@ local function collapsetree() local lpn = v[i-1].parnumber if lpn and lpn == 0 then lpn = nil end if type(d[1]) ~= "string" then lpn = nil end -- no need anyway so no further testing needed +local justdone = false for j=1,#vd do local vdj = vd[j] if type(vdj) == "string" then +--~ print(vdj) -- experiment, should be improved -- can be simplified ... lpn instead of done if done then @@ -779,6 +917,8 @@ local function collapsetree() end end else +--~ nd = nd + 1 +--~ d[nd] = joiner_3 -- lpn = nil end if vdj ~= "" then @@ -815,7 +955,7 @@ local function prunetree(tree) end end -function finishexport() +local function finishexport() if entry then local result = entry[2] if result and result[#result] == " " then @@ -828,27 +968,25 @@ function finishexport() end end -local function stopexport() - if handle then - report_export("finalizing") - finishexport() - if collapse then - collapsetree() - if trace_tree then - prunetree(tree) - report_export(table.serialize(tree,"root")) - end - end - checkinserts(tree.data) - checkreferences(tree.data) - flushtree(tree.data) - handle = false - end -end +local displaymapping = { + inline = "inline", + display = "block", + mixed = "inline", +} + +local e_template = [[ +%s { + display: %s +}]] + +local d_template = [[ +%s[detail=%s] { + display: %s +}]] -- encoding='utf-8' -local preamble = [[ +local xmlpreamble = [[ @@ -857,23 +995,112 @@ local preamble = [[ ]] -local done = false +local csspreamble = [[ -local function startexport(v) - if not done then - local filename = tex.jobname - if type(v) == "string" and v ~= variables.yes and v ~= "" then - filename = v + +]] + +local cssfile, xhtmlfile = nil, nil + +directives.register("backend.export.css", function(v) cssfile = v end) +directives.register("backend.export.xhtml",function(v) xhtmlfile = v end) + +local function stopexport(v) + starttiming(treehash) + report_export("finalizing") + finishexport() + collapsetree() + if trace_tree then + prunetree(tree) + report_export(table.serialize(tree,"root")) + end + checkinserts(tree.data) + hashlistdata() + if type(v) ~= "string" or v == variables.yes or v == "" then + v = tex.jobname + end + local xmlfile = file.addsuffix(v,"export") + local handle = io.open(xmlfile,"wb") + if handle then + report_export("saving xml data in '%s",xmlfile) + handle:write(format(xmlpreamble,tex.jobname,os.date(),environment.version,version)) + if cssfile then + if type(v) ~= "string" or cssfile == variables.yes or cssfile == "" or cssfile == xmlfile then + cssfile = file.replacesuffix(xmlfile,"css") + else + cssfile = file.addsuffix(cssfile,"css") + end + report_export("adding css reference '%s",cssfile) + handle:write(format(csspreamble,cssfile)) end - local filename = file.addsuffix(filename,"export") -- todo: v - handle = io.open(filename,"wb") - if handle then - nodes.tasks.appendaction("shipouts", "normalizers", "nodes.handlers.export") - report_export("saving xml in '%s",filename) - handle:write(format(preamble,tex.jobname,os.date(),environment.version,version)) - luatex.registerstopactions(stopexport) + flushtree(handle,tree.data) + handle:close() + -- css template file + local cssfile = file.replacesuffix(xmlfile,"template") + report_export("saving css template in '%s",cssfile) + local templates = { format("/* template for file %s */",xmlfile) } + for element, details in table.sortedhash(used) do + templates[#templates+1] = format("/* category: %s */",element) + for detail, nature in table.sortedhash(details) do + local d = displaymapping[nature or "display"] or "block" + if detail == "" then + templates[#templates+1] = format(e_template,element,d) + else + templates[#templates+1] = format(d_template,element,detail,d) + end + end + end + io.savedata(cssfile,concat(templates,"\n\n")) + -- xhtml references + if xhtmlfile then + if type(v) ~= "string" or xhtmlfile == variables.yes or xhtmlfile == "" or xhtmlfile == xmlfile then + xhtmlfile = file.replacesuffix(xmlfile,"xhtml") + else + xhtmlfile = file.addsuffix(xhtmlfile,"xhtml") + end + report_export("saving xhtml variant in '%s",xhtmlfile) + local xmltree = xml.load(xmlfile) + if xmltree then + local xmlwrap = xml.wrap + for e in xml.collected(xmltree,"/document") do + e.at["xmlns:xhtml"] = "http://www.w3.org/1999/xhtml" + break + end + local wrapper = { tg = "a", ns = "xhtml", at = { href = "unknown" } } + for e in xml.collected(xmltree,"link") do + local location = e.at.location + if location then + wrapper.at.href = "#" .. gsub(location,":","_") + xmlwrap(e,wrapper) + end + end + local wrapper = { tg = "a", ns = "xhtml", at = { name = "unknown" } } + for e in xml.collected(xmltree,"!link[@location]") do + local location = e.at.location + if location then + wrapper.at.name = gsub(location,":","_") + xmlwrap(e,wrapper) + end + end + xml.save(xmltree,xhtmlfile) + end + end + else + report_export("unable to saving xml in '%s",xmlfile) + end + stoptiming(treehash) +end + +local function startexport(v) + if v and not exporting then + nodes.tasks.appendaction("shipouts", "normalizers", "nodes.handlers.export") + report_export("enabling export to xml") + luatex.registerstopactions(function() stopexport(v) end) + if trace_spaces then + joiner_1 = "" joiner_2 = "" joiner_3 = "" joiner_4 = "" joiner_5 = "" + joiner_6 = "" joiner_7 = "" joiner_8 = "" joiner_9 = "" joiner_0 = "" end - done = true + exporting = true end end @@ -883,23 +1110,32 @@ local function injectbreak() flushresult(entry) flushresult(makebreak(entry)) result = { } - entry = { entry[1], result, last, lastpar } + entry = { entry[1], result, last, lastpar } -- entry[1] ? +end + +local function injectspace(a,joiner) + flushresult(entry) + result = { joiner } + local tl = taglist[a] + entry = { tl , result, a, lastpar, n } end local function collectresults(head,list,p) - local preceding = p or false -- nasty hack + local preceding = p or false for n in traverse_nodes(head) do local id = n.id -- 14: image, 8: literal (mp) if id == glyph_code then local at = has_attribute(n,a_tagged) if not at then - report_export("skipping character: 0x%05X %s (no attribute)",n.char,utfchar(n.char)) + -- we need to tag the pagebody stuff as being valid skippable + -- + -- report_export("skipping character: 0x%05X %s (no attribute)",n.char,utfchar(n.char)) else - -- we could add tonunicodes for ligatures + -- we could add tonunicodes for ligatures (todo) local components = n.components - if components then - collectresults(components,nil) - preceding = false + if components then -- we loose data + collectresults(components,nil,preceding) +--~ preceding = true else if last ~= at then local tl = taglist[at] @@ -913,16 +1149,20 @@ local function collectresults(head,list,p) result = { } end lastpar = has_attribute(n,a_taggedpar) - entry = { tl , result, at, lastpar, n } - attributehash[tl[#tl]] = { -- this includes detail ! - align = has_attribute(n,a_taggedalign ), - columns = has_attribute(n,a_taggedcolumns), - rows = has_attribute(n,a_taggedrows ), - packed = has_attribute(n,a_taggedpacked ), - symbol = has_attribute(n,a_taggedsymbol ), - insert = has_attribute(n,a_taggedinsert ), - reference = has_attribute(n,a_reference ), + entry = { tl, result, at, lastpar, n } + local ah = { -- this includes detail ! + align = has_attribute(n,a_taggedalign ), + columns = has_attribute(n,a_taggedcolumns), + rows = has_attribute(n,a_taggedrows ), + packed = has_attribute(n,a_taggedpacked ), + symbol = has_attribute(n,a_taggedsymbol ), + insert = has_attribute(n,a_taggedinsert ), + reference = has_attribute(n,a_reference ), + tag = has_attribute(n,a_taggedtag ), -- used for synonyms } + if next(ah) then + attributehash[tl[#tl]] = ah + end last = at elseif last then local at = has_attribute(n,a_taggedpar) @@ -980,44 +1220,74 @@ local function collectresults(head,list,p) last = nil lastpar = nil else - -- maybe check for lines: n.subtype = line_code +--~ if result and #result > 0 then -- and n.subtype == line_code then +--~ local r = result[#result] +--~ if type(r) == "string" and r ~= " " then +--~ local s = utfsub(r,-1) +--~ if s == hyphen then +--~ result[#result] = utfsub(r,1,-2) +--~ elseif s ~= joiner_7 then +--~ result[#result] = r .. joiner_7 +--~ --~ preceding = true +--~ end +--~ end +--~ preceding = false +--~ end + -- we need to determine an end-of-line preceding = collectresults(n.list,n,preceding) preceding = false end - elseif id == disc_code then + elseif id == disc_code then -- probably too late collectresults(n.replace,nil) preceding = false elseif id == glue_code then + -- we need to distinguish between hskips and vskips local subtype = n.subtype - if subtype == userskip_code then + if subtype == userskip_code then -- todo space_code if n.spec.width > threshold then - preceding = true - if result then - if last and #result > 0 and result[#result] ~= " " then - if has_attribute(n,a_tagged) == last then - result[#result+1] = joiner_6 - preceding = false - end +--~ preceding = true + if result and last and #result > 0 and result[#result] ~= " " then + local a = has_attribute(n,a_tagged) + if a == last then + result[#result+1] = joiner_6 + preceding = false + elseif a then + -- e.g LOGOLOGO + preceding = false + last = a + injectspace(last,joiner_6) end end end ---~ elseif subtype == rightskip_code or subtype == parfillskip_code then ---~ if result and last and #result > 0 and result[#result] ~= " " then ---~ result[#result+1] = joiner_7 ---~ end + elseif subtype == rightskip_code or subtype == parfillskip_code then +if result and #result > 0 then -- and n.subtype == line_code then + local r = result[#result] + if type(r) == "string" and r ~= " " then + local s = utfsub(r,-1) + if s == hyphen then + result[#result] = utfsub(r,1,-2) + elseif s ~= joiner_7 then + result[#result] = r .. joiner_7 +--~ preceding = true + end + end + preceding = false +end end elseif id == kern_code then if n.kern > threshold then - preceding = true - if result then - if last and #result > 0 and result[#result] ~= " " then - if has_attribute(n,a_tagged) == last then - result[#result+1] = joiner_8 - preceding = false - end +--~ preceding = true + if result and last and #result > 0 and result[#result] ~= " " then + local a = has_attribute(n,a_tagged) + if a == last then + result[#result+1] = joiner_8 + preceding = false + elseif a then + -- e.g LOGOLOGO + preceding = false + last = a + injectspace(last,joiner_8) end - elseif not preceding then - preceding = true end end end @@ -1026,10 +1296,6 @@ local function collectresults(head,list,p) end function nodes.handlers.export(head) - if trace_spaces then - joiner_1 = "" joiner_2 = "" joiner_3 = "" joiner_4 = "" joiner_5 = "" - joiner_6 = "" joiner_7 = "" joiner_8 = "" joiner_9 = "" joiner_0 = "" - end if result then -- maybe we need a better test for what is in result so far if page_breaks then @@ -1037,7 +1303,15 @@ function nodes.handlers.export(head) end result[#result+1] = joiner_0 end + starttiming(treehash) collectresults(head) -- no flush here, pending page stuff + stoptiming(treehash) return head, true end + +statistics.register("xml exporting time", function() + if exporting then + return format("%s seconds", statistics.elapsedtime(treehash)) + end +end) diff --git a/tex/context/base/back-exp.mkiv b/tex/context/base/back-exp.mkiv index 98da9b06f..2da163a7e 100644 --- a/tex/context/base/back-exp.mkiv +++ b/tex/context/base/back-exp.mkiv @@ -33,6 +33,7 @@ \definesystemattribute[taggedpacked] [public] \definesystemattribute[taggedsymbol] [public] \definesystemattribute[taggedinsert] [public] +\definesystemattribute[taggedtag] [public] \def\setelementexporttag {\dotripleargument\dosetelementexporttag} @@ -74,6 +75,14 @@ \def\dotagtabulatealign{\attribute\taggedalignattribute\ifcase\tabulatealign\attributeunsetvalue\or\plusthree\or\plusone\or\plustwo\or\attributeunsetvalue\fi}% \to \everyenableelements +\appendtoks + \def\dotagsynonym{\ctxlua{structures.tags.setsynonym("\currentsynonym","\currentsynonymtag")}}% +\to \everyenableelements + +\appendtoks + \def\dotagsorting{\ctxlua{structures.tags.setsorting("\currentsorting","\currentsortingtag")}}% +\to \everyenableelements + \appendtoks \def\dotagsetparcounter{\global\advance\tagparcounter\plusone\attribute\taggedparattribute\tagparcounter}% \to \everyenableelements @@ -90,14 +99,24 @@ \def\dotagsetnotesymbol{\ctxlua{structures.tags.setdescriptionid("\currentnote",\currentnotenumber)}}% \to \everyenableelements -% The action: \setubackend[export=yes] % or filename +\appendtoks + \unexpanded\def\doverbatimspace{\char32\relax}% will be done permanently +\to \everyenableelements + +% The action: \setupbackend[export=yes] % or filename -\def\c!export{export} +\def\c!export {export} % maybe: options={css,xhtml} +\def\c!css {css} +\def\c!xhtml {xhtml} \appendtoks \doifsomething{\backendparameter\c!export} - {\setupstructure[\c!state=\v!start]% - \enabledirectives[backend.export=\backendparameter\c!export]}% + {\setupstructure + [\c!state=\v!start]% + \enabledirectives + [backend.export=\backendparameter\c!export,% + backend.export.xhtml=\backendparameter\c!xhtml,% + backend.export.css=\backendparameter\c!css]}% \to \everysetupbackend \protect \endinput diff --git a/tex/context/base/back-ini.lua b/tex/context/base/back-ini.lua index 5cabc16ac..39de73741 100644 --- a/tex/context/base/back-ini.lua +++ b/tex/context/base/back-ini.lua @@ -6,7 +6,6 @@ if not modules then modules = { } end modules ['back-ini'] = { license = "see context related readme files" } -local setmetatable = setmetatable backends = backends or { } local backends = backends @@ -15,21 +14,26 @@ local trace_backend = false trackers.register("backend.initializers", function( local report_backend = logs.reporter("backend","initializing") +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + local function nothing() return nil end backends.nothing = nothing -local mt = { - __index = function(t,k) - t[k] = nothing - return nothing - end -} +local nodeinjections = { } +local codeinjections = { } +local registrations = { } +local tables = allocate() + +local function donothing(t,k) + t[k] = nothing + return nothing +end -local nodeinjections = { } setmetatable(nodeinjections, mt) -local codeinjections = { } setmetatable(codeinjections, mt) -local registrations = { } setmetatable(registrations, mt) -local tables = { } +setmetatableindex(nodeinjections, donothing) +setmetatableindex(codeinjections, donothing) +setmetatableindex(registrations, donothing) local defaults = { nodeinjections = nodeinjections, @@ -40,10 +44,10 @@ local defaults = { backends.defaults = defaults -backends.nodeinjections = { } setmetatable(backends.nodeinjections, { __index = nodeinjections }) -backends.codeinjections = { } setmetatable(backends.codeinjections, { __index = codeinjections }) -backends.registrations = { } setmetatable(backends.registrations, { __index = registrations }) -backends.tables = { } setmetatable(backends.tables, { __index = tables }) +backends.nodeinjections = { } setmetatableindex(backends.nodeinjections, nodeinjections) +backends.codeinjections = { } setmetatableindex(backends.codeinjections, codeinjections) +backends.registrations = { } setmetatableindex(backends.registrations, registrations) +backends.tables = { } setmetatableindex(backends.tables, tables) backends.current = "unknown" @@ -57,8 +61,8 @@ function backends.install(what) backends.current = what for category, default in next, defaults do local target, plugin = backends[category], backend[category] - setmetatable(plugin, { __index = default }) - setmetatable(target, { __index = plugin }) + setmetatableindex(plugin, default) + setmetatableindex(target, plugin) end elseif trace_backend then report_backend("no backend named %s",what) @@ -77,7 +81,7 @@ end) local comment = { "comment", "" } -tables.vfspecials = { +tables.vfspecials = allocate { red = comment, green = comment, blue = comment, diff --git a/tex/context/base/back-pdf.lua b/tex/context/base/back-pdf.lua index 5f4ea465c..f6f82c7f5 100644 --- a/tex/context/base/back-pdf.lua +++ b/tex/context/base/back-pdf.lua @@ -427,6 +427,8 @@ function registrations.transparency(n,a,t) end end +-- overloaded in lpdf-xmp: + function codeinjections.adddocumentinfo(key,value) lpdf.addtoinfo(key,lpdf.tosixteen(value)) end diff --git a/tex/context/base/buff-ver.lua b/tex/context/base/buff-ver.lua index a1f98ab0a..bd274a36a 100644 --- a/tex/context/base/buff-ver.lua +++ b/tex/context/base/buff-ver.lua @@ -18,25 +18,25 @@ local concat = table.concat local C, P, R, V, Carg, Cc, Cs = lpeg.C, lpeg.P, lpeg.R, lpeg.V, lpeg.Carg, lpeg.Cc, lpeg.Cs local patterns, lpegmatch, is_lpeg = lpeg.patterns, lpeg.match, lpeg.is_lpeg -local tabtospace = utilities.strings.tabtospace -local variables = interfaces.variables -local settings_to_array = utilities.parsers.settings_to_array +local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end) +local report_visualizers = logs.reporter("buffers","visualizers") -local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end) +local allocate = utilities.storage.allocate -local report_visualizers = logs.reporter("buffers","visualizers") +visualizers = visualizers or { } +local specifications = allocate() +visualizers.specifications = specifications -visualizers = visualizers or { } +local tabtospace = utilities.strings.tabtospace +local variables = interfaces.variables +local settings_to_array = utilities.parsers.settings_to_array +local verbatim = context.verbatim +local variables = interfaces.variables +local findfile = resolvers.findfile +local addsuffix = file.addsuffix -local specifications = { } visualizers.specifications = specifications - -local verbatim = context.verbatim -local variables = interfaces.variables -local findfile = resolvers.findfile -local addsuffix = file.addsuffix - -local v_auto = variables.auto -local v_yes = variables.yes +local v_auto = variables.auto +local v_yes = variables.yes -- beware, these all get an argument (like newline) @@ -315,7 +315,8 @@ function visualizers.register(name,specification) return specification end -local escapepatterns = { } visualizers.escapepatterns = escapepatterns +local escapepatterns = allocate() +visualizers.escapepatterns = escapepatterns local function texmethod(s) context.bgroup() diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv index ab1d0cb23..114cb2128 100644 --- a/tex/context/base/buff-ver.mkiv +++ b/tex/context/base/buff-ver.mkiv @@ -466,8 +466,9 @@ \def\dodotypeblockverbatim#1#2% {\secondstageinitializetyping - \beginofverbatimlines \dostarttagged\t!verbatimblock\currenttyping + \beginofverbatimlines + \dostarttagged\t!verbatimlines\empty \ctxcommand{typebuffer { name = "_typing_", strip = "\typingparameter\c!strip", @@ -479,6 +480,7 @@ }}% \dostoptagged \endofverbatimlines + \dostoptagged \csname#2\endcsname} \def\dostoptyping#1% hm, currenttyping @@ -578,8 +580,9 @@ \dosetuptypelinenumbering \firststageinitializetyping \secondstageinitializetyping - \beginofverbatimlines \dostarttagged\t!verbatimblock\currenttyping + \beginofverbatimlines + \dostarttagged\t!verbatimlines\empty \ctxcommand{typefile { name = "#2", strip = "\typingparameter\c!strip", @@ -591,6 +594,7 @@ }}% \dostoptagged \endofverbatimlines + \dostoptagged \stoppacked \typingparameter\c!after} @@ -741,7 +745,7 @@ \firststageinitializetyping \secondstageinitializetyping \beginofverbatimlines - \dostarttagged\t!verbatim{#1}% + \dostarttagged\t!verbatimblock{#1}% \ctxcommand{typebuffer { name = "#2", strip = "\typingparameter\c!strip", @@ -813,11 +817,13 @@ \fi} \def\doverbatimemptyline - {\ifconditional\verbatimnumberinglines + {\dostoptagged + \ifconditional\verbatimnumberinglines \par\strut\par % this will be an option where we use a signal instead of a strut \else \blank[\typingparameter\c!blank]% - \fi} + \fi + \dostarttagged\t!verbatimlines\empty} % hooks: diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua index a10b75398..159ff47e7 100644 --- a/tex/context/base/char-ini.lua +++ b/tex/context/base/char-ini.lua @@ -13,20 +13,24 @@ local utf = unicode.utf8 local utfchar, utfbyte, utfvalues = utf.char, utf.byte, string.utfvalues local concat, unpack = table.concat, table.unpack -local next, tonumber, type, rawget, rawset, setmetatable = next, tonumber, type, rawget, rawset, setmetatable +local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset local texsprint, texprint = tex.sprint, tex.print local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch -local texsetlccode, texsetuccode, texsetsfcode, texsetcatcode = tex.setlccode, tex.setuccode, tex.setsfcode, tex.setcatcode local P, R, lpegmatch = lpeg.P, lpeg.R, lpeg.match -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate +local mark = utilities.storage.mark +local texsetlccode = tex.setlccode +local texsetuccode = tex.setuccode +local texsetsfcode = tex.setsfcode +local texsetcatcode = tex.setcatcode +local ctxcatcodes = tex.ctxcatcodes +local texcatcodes = tex.texcatcodes +local setmetatableindex = table.setmetatableindex -local ctxcatcodes = tex.ctxcatcodes -local texcatcodes = tex.texcatcodes +local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end) -local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end) - -local report_defining = logs.reporter("characters") +local report_defining = logs.reporter("characters") --[[ldx--

This module implements some methods and creates additional datastructured @@ -95,7 +99,7 @@ local private = { local ranges = allocate() characters.ranges = ranges -setmetatablekey(data, "__index", function(t,k) +setmetatableindex(data, function(t,k) local tk = type(k) if tk == "string" then k = lpegmatch(pattern,k) or utfbyte(k) @@ -124,9 +128,7 @@ setmetatablekey(data, "__index", function(t,k) end end return private -- handy for when we loop over characters in fonts and check for a property -end ) - ---~ setmetatable(data,{ __index = function(t,k) return "" end }) -- quite old, obsolete +end) local blocks = allocate { ["aegeannumbers"] = { first = 0x10100, last = 0x1013F, description = "Aegean Numbers" }, @@ -304,9 +306,9 @@ local blocks = allocate { characters.blocks = blocks -setmetatable(blocks, { __index = function(t,k) +setmetatableindex(blocks, function(t,k) return k and rawget(t,lower(gsub(k,"[^a-zA-Z]",""))) -end } ) +end) function characters.getrange(name) -- used in font fallback definitions (name or range) local range = blocks[name] @@ -400,10 +402,10 @@ local mt = { -- yes or no ? end } -setmetatable(characters.is_character, mt) -setmetatable(characters.is_letter, mt) -setmetatable(characters.is_command, mt) -setmetatable(characters.is_spacing, mt) +setmetatableindex(characters.is_character, mt) +setmetatableindex(characters.is_letter, mt) +setmetatableindex(characters.is_command, mt) +setmetatableindex(characters.is_spacing, mt) -- linebreak: todo: hash -- @@ -702,32 +704,32 @@ utf.string = utf.string or utfstring characters.categories = allocate() local categories = characters.categories -- lazy table -setmetatable(categories, { __index = function(t,u) if u then local c = data[u] c = c and c.category or u t[u] = c return c end end } ) +setmetatableindex(categories, function(t,u) if u then local c = data[u] c = c and c.category or u t[u] = c return c end end) characters.lccodes = allocate() local lccodes = characters.lccodes -- lazy table characters.uccodes = allocate() local uccodes = characters.uccodes -- lazy table characters.shcodes = allocate() local shcodes = characters.shcodes -- lazy table characters.fscodes = allocate() local fscodes = characters.fscodes -- lazy table -setmetatable(lccodes, { __index = function(t,u) if u then local c = data[u] c = c and c.lccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end } ) -setmetatable(uccodes, { __index = function(t,u) if u then local c = data[u] c = c and c.uccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end } ) -setmetatable(shcodes, { __index = function(t,u) if u then local c = data[u] c = c and c.shcode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end } ) -setmetatable(fscodes, { __index = function(t,u) if u then local c = data[u] c = c and c.fscode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end } ) +setmetatableindex(lccodes, function(t,u) if u then local c = data[u] c = c and c.lccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end) +setmetatableindex(uccodes, function(t,u) if u then local c = data[u] c = c and c.uccode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end) +setmetatableindex(shcodes, function(t,u) if u then local c = data[u] c = c and c.shcode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end) +setmetatableindex(fscodes, function(t,u) if u then local c = data[u] c = c and c.fscode or (type(u) == "string" and utfbyte(u)) or u t[u] = c return c end end) characters.lcchars = allocate() local lcchars = characters.lcchars -- lazy table characters.ucchars = allocate() local ucchars = characters.ucchars -- lazy table characters.shchars = allocate() local shchars = characters.shchars -- lazy table characters.fschars = allocate() local fschars = characters.fschars -- lazy table -setmetatable(lcchars, { __index = function(t,u) if u then local c = data[u] c = c and c.lccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end } ) -setmetatable(ucchars, { __index = function(t,u) if u then local c = data[u] c = c and c.uccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end } ) -setmetatable(shchars, { __index = function(t,u) if u then local c = data[u] c = c and c.shcode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end } ) -setmetatable(fschars, { __index = function(t,u) if u then local c = data[u] c = c and c.fscode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end } ) +setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end) +setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end) +setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end) +setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end) characters.specialchars = allocate() local specialchars = characters.specialchars -- lazy table characters.descriptions = allocate() local descriptions = characters.descriptions -- lazy table -setmetatable(specialchars, { __index = function(t,u) +setmetatableindex(specialchars, function(t,u) if u then local c = data[u] local s = c and c.specials @@ -752,9 +754,9 @@ setmetatable(specialchars, { __index = function(t,u) return u end end -end } ) +end) -setmetatable(descriptions, { __index = function(t,k) +setmetatableindex(descriptions, function(t,k) -- 0.05 - 0.10 sec for u, c in next, data do local d = c.description @@ -769,7 +771,7 @@ setmetatable(descriptions, { __index = function(t,k) t[k] = k end return d -end } ) +end) function characters.unicodechar(asked) local n = tonumber(asked) diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua index da8e70962..8edc05023 100644 --- a/tex/context/base/cldf-ini.lua +++ b/tex/context/base/cldf-ini.lua @@ -21,6 +21,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- __flushlines is an experiment and rather ugly so it will go away +local tex = tex + context = context or { } local context = context @@ -29,31 +31,29 @@ local next, type, tostring, setmetatable = next, type, tostring, setmetatable local insert, remove, concat = table.insert, table.remove, table.concat local lpegmatch = lpeg.match -local tex = tex - -local texsprint = tex.sprint -local textprint = tex.tprint -local texprint = tex.print -local texiowrite = texio.write -local texcount = tex.count +local texsprint = tex.sprint +local textprint = tex.tprint +local texprint = tex.print +local texiowrite = texio.write +local texcount = tex.count -local isnode = node.is_node -- after 0.65 just node.type -local writenode = node.write -local copynodelist = node.copy_list +local isnode = node.is_node -- after 0.65 just node.type +local writenode = node.write +local copynodelist = node.copy_list -local ctxcatcodes = tex.ctxcatcodes -local prtcatcodes = tex.prtcatcodes -local texcatcodes = tex.texcatcodes -local txtcatcodes = tex.txtcatcodes -local vrbcatcodes = tex.vrbcatcodes -local xmlcatcodes = tex.xmlcatcodes +local ctxcatcodes = tex.ctxcatcodes +local prtcatcodes = tex.prtcatcodes +local texcatcodes = tex.texcatcodes +local txtcatcodes = tex.txtcatcodes +local vrbcatcodes = tex.vrbcatcodes +local xmlcatcodes = tex.xmlcatcodes -local flush = texsprint +local flush = texsprint -local report_context = logs.reporter("cld","tex") -local report_cld = logs.reporter("cld","stack") +local report_context = logs.reporter("cld","tex") +local report_cld = logs.reporter("cld","stack") -local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end) +local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end) -- for tracing it's easier to have two stacks @@ -116,11 +116,11 @@ end context._stack_f_ = _stack_f_ context._store_f_ = _store_f_ -context._flush_f_ = _flush_f_ cldff = _flush_f_ +context._flush_f_ = _flush_f_ _cldf_ = _flush_f_ context._stack_n_ = _stack_n_ context._store_n_ = _store_n_ -context._flush_n_ = _flush_n_ cldfn = _flush_n_ +context._flush_n_ = _flush_n_ _cldn_ = _flush_n_ -- Should we keep the catcodes with the function? @@ -285,7 +285,7 @@ local function writer(parent,command,first,...) elseif tn == 1 then -- some 20% faster than the next loop local tj = ti[1] if type(tj) == "function" then - flush(currentcatcodes,"[\\cldff{",_store_f_(tj),"}]") + flush(currentcatcodes,"[\\cldf{",_store_f_(tj),"}]") else flush(currentcatcodes,"[",tj,"]") end @@ -293,13 +293,13 @@ local function writer(parent,command,first,...) for j=1,tn do local tj = ti[j] if type(tj) == "function" then - ti[j] = "\\cldff{" .. _store_f_(tj) .. "}" + ti[j] = "\\cldf{" .. _store_f_(tj) .. "}" end end flush(currentcatcodes,"[",concat(ti,","),"]") end elseif typ == "function" then - flush(currentcatcodes,"{\\cldff{",_store_f_(ti),"}}") -- todo: ctx|prt|texcatcodes + flush(currentcatcodes,"{\\cldf{",_store_f_(ti),"}}") -- todo: ctx|prt|texcatcodes elseif typ == "boolean" then if ti then -- flush(currentcatcodes,"^^M") @@ -310,7 +310,7 @@ local function writer(parent,command,first,...) elseif typ == "thread" then report_context("coroutines not supported as we cannot yield across boundaries") elseif isnode(ti) then -- slow - flush(currentcatcodes,"{\\cldfn{",_store_n_(ti),"}}") + flush(currentcatcodes,"{\\cldn{",_store_n_(ti),"}}") else report_context("error: '%s' gets a weird argument '%s'",command,tostring(ti)) end @@ -354,7 +354,7 @@ local function caller(parent,f,a,...) end elseif typ == "function" then -- ignored: a ... - flush(currentcatcodes,"{\\cldff{",_store_f_(f),"}}") -- todo: ctx|prt|texcatcodes + flush(currentcatcodes,"{\\cldf{",_store_f_(f),"}}") -- todo: ctx|prt|texcatcodes elseif typ == "boolean" then if f then if a ~= nil then @@ -377,7 +377,7 @@ local function caller(parent,f,a,...) report_context("coroutines not supported as we cannot yield across boundaries") elseif isnode(f) then -- slow -- writenode(f) - flush(currentcatcodes,"\\cldfn{",_store_n_(f),"}") + flush(currentcatcodes,"\\cldn{",_store_n_(f),"}") else report_context("error: 'context' gets a weird argument '%s'",tostring(f)) end @@ -625,7 +625,7 @@ local function caller(parent,f,a,...) end elseif typ == "function" then -- ignored: a ... - flush(currentcatcodes,mpdrawing,"{\\cldff{",store_(f),"}}") + flush(currentcatcodes,mpdrawing,"{\\cldf{",store_(f),"}}") elseif typ == "boolean" then -- ignored: a ... if f then diff --git a/tex/context/base/cldf-ini.mkiv b/tex/context/base/cldf-ini.mkiv index 35cf5a2ac..5f7e31ae7 100644 --- a/tex/context/base/cldf-ini.mkiv +++ b/tex/context/base/cldf-ini.mkiv @@ -15,6 +15,9 @@ \registerctxluafile{cldf-ini}{1.001} +\def\cldf#1{\directlua\zerocount{_cldf_(#1)}} % global (functions) +\def\cldn#1{\directlua\zerocount{_cldn_(#1)}} % global (nodes) + \normalprotected\def\cldprocessfile#1{\directlua\zerocount{context.runfile("#1")}} \def\cldcontext #1{\directlua\zerocount{context(#1)}} \def\cldcommand #1{\directlua\zerocount{context.#1}} diff --git a/tex/context/base/cldf-int.lua b/tex/context/base/cldf-int.lua index 4e2e7b0e6..2291fd849 100644 --- a/tex/context/base/cldf-int.lua +++ b/tex/context/base/cldf-int.lua @@ -7,6 +7,8 @@ if not modules then modules = { } end modules ['mult-clm'] = { } -- another experiment +-- needs upgrading +-- needs checking -- todo: multilingual local texsprint, ctxcatcodes, vrbcatcodes = tex.sprint, tex.ctxcatcodes, tex.vrbcatcodes @@ -15,9 +17,10 @@ local unpack = unpack or table.unpack local trace_define = false trackers.register("context.define", function(v) trace_define = v end) -mkiv = mkiv or { } +interfaces = interfaces or { } -mkiv.h, mkiv.a = utilities.parsers.settings_to_hash, utilities.parsers.settings_to_array +_clmh_ = utilities.parsers.settings_to_array +_clma_ = utilities.parsers.settings_to_array local starters, stoppers, macros, stack = { }, { }, { }, { } @@ -30,17 +33,17 @@ local checkers = { "\\dosixtupleempty", } -function mkiv.m(name,...) +function _clmm_(name,...) macros[name](...) end -function mkiv.b(name,...) +function _clmb_(name,...) local sn = stack[name] insert(sn,{...}) starters[name](...) end -function mkiv.e(name) +function _clme_(name) local sn = stack[name] local sv = remove(sn) if sv then @@ -50,9 +53,9 @@ function mkiv.e(name) end end -mkiv.n = tonumber +_clmn_ = tonumber -function mkiv.define(name,specification) -- name is optional +function interfaces.definecommand(name,specification) -- name is optional if type(name) == "table" then specification = name name = specification.name @@ -63,15 +66,15 @@ function mkiv.define(name,specification) -- name is optional local environment = specification.environment if na == 0 then if environment then - texsprint(ctxcatcodes,"\\mkdefstart{",name,"}{\\ctxlua{mkiv.b('",name,"')}}") - texsprint(ctxcatcodes,"\\mkdefstop{", name,"}{\\ctxlua{mkiv.b('",name,"')}}") + texsprint(ctxcatcodes,"\\clmb{",name,"}{\\ctxlua{_clmb_('",name,"')}}") + texsprint(ctxcatcodes,"\\clme{",name,"}{\\ctxlua{_clme_('",name,"')}}") else - texsprint(ctxcatcodes,"\\mkivdef{", name,"}{\\ctxlua{mkiv.m('",name,"')}}") + texsprint(ctxcatcodes,"\\clmm{",name,"}{\\ctxlua{_clmm_('",name,"')}}") end else stack[name] = { } local opt, done = 0, false - local mkivdo = "\\mkivdo" .. name + local mkivdo = "\\mkivdo" .. name -- maybe clddo texsprint(ctxcatcodes,"\\def",mkivdo) for i=1,na do local a = arguments[i] @@ -87,29 +90,29 @@ function mkiv.define(name,specification) -- name is optional end end if environment then - texsprint(ctxcatcodes,"{\\ctxlua{mkiv.b('",name,"'") + texsprint(ctxcatcodes,"{\\ctxlua{_clmb_('",name,"'") else - texsprint(ctxcatcodes,"{\\ctxlua{mkiv.m('",name,"'") + texsprint(ctxcatcodes,"{\\ctxlua{_clmm_('",name,"'") end for i=1,na do local a = arguments[i] local variant = a[2] if variant == "list" then - texsprint(ctxcatcodes,",mkiv.a([[#",i,"]])") + texsprint(ctxcatcodes,",_clma_([[#",i,"]])") elseif variant == "hash" then - texsprint(ctxcatcodes,",mkiv.h([[#",i,"]])") + texsprint(ctxcatcodes,",_clmh_([[#",i,"]])") elseif variant == "number" then - texsprint(ctxcatcodes,",mkiv.n([[#",i,"]])") + texsprint(ctxcatcodes,",_clmn_([[#",i,"]])") else texsprint(ctxcatcodes,",[[#",i,"]]") end end texsprint(ctxcatcodes,")}}") if environment then - texsprint(ctxcatcodes,"\\mkivdefstop{" ,name,"}{\\ctxlua{mkiv.e('",name,"')}}") - texsprint(ctxcatcodes,"\\mkivdefstart{",name,"}{",checkers[opt],mkivdo,"}") + texsprint(ctxcatcodes,"\\clme{",name,"}{\\ctxlua{_clme_('",name,"')}}") + texsprint(ctxcatcodes,"\\clmb{",name,"}{",checkers[opt],mkivdo,"}") else - texsprint(ctxcatcodes,"\\mkivdef{", name,"}{",checkers[opt],mkivdo,"}") + texsprint(ctxcatcodes,"\\clmm{",name,"}{",checkers[opt],mkivdo,"}") end end if environment then @@ -121,7 +124,7 @@ function mkiv.define(name,specification) -- name is optional end end -function mkiv.tolist(t) +function interfaces.tolist(t) local r = { } for i=1,#t do r[i] = t[i] @@ -139,15 +142,15 @@ end --~ \startluacode --~ function test(opt_1, opt_2, arg_1) --~ context.startnarrower() ---~ context("options 1: %s",mkiv.tolist(opt_1)) +--~ context("options 1: %s",interfaces.tolist(opt_1)) --~ context.par() ---~ context("options 2: %s",mkiv.tolist(opt_2)) +--~ context("options 2: %s",interfaces.tolist(opt_2)) --~ context.par() --~ context("argument 1: %s",arg_1) --~ context.stopnarrower() --~ end ---~ mkiv.define { +--~ interfaces.definecommand { --~ name = "test", --~ arguments = { --~ { "option", "list" }, @@ -163,17 +166,17 @@ end --~ \startluacode --~ local function startmore(opt_1) --~ context.startnarrower() ---~ context("start more, options: %s",mkiv.tolist(opt_1)) +--~ context("start more, options: %s",interfaces.tolist(opt_1)) --~ context.startnarrower() --~ end --~ local function stopmore(opt_1) --~ context.stopnarrower() ---~ context("stop more, options: %s",mkiv.tolist(opt_1)) +--~ context("stop more, options: %s",interfaces.tolist(opt_1)) --~ context.stopnarrower() --~ end ---~ mkiv.define ( "more", { +--~ interfaces.definecommand ( "more", { --~ environment = true, --~ arguments = { --~ { "option", "list" }, diff --git a/tex/context/base/cldf-int.mkiv b/tex/context/base/cldf-int.mkiv index b510dfe80..cedac8fc0 100644 --- a/tex/context/base/cldf-int.mkiv +++ b/tex/context/base/cldf-int.mkiv @@ -17,14 +17,8 @@ \unprotect -\unexpanded\def\mkivdefstart #1{\unexpanded\expandafter\def\csname\e!start#1\endcsname} -\unexpanded\def\mkivdefstop #1{\unexpanded\expandafter\def\csname\e!stop #1\endcsname} -\unexpanded\def\mkivdef #1{\unexpanded\expandafter\def\csname #1\endcsname} - - \def\cldff #1{\directlua\zerocount{cldff(#1)}} % global (functions) - \def\cldfn #1{\directlua\zerocount{cldfn(#1)}} % global (nodes) - - %\def\mkivflush #1{\directlua\zerocount{context._flush_f_(#1)}} % obsolete - \let\mkivflush \cldff +\unexpanded\def\clmb#1{\unexpanded\expandafter\def\csname\e!start#1\endcsname} +\unexpanded\def\clme#1{\unexpanded\expandafter\def\csname\e!stop #1\endcsname} +\unexpanded\def\clmm#1{\unexpanded\expandafter\def\csname #1\endcsname} \protect \endinput diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index 67a42198f..6d4d27f53 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.04.03 22:32} +\newcontextversion{2011.04.11 16:45} %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 acc44ba36..cbf10277a 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.04.03 22:32} +\newcontextversion{2011.04.11 16:45} %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.mkii b/tex/context/base/context.mkii index dcadc7c69..3223fea70 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.04.03 22:32} +\edef\contextversion{2011.04.11 16:45} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index c303419b9..64e2b5e28 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.04.03 22:32} +\edef\contextversion{2011.04.11 16:45} %D For those who want to use this: diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua index 3ad9f6c98..3b2d396b0 100644 --- a/tex/context/base/core-con.lua +++ b/tex/context/base/core-con.lua @@ -17,14 +17,16 @@ slower but look nicer this way.

local utf = unicode.utf8 local floor, date, time, concat = math.floor, os.date, os.time, table.concat -local lower, format, rep = string.lower, string.format, string.rep +local lower, format, rep, match = string.lower, string.format, string.rep, string.match local utfchar, utfbyte = utf.char, utf.byte local tonumber, tostring = tonumber, tostring local settings_to_array = utilities.parsers.settings_to_array local allocate = utilities.storage.allocate -local context = context +local context = context + +local variables = interfaces.variables converters = converters or { } local converters = converters @@ -697,3 +699,170 @@ end -- function converters.Alphabetic(n,code) -- do_alphabetic(n,counters[code] or counters['**'],uppercased) -- end + +-- -- + +local ordinals = { + english = function(n) + local two = n % 100 + if two == 11 or two == 12 or to == 13 then + return "th" + else + local one = n % 10 + if one == 1 then + return "st" + elseif one == 2 then + return "nd" + elseif one == 3 then + return "rd" + else + return "th" + end + end + end, + dutch = function(n) + return "e" + end, + french = function(n) + if n == 1 then + return "er" + end + end, +} + +ordinals.en = ordinals.english +ordinals.nl = ordinals.dutch +ordinals.fr = ordinals.french + +function converters.ordinal(n,language) + local t = language and ordinals[language] + return t and t(n) +end + +function commands.ordinal(n,language) + local t = language and ordinals[language] + local o = t and t(n) + if o then + context.highordinalstr(o) + end +end + +-- -- + +local v_day = variables.day +local v_year = variables.year +local v_month = variables.month +local v_weekday = variables.weekday +local v_referral = variables.referral + +local convert = converters.convert + +local days = { + variables.sunday, + variables.monday, + variables.tuesday, + variables.wednesday, + variables.thursday, + variables.friday, + variables.saturday, +} + +local months = { + variables.january, + variables.february, + variables.march, + variables.april, + variables.may, + variables.june, + variables.july, + variables.august, + variables.september, + variables.october, + variables.november, + variables.december, +} + +function commands.dayname(n) + context.labeltext(days[n] or "unknown") +end + +function commands.weekdayname(day,month,year) + context.labeltext(days[weekday(day,month,year)] or "unknown") +end + +function commands.monthname(n) + context.labeltext(months[n] or "unknown") +end + +function commands.monthmnem(n) + local m = months[n] + context.labeltext(m and (m ..":mnem") or "unknown") +end + +-- a prelude to a function that we can use at the lua end + +-- historic : day+ month:mnem +-- maybe better: day:ord month:mmem + +function commands.currentdate(str,currentlanguage) -- j and jj obsolete + local list = utilities.parsers.settings_to_array(str) + local year, month, day = tex.year, tex.month, tex.day + local auto = true + for i=1,#list do + local entry = list[i] + local tag, plus = match(entry,"^([^%+:]+)(.*)$") + local ordinal, mnemonic, whatordinal = false, false, nil + if not tag then + tag = entry + elseif plus == "+" or plus == "ord" then + ordinal = true + elseif plus == "mnem" then + mnemonic = true + end + if not auto and (tag == v_year or tag == v_month or tag == v_day or tag == v_weekday) then + context.space() + end + auto = false + if tag == v_year or tag == "y" then + context.convertnumber(v_year,year) + elseif tag == "yy" then + context("%02i",year % 100) + elseif tag == "Y" then + context(year) + elseif tag == v_month or tag == "m" then + if mnemonic then + commands.monthmnem(month) + else + commands.monthname(month) + end + elseif tag == "mm" then + context("%02i",month) + elseif tag == "M" then + context(month) + elseif tag == v_day or tag == "d" then + context.convertnumber(v_day,day) + whatordinal = day + elseif tag == "dd" then + context("%02i",day) + whatordinal = day + elseif tag == "D" then + context(day) + whatordinal = day + elseif tag == v_weekday or tag == "w" then + commands.dayname(weekday(day,month,year)) + elseif tag == "W" then + context(weekday(day,month,year)) + elseif tag == v_referral then + context("%04i%02i%02i",year,month,day) + elseif tag == v_space or tag == "\\ " then + context.space() + auto = true + elseif tag ~= "" then + context(tag) + auto = true + end + if ordinal and whatordinal then + commands.ordinal(whatordinal,currentlanguage) + end + end +end diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv index e2ae88f60..75f2b6acd 100644 --- a/tex/context/base/core-con.mkiv +++ b/tex/context/base/core-con.mkiv @@ -17,7 +17,7 @@ \unprotect -\ifx\currentlanguage\undefined \let\currentlanguage\empty \fi +\ifx\currentlanguage\undefined \let\currentlanguage\empty \fi \ifx\labeltext \undefined \let\labeltext\firstofoneargument \fi %D This module deals with all kind of conversions from numbers @@ -202,17 +202,8 @@ %D %D Anyhow, the conversion looks like: -\def\domonthtag#1% - {\ifcase#1% - \or \v!january \or \v!february \or \v!march \or \v!april - \or \v!may \or \v!june \or \v!july \or \v!august - \or \v!september \or \v!october \or \v!november \or \v!december - \else - \v!unknown - \fi} - -\def\doconvertmonthlong #1{\labeltext{\domonthtag{#1}}} -\def\doconvertmonthshort#1{\labeltext{\domonthtag{#1}:\s!mnem}} +\def\doconvertmonthlong #1{\ctxcommand{month(#1)}} +\def\doconvertmonthshort#1{\ctxcommand{monthmnem(#1)}} \let\doconvertmonth\doconvertmonthlong @@ -245,25 +236,18 @@ %D 2000 into leap years, right? Well, converting to string %D looks familiar: -\def\doconvertday#1% - {\labeltext - {\ifcase#1 - \or \v!sunday \or \v!monday \or \v!tuesday \or \v!wednesday - \or \v!thursday \or \v!friday \or \v!saturday \fi}} +\def\doconvertday#1{\ctxcommand{day(#1)}} %D \macros %D {getdayoftheweek, dayoftheweek} -%D -%D The conversion algoritm is an old one and a translation from -%D a procedure written in MODULA~2 back in the 80's. I finaly -%D found the 4--100-400 rules in some enclopedia. Look at this -%D messy low level routine that takes the day, month and year -%D as arguments: \newcount\normalweekday -\def\getdayoftheweek#1#2#3{\normalweekday\ctxcommand{weekday(\number#1,\number#2,\number#3)}} -\def\dayoftheweek #1#2#3{\doconvertday{\ctxcommand{weekday(\number#1,\number#2,\number#3)}}} +% \def\getdayoftheweek#1#2#3{\normalweekday\ctxcommand{weekday(\number#1,\number#2,\number#3)}} +% \def\dayoftheweek #1#2#3{\doconvertday{\ctxcommand{weekday(\number#1,\number#2,\number#3)}}} + +\def\getdayoftheweek#1#2#3{\normalweekday\ctxcommand{weekday(\number#1,\number#2,\number#3)}\relax} % number +\def\dayoftheweek #1#2#3{\ctxcommand{weekdayname(\number#1,\number#2,\number#3)}} % name %D Using this macro in %D @@ -412,79 +396,131 @@ %D \getbuffer %D \stoplines -\def\referraldatepattern{j,mm,dd} % jj,mm,dd changed at januari 1-1-2000 - -\newsignal\datesignal - -\def\dobetweendates - {\ifdim\lastskip=\datesignal\relax\else - \unskip\space - \hskip\datesignal\relax - \fi} - -\def\dodobetweendates - {\let\betweendates\dobetweendates}% +% \newtoks \everycurrentdate +% +% \newsignal\datesignal +% +% \def\dobetweendates +% {\ifdim\lastskip=\datesignal\relax\else +% \unskip\space +% \hskip\datesignal\relax +% \fi} +% +% \def\referraldatepattern{j,mm,dd} % jj,mm,dd changed at januari 1-1-2000 +% +% \def\dodobetweendates +% {\let\betweendates\dobetweendates}% +% +% \def\dodocurrentdate#1% +% {\processallactionsinset[#1] +% [ \v!year=>\betweendates +% \convertnumber\v!year\normalyear, +% yy=>\lasttwodigits\normalyear, +% y=>\convertnumber\v!year\normalyear, +% Y=>\number\normalyear, +% \v!month=>\betweendates +% \month\normalmonth, +% mm=>\twodigits\normalmonth, +% m=>\month\normalmonth, +% M=>\number\normalmonth, +% \v!day=>\betweendates +% \convertnumber\v!day\normalday, +% \v!day+=>\betweendates +% \convertnumber\v!day\normalday +% \ordinal\normalday, +% dd=>\twodigits\normalday, +% dd+=>\convertnumber\v!day{\twodigits\normalday}% +% \ordinal\normalday, +% d=>\convertnumber\v!day\normalday, +% d+=>\convertnumber\v!day\normalday +% \ordinal\normalday, +% d=>\number\normalday, +% \v!weekday=>\betweendates +% \convertnumber\v!day{\dayoftheweek\normalday\normalmonth\normalyear}, +% w=>\convertnumber\v!day{\dayoftheweek\normalday\normalmonth\normalyear}, +% W=>\dayoftheweek\normalday\normalmonth\normalyear, +% \v!referral=>\docomplexcurrentdate\referraldatepattern, +% \v!space=>\unskip\ \hskip\datesignal, +% \ =>\unskip\ \hskip\datesignal, +% \s!default=>, +% \s!unknown=>\unskip\commalistelement +% \hskip\datesignal +% \let\betweendates\dodobetweendates]} +% +% \def\docurrentdate[#1]% +% {\begingroup +% \the\everycurrentdate +% \let\betweendates\dodobetweendates +% \doifsomething{#1}{\edef\currentdatespecification{#1}}% +% \normalexpanded{\dodocurrentdate{\currentdatespecification}}% +% \ifdim\lastskip=\datesignal\relax +% \unskip +% \fi +% \endgroup} + +%D \starttabulate[|l|l|] +%D \HL +%D \NC year \NC (\currentdate[year]) \NC\NR +%D \NC yy \NC (\currentdate[yy]) \NC\NR +%D \NC y \NC (\currentdate[y]) \NC\NR +%D \NC Y \NC (\currentdate[Y]) \NC\NR +%D \HL +%D \NC month \NC (\currentdate[month]) \NC\NR +%D \NC mm \NC (\currentdate[mm]) \NC\NR +%D \NC m \NC (\currentdate[m]) \NC\NR +%D \NC M \NC (\currentdate[M]) \NC\NR +%D \HL +%D \NC day \NC (\currentdate[day]) \NC\NR +%D \NC dd \NC (\currentdate[dd]) \NC\NR +%D \NC d \NC (\currentdate[d]) \NC\NR +%D \NC D \NC (\currentdate[D]) \NC\NR +%D \HL +%D \NC weekday \NC (\currentdate[weekday]) \NC\NR +%D \NC w \NC (\currentdate[w]) \NC\NR +%D \NC W \NC (\currentdate[W]) \NC\NR +%D \HL +%D \NC referral \NC (\currentdate[referral]) \NC\NR +%D \HL +%D \NC day+ \NC (\currentdate[day+]) \NC\NR +%D \NC dd+ \NC (\currentdate[dd+]) \NC\NR +%D \NC d+ \NC (\currentdate[d+]) \NC\NR +%D \NC D+ \NC (\currentdate[D+]) \NC\NR +%D \HL +%D \stoptabulate +%D +%D \startbuffer +%D (\currentdate[D,.,M,.,Y]) +%D (\currentdate[day,month,year]) +%D (\currentdate[day,+,month,+,year]) +%D \stopbuffer +%D +%D \typebuffer \getbuffer \newtoks \everycurrentdate -\def\docomplexcurrentdate#1% - {\normalexpanded{\noexpand\processallactionsinset[#1]} - [ \v!day=>\betweendates\the\normalday, - \v!day+=>\betweendates\convertnumber{\v!day+}\normalday, - \v!month=>\betweendates\month\normalmonth, - \v!year=>\betweendates\the\normalyear, - \v!space=>\unskip\ \hskip\datesignal, - \ =>\unskip\ \hskip\datesignal, - d=>\convertnumber\v!day\normalday, - d+=>\convertnumber{\v!day+}\normalday, - m=>\convertnumber\v!month\normalmonth, - j=>\convertnumber\v!year\normalyear, - y=>\convertnumber\v!year\normalyear, - w=>\betweendates\dayoftheweek\normalday\normalmonth\normalyear, - dd=>\ifnum\normalday >9 \else0\fi\the\normalday, - dd+=>\convertnumber{\v!day+}{\ifnum\normalday >9 \else0\fi\the\normalday}, - mm=>\ifnum\normalmonth>9 \else0\fi\the\normalmonth, - jj=>\expandafter\gobbletwoarguments\the\normalyear, - yy=>\expandafter\gobbletwoarguments\the\normalyear, - \v!weekday=>\betweendates\dayoftheweek\normalday\normalmonth\normalyear, - \v!referral=>\docomplexcurrentdate\referraldatepattern, - \s!default=>, - \s!unknown=>\unskip\commalistelement\hskip\datesignal\let\betweendates\dodobetweendates]} - -\def\complexcurrentdate[#1]% - {\bgroup - \the\everycurrentdate - \let\betweendates\dodobetweendates - \docomplexcurrentdate{#1}% - \ifdim\lastskip=\datesignal\relax - \unskip - \fi - \egroup} +\unexpanded\def\currentdate + {\dosingleempty\docurrentdate} -\def\simplecurrentdate - {\complexcurrentdate[\currentdatespecification]} +\def\docurrentdate[#1]% + {\begingroup + \the\everycurrentdate + \doifsomething{#1}{\edef\currentdatespecification{#1}}% + \ctxcommand{currentdate(\!!bs\currentdatespecification\!!es,"\labellanguage")}% + \endgroup} -\definecomplexorsimple\currentdate +\unexpanded\def\date + {\dodoubleempty\dodate} \def\dodate[#1][#2]% - {\bgroup + {\begingroup \iffirstargument \getparameters[\??da][d=\normalday,m=\normalmonth,y=\normalyear,#1]% \normalday \@@dad\relax \normalmonth\@@dam\relax \normalyear \@@day\relax - \ifsecondargument - \currentdate[#2]% - \else - \currentdate - \fi - \else - \currentdate \fi - \egroup} - -\def\date - {\dodoubleempty\dodate} + \docurrentdate{#2}% + \endgroup} %D \macros %D {currenttime} @@ -493,7 +529,7 @@ %D a pattern similar to the previous date macro using the %D keys \type {h}, \type {m} and a separator. -\def\calculatecurrenttime +\unexpanded\def\calculatecurrenttime {\edef\currenthour {\ctxcommand{hour ()}}% \edef\currentminute{\ctxcommand{minute()}}% \edef\currentsecond{\ctxcommand{second()}}} @@ -505,8 +541,7 @@ \def\complexcurrenttime[#1]% {\calculatecurrenttime - \processallactionsinset[#1] - [h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]} + \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]} \def\simplecurrenttime {\expanded{\complexcurrenttime[\currenttimespecification]}} @@ -592,19 +627,16 @@ %D need to handle the second argument. \def\convertnumber#1#2% - {\csname\??cv % we want a fully expandable (no if interference) - \ifcsname\??cv\currentlanguage#1\endcsname - \currentlanguage#1% - \@EA\firstoftwoarguments % dirty, gobble {#1} - \else\ifcsname\??cv#1\endcsname - #1% - \@EAEAEA\firstoftwoarguments % dirty, gobble {#1} - \else - ->\s!default - \fi\fi + {\csname + \??cv=>% we want a fully expandable (no if interference) + \ifcsname\??cv\currentlanguage#1\endcsname1\else + \ifcsname\??cv #1\endcsname2\else + 3\fi\fi \endcsname{#1}{\number#2}} -\letvalue{\??cv->\s!default}\docheckedconversion +\setvalue{\??cv=>1}#1{\csname\??cv\currentlanguage#1\endcsname} +\setvalue{\??cv=>2}#1{\csname\??cv #1\endcsname} +\letvalue{\??cv=>3}\checkedconversion \def\doifconversiondefinedelse#1% {\ifcsname\??cv\currentlanguage#1\endcsname @@ -639,14 +671,9 @@ %D difficult to implement. Fortunately dates never exceed the %D number~31. -\ifx\high \undefined \let\high \firstofoneargument \fi -\ifx\notsmallcapped\undefined \let\notsmallcapped\firstofoneargument \fi - -\def\highordinalstr#1{\high{\notsmallcapped{#1}}} -\def\ordinalstr #1{\notsmallcapped{#1}} - -\def\ordinaldaynumber#1% \strippedcsname\ordinaldaynumber - {\expanded{\executeifdefined{\currentlanguage ordinaldaynumber}\noexpand\firstofoneargument{\number#1}}} +\def\highordinalstr #1{\high{\notsmallcapped{#1}}} +\def\ordinalstr #1{\notsmallcapped{#1}} +\def\ordinaldaynumber #1{\ctxcommand{ordinal(#1,"\currentlanguage"}} %D As longs as symbols are linked to levels or numbers, we can %D also use the conversion mechanism, but in for instance the diff --git a/tex/context/base/core-env.lua b/tex/context/base/core-env.lua index 5545b5d32..bc260bc36 100644 --- a/tex/context/base/core-env.lua +++ b/tex/context/base/core-env.lua @@ -11,80 +11,68 @@ if not modules then modules = { } end modules ['core-env'] = { -- -- if tex.modes['xxxx'] then .... else .... end -local csname_id, texcount, create = token.csname_id, tex.count, token.create - local P, C, S, Cc, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.match, lpeg.patterns -local undefined = csname_id("*undefined*crap*") -local iftrue = create("iftrue")[2] -- inefficient hack +local csname_id = token.csname_id +local texcount = tex.count +local create = token.create + +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + +local undefined = csname_id("*undefined*crap*") +local iftrue = create("iftrue")[2] -- inefficient hack + +tex.modes = allocate { } +tex.systemmodes = allocate { } +tex.constants = allocate { } +tex.conditionals = allocate { } +tex.ifs = allocate { } -tex.modes = { } local modes = { } -tex.systemmodes = { } local systemmodes = { } -tex.constants = { } -tex.conditionals = { } -tex.ifs = { } +local modes = { } +local systemmodes = { } -setmetatable(tex.modes, { - __index = function(t,k) - local m = modes[k] - if m then - return m() +setmetatableindex(tex.modes, function(t,k) + local m = modes[k] + if m then + return m() + else + local n = "mode" .. k + if csname_id(n) == undefined then + return false else - local n = "mode" .. k - if csname_id(n) == undefined then - return false - else - modes[k] = function() return texcount[n] >= 1 end - return texcount[n] >= 1 - end + modes[k] = function() return texcount[n] >= 1 end + return texcount[n] >= 1 end end -}) +end) -setmetatable(tex.systemmodes, { - __index = function(t,k) - local m = systemmodes[k] - if m then - return m() +setmetatableindex(tex.systemmodes, function(t,k) + local m = systemmodes[k] + if m then + return m() + else + local n = "mode*" .. k + if csname_id(n) == undefined then + return false else - local n = "mode*" .. k - if csname_id(n) == undefined then - return false - else - systemmodes[k] = function() return texcount[n] >= 1 end - return texcount[n] >= 1 - end + systemmodes[k] = function() return texcount[n] >= 1 end + return texcount[n] >= 1 end end -}) - -setmetatable(tex.constants, { - __index = function(t,k) - return csname_id(k) ~= undefined and texcount[k] or 0 - end, ---~ __newindex = function(t,k) ---~ if csname_id(k) ~= undefined then ---~ texcount[k] = k ---~ end ---~ end -}) - -setmetatable(tex.conditionals, { - __index = function(t,k) -- 0 == true - return csname_id(k) ~= undefined and texcount[k] == 0 - end, ---~ __newindex = function(t,k) -- not ok ---~ if csname_id(k) ~= undefined then ---~ texcount[k] = k and 0 or 1 -- 0 == true ---~ end ---~ end -}) - -setmetatable(tex.ifs, { - __index = function(t,k) - return csname_id(k) ~= undefined and create(k)[2] == iftrue -- inefficient, this create, we need a helper - end -}) +end) + +setmetatableindex(tex.constants, function(t,k) + return csname_id(k) ~= undefined and texcount[k] or 0 +end) + +setmetatableindex(tex.conditionals, function(t,k) -- 0 == true + return csname_id(k) ~= undefined and texcount[k] == 0 +end) + +setmetatableindex(tex.ifs, function(t,k) + return csname_id(k) ~= undefined and create(k)[2] == iftrue -- inefficient, this create, we need a helper +end) ---- arg = P("{") * C(patterns.nested) * P("}") + Cc("") diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua index c1a55b9f9..51f6dd890 100644 --- a/tex/context/base/core-two.lua +++ b/tex/context/base/core-two.lua @@ -8,15 +8,16 @@ if not modules then modules = { } end modules ['core-two'] = { local remove, concat = table.remove, table.concat local texprint = tex.print -local allocate, mark = utilities.storage.allocate, utilities.storage.mark - -local collected, tobesaved = allocate(), allocate() +local allocate = utilities.storage.allocate --[[ldx--

We save multi-pass information in the main utility table. This is a bit of a mess because we support old and new methods.

--ldx]]-- +local collected = allocate() +local tobesaved = allocate() + local jobpasses = { collected = collected, tobesaved = tobesaved, @@ -25,8 +26,8 @@ local jobpasses = { job.passes = jobpasses local function initializer() - collected = mark(jobpasses.collected) - tobesaved = mark(jobpasses.tobesaved) + collected = jobpasses.collected + tobesaved = jobpasses.tobesaved end job.register('job.passes.collected', tobesaved, initializer, nil) diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua index cae744176..02411f13d 100644 --- a/tex/context/base/core-uti.lua +++ b/tex/context/base/core-uti.lua @@ -19,17 +19,20 @@ saves much runtime but at the cost of more memory usage.

local format, match = string.format, string.match local next, type, tostring = next, type, tostring -local definetable, accesstable = utilities.tables.definetable, utilities.tables.accesstable -local serialize = table.serialize -local packers = utilities.packers -local allocate, mark = utilities.storage.allocate, utilities.storage.mark + +local definetable = utilities.tables.definetable +local accesstable = utilities.tables.accesstable +local serialize = table.serialize +local packers = utilities.packers +local allocate = utilities.storage.allocate +local mark = utilities.storage.mark local report_jobcontrol = logs.reporter("jobcontrol") -job = job or { } -local job = job +job = job or { } +local job = job -job.version = 1.14 +job.version = 1.14 -- some day we will implement loading of other jobs and then we need -- job.jobs @@ -57,8 +60,8 @@ function job.initialize(loadname,savename) end) end -function job.register(...) -- collected, tobesaved, initializer, finalizer - savelist[#savelist+1] = { ... } +function job.register(collected, tobesaved, initializer, finalizer) + savelist[#savelist+1] = { collected, tobesaved, initializer, finalizer } end -- as an example we implement variables @@ -81,9 +84,9 @@ job.register('job.variables.checksums', checksums) local rmethod, rvalue local function initializer() - tobesaved = mark(jobvariables.tobesaved) - collected = mark(jobvariables.collected) - checksums = mark(jobvariables.checksums) + tobesaved = jobvariables.tobesaved + collected = jobvariables.collected + checksums = jobvariables.checksums rvalue = collected.randomseed if not rvalue then rvalue = math.random() @@ -168,9 +171,10 @@ function job.load(filename) for l=1,#savelist do local list = savelist[l] local target, initializer = list[1], list[3] - packers.unpack(accesstable(target),job.packed,true) + local result = mark(accesstable(target)) + packers.unpack(result,job.packed,true) if type(initializer) == "function" then - initializer(accesstable(target)) + initializer(result) end end job.packed = nil diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua index a053c1aca..108858ccc 100644 --- a/tex/context/base/data-env.lua +++ b/tex/context/base/data-env.lua @@ -6,17 +6,23 @@ if not modules then modules = { } end modules ['data-env'] = { license = "see context related readme files", } -local allocate = utilities.storage.allocate local lower, gsub = string.lower, string.gsub -local fileextname = file.extname - local resolvers = resolvers -local formats = allocate() resolvers.formats = formats -local suffixes = allocate() resolvers.suffixes = suffixes -local dangerous = allocate() resolvers.dangerous = dangerous -local suffixmap = allocate() resolvers.suffixmap = suffixmap +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local fileextname = file.extname + +local formats = allocate() +local suffixes = allocate() +local dangerous = allocate() +local suffixmap = allocate() + +resolvers.formats = formats +resolvers.suffixes = suffixes +resolvers.dangerous = dangerous +resolvers.suffixmap = suffixmap local relations = allocate { -- todo: handlers also here core = { @@ -228,9 +234,9 @@ local function simplified(t,k) return rawget(t,lower(gsub(k," ",""))) end -setmetatablekey(formats, "__index", simplified) -setmetatablekey(suffixes, "__index", simplified) -setmetatablekey(suffixmap, "__index", simplified) +setmetatableindex(formats, simplified) +setmetatableindex(suffixes, simplified) +setmetatableindex(suffixmap, simplified) -- A few accessors, mostly for command line tool. diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua index 82066a90e..842eed169 100644 --- a/tex/context/base/data-res.lua +++ b/tex/context/base/data-res.lua @@ -16,15 +16,20 @@ if not modules then modules = { } end modules ['data-res'] = { local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys -local next, type, rawget, setmetatable, getmetatable = next, type, rawget, setmetatable, getmetatable +local next, type, rawget = next, type, rawget local os = os local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join -local collapsepath, joinpath = file.collapsepath, file.joinpath -local allocate = utilities.storage.allocate +local filedirname = file.dirname +local filebasename = file.basename +local fileextname = file.extname +local filejoin = file.join +local collapsepath = file.collapsepath +local joinpath = file.joinpath +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end) @@ -169,7 +174,8 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp force_suffixes = true, } - setmetatable(variables, { __index = function(t,k) + setmetatableindex(variables,function(t,k) + local v for i=1,#order do v = order[i][k] if v ~= nil then @@ -182,10 +188,10 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) - setmetatable(environment, { __index = function(t,k) - v = osgetenv(k) + setmetatableindex(environment, function(t,k) + local v = osgetenv(k) if v == nil then v = variables[k] end @@ -195,9 +201,9 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp v = resolvers.repath(v) -- for taco who has a : separated osfontdir t[k] = v return v - end } ) + end) - setmetatable(expansions, { __index = function(t,k) + setmetatableindex(expansions, function(t,k) local v = environment[k] if type(v) == "string" then v = lpegmatch(variableresolver,v) @@ -205,7 +211,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp end t[k] = v return v - end } ) + end) return newinstance @@ -711,7 +717,7 @@ function resolvers.registerfilehash(name,content,someerror) end end -function isreadable(name) +local function isreadable(name) local readable = lfs.isfile(name) -- not file.is_readable(name) asit can be a dir if trace_detail then if readable then diff --git a/tex/context/base/data-tmp.lua b/tex/context/base/data-tmp.lua index 240493195..10cbe4486 100644 --- a/tex/context/base/data-tmp.lua +++ b/tex/context/base/data-tmp.lua @@ -290,6 +290,8 @@ function caches.is_writable(filepath,filename) return file.is_writable(tmaname) end +local saveoptions = { name = "return", reduce = true } + function caches.savedata(filepath,filename,data,raw) local tmaname, tmcname = caches.setluanames(filepath,filename) local reduce, simplify = true, true @@ -298,9 +300,9 @@ function caches.savedata(filepath,filename,data,raw) end data.cache_uuid = os.uuid() if caches.direct then - file.savedata(tmaname, table.serialize(data,'return',false,true,false)) -- no hex + file.savedata(tmaname,table.serialize(data,saveoptions)) else - table.tofile(tmaname, data,'return',false,true,false) -- maybe not the last true + table.tofile(tmaname,data,saveoptions) end utilities.lua.compile(tmaname,tmcname) end diff --git a/tex/context/base/font-col.lua b/tex/context/base/font-col.lua index 945d35d43..e0d2fed11 100644 --- a/tex/context/base/font-col.lua +++ b/tex/context/base/font-col.lua @@ -87,7 +87,7 @@ function collections.define(name,font,ranges,details) end end -function collections.stage_1(name) +function collections.stage_one(name) local last = font.current() if trace_collecting then report_fonts("def: registering font %s with name %s",last,name) @@ -95,7 +95,7 @@ function collections.stage_1(name) list[#list+1] = last end -function collections.stage_2(name) +function collections.stage_two(name) statistics.starttiming(fonts) local d = definitions[name] local t = { } diff --git a/tex/context/base/font-col.mkiv b/tex/context/base/font-col.mkiv index 20af3e91b..f4f9a9dc7 100644 --- a/tex/context/base/font-col.mkiv +++ b/tex/context/base/font-col.mkiv @@ -94,10 +94,10 @@ {\doclonefonta{#1 \savedfontspec}} \def\doclonefontstageone#1% - {\ctxlua{fonts.collections.stage_1("#1")}} + {\ctxlua{fonts.collections.stage_one("#1")}} \def\doclonefontstagetwo#1% - {\ctxlua{fonts.collections.stage_2("#1")}} + {\ctxlua{fonts.collections.stage_two("#1")}} % check : only replace when present in replacement font (default: no) % force : force replacent even when basefont has glyph (default: yes) diff --git a/tex/context/base/font-con.lua b/tex/context/base/font-con.lua index 7e823c6e2..0da0e8e46 100644 --- a/tex/context/base/font-con.lua +++ b/tex/context/base/font-con.lua @@ -9,13 +9,11 @@ if not modules then modules = { } end modules ['font-con'] = { local utf = unicode.utf8 -local next, tostring, setmetatable, rawget = next, tostring, setmetatable, rawget +local next, tostring, rawget = next, tostring, rawget local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub local utfbyte = utf.byte local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy -local allocate = utilities.storage.allocate - local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end) @@ -37,6 +35,9 @@ local specifiers = fonts.specifiers local contextsetups = specifiers.contextsetups local contextnumbers = specifiers.contextnumbers +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + -- will be directives constructors.dontembed = allocate() @@ -670,7 +671,7 @@ function constructors.finalize(tfmdata) -- if not tfmdata.descriptions then local descriptions = { } -- yes or no - setmetatable(descriptions, { __index = function(t,k) local v = { } t[k] = v return v end }) + setmetatableindex(descriptions, function(t,k) local v = { } t[k] = v return v end) tfmdata.descriptions = descriptions end -- @@ -868,16 +869,14 @@ end local formats = allocate() fonts.formats = formats -setmetatable(formats, { - __index = function(t,k) - local l = lower(k) - if rawget(t,k) then - t[k] = l - return l - end - return rawget(t,file.extname(l)) +setmetatableindex(formats, function(t,k) + local l = lower(k) + if rawget(t,k) then + t[k] = l + return l end -} ) + return rawget(t,file.extname(l)) +end) local locations = { } @@ -977,7 +976,7 @@ function constructors.newfeatures(what) local features = handlers[what].features if not features then local tables = handlers[what].tables -- can be preloaded - features = { + features = allocate { defaults = { }, descriptions = tables and tables.features or { }, initializers = { base = { }, node = { } }, diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index fe32a2420..486300bc1 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -29,6 +29,8 @@ local report_defining = logs.reporter("fonts","defining") local report_status = logs.reporter("fonts","status") local report_mapfiles = logs.reporter("fonts","mapfiles") +local setmetatableindex = table.setmetatableindex + local fonts = fonts local handlers = fonts.handlers local otf = handlers.otf -- brrr @@ -94,9 +96,7 @@ function definers.resetnullfont() definers.resetnullfont = function() end end -setmetatablekey(fontdata, "__index", function(t,k) - return nulldata -end) +setmetatableindex(fontdata, function(t,k) return nulldata end) local chardata = allocate() -- chardata local parameters = allocate() @@ -109,26 +109,26 @@ hashes.parameters = parameters hashes.quads = quaddata hashes.xheights = xheightdata -setmetatablekey(chardata, "__index", function(t,k) +setmetatableindex(chardata, function(t,k) local characters = fontdata[k].characters t[k] = characters return characters end) -setmetatablekey(parameters, "__index", function(t,k) +setmetatableindex(parameters, function(t,k) local parameters = fontdata[k].parameters t[k] = parameters return parameters end) -setmetatablekey(quaddata, "__index", function(t,k) +setmetatableindex(quaddata, function(t,k) local parameters = parameters[k] local quad = parameters and parameters.quad or 0 t[k] = quad return quad end) -setmetatablekey(xheightdata, "__index", function(t,k) +setmetatableindex(xheightdata, function(t,k) local parameters = parameters[k] local xheight = parameters and parameters.xheight or 0 t[k] = xheight @@ -865,7 +865,7 @@ mappings.reset() -- resets the default file -- => commands -function nametoslot(name) +local function nametoslot(name) local t = type(name) if t == "string" then local tfmdata = fonts.hashes.identifiers[currentfont()] @@ -1202,20 +1202,18 @@ local xheights = hashes.xheights local currentfont = font.current local texdimen = tex.dimen -setmetatable(number.dimenfactors, { - __index = function(t,k) - if k == "ex" then - return xheigths[currentfont()] - elseif k == "em" then - return quads[currentfont()] - elseif k == "%" then - return dimen.hsize/100 - else - -- error("wrong dimension: " .. (s or "?")) -- better a message - return false - end +setmetatableindex(number.dimenfactors, function(t,k) + if k == "ex" then + return xheigths[currentfont()] + elseif k == "em" then + return quads[currentfont()] + elseif k == "%" then + return dimen.hsize/100 + else + -- error("wrong dimension: " .. (s or "?")) -- better a message + return false end -} ) +end) --[[ldx--

Before a font is passed to we scale it. Here we also need diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index c4904aa39..182e543b0 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -409,18 +409,17 @@ function definers.read(specification,size,id) -- id can be optional, name can al if not tfmdata then -- or id? report_defining( "unknown font %s, loading aborted",specification.name) elseif trace_defining and type(tfmdata) == "table" then - constructors.finalize(tfmdata) - -- local properties = tfmdata.properties or { } - -- local parameters = tfmdata.parameters or { } + local properties = tfmdata.properties or { } + local parameters = tfmdata.parameters or { } report_defining("using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s", - properties.type or "unknown", - id or "?", - properties.name or "?", - parameters.size or "default", - properties.encodingbytes or "?", - properties.encodingname or "unicode", - properties.fullname or "?", - file.basename(properties.filename or "?")) + properties.type or "unknown", + id or "?", + properties.name or "?", + parameters.size or "default", + properties.encodingbytes or "?", + properties.encodingname or "unicode", + properties.fullname or "?", + file.basename(properties.filename or "?")) end statistics.stoptiming(fonts) return tfmdata @@ -430,4 +429,4 @@ end

We overload the reader.

--ldx]]-- -callbacks.register('define_font' , definers.read, "definition of fonts (tfmdata preparation)") +callbacks.register('define_font', definers.read, "definition of fonts (tfmdata preparation)") diff --git a/tex/context/base/font-enc.lua b/tex/context/base/font-enc.lua index a06866225..a6f9250e7 100644 --- a/tex/context/base/font-enc.lua +++ b/tex/context/base/font-enc.lua @@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['font-enc'] = { local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local setmetatableindex = table.setmetatableindex + --[[ldx--

Because encodings are going to disappear, we don't bother defining them in tables. But we may do so some day, for consistency.

@@ -136,10 +138,10 @@ if not encodings.agl then encodings.agl = { } - setmetatable(encodings.agl, { __index = function(t,k) + setmetatableindex(encodings.agl, function(t,k) report_encoding("loading (extended) adobe glyph list") dofile(resolvers.findfile("font-agl.lua")) return rawget(encodings.agl,k) - end }) + end) end diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua index 556f093d4..a5c60d252 100644 --- a/tex/context/base/font-gds.lua +++ b/tex/context/base/font-gds.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['font-gds'] = { -- depends on ctx local type, next = type, next -local gmatch = string.gmatch +local gmatch, format = string.gmatch, string.format local fonts, nodes, attributes, node = fonts, nodes, attributes, node @@ -18,6 +18,9 @@ local report_fonts = logs.reporter("fonts","goodies") local allocate = utilities.storage.allocate +local otf = fonts.handlers.otf +local addotffeature = otf.enhancers.addfeature + local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -305,6 +308,25 @@ function colorschemes.enable() function colorschemes.enable() end end +local function setextrafeatures(tfmdata) + local goodies = tfmdata.goodies + if goodies then + for i=1,#goodies do + local g = goodies[i] + local f = g.features + if f then + for feature, specification in next, f do + addotffeature(tfmdata.shared.rawdata,feature,specification) + registerotffeature { + name = feature, + description = format("extra: %s",feature) + } + end + end + end + end +end + -- installation (collected to keep the overview) -- also for type 1 registerotffeature { @@ -317,23 +339,14 @@ registerotffeature { } } -registerafmfeature { - name = "goodies", - description = "goodies on top of built in features", - initializers = { - position = 1, - base = setgoodies, - node = setgoodies, - } -} - -registertfmfeature { - name = "goodies", - description = "goodies on top of built in features", +registerotffeature { + name = "extrafeatures", + description = "extra features", + default = true, initializers = { - position = 1, - base = setgoodies, - node = setgoodies, + position = 2, + base = setextrafeatures, + node = setextrafeatures, } } @@ -341,7 +354,7 @@ registerotffeature { name = "featureset", description = "goodie feature set", initializers = { - position = 2, + position = 3, base = setfeatureset, node = setfeatureset, } @@ -365,6 +378,30 @@ registerotffeature { } } +-- afm + +registerafmfeature { + name = "goodies", + description = "goodies on top of built in features", + initializers = { + position = 1, + base = setgoodies, + node = setgoodies, + } +} + +-- tfm + +registertfmfeature { + name = "goodies", + description = "goodies on top of built in features", + initializers = { + position = 1, + base = setgoodies, + node = setgoodies, + } +} + -- experiment, we have to load the definitions immediately as they precede -- the definition so they need to be initialized in the typescript diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv index e8c2ee8af..b179aae35 100644 --- a/tex/context/base/font-ini.mkiv +++ b/tex/context/base/font-ini.mkiv @@ -4394,7 +4394,7 @@ \def\dolookupfontbyspec #1{\ctxcommand{fontlookupinitialize("#1")}} \def\dolookupnoffound {\ctxcommand{fontlookupnoffound()}} -\def\dolookupgetkeyofindex#1#2{\ctxcommand{fontlookupgetkeyofindex("#1",#2))}} +\def\dolookupgetkeyofindex#1#2{\ctxcommand{fontlookupgetkeyofindex("#1",#2)}} \def\dolookupgetkey #1{\ctxcommand{fontlookupgetkey("#1")}} \def\cleanfontname #1{\ctxcommand{cleanfontname("#1")}} diff --git a/tex/context/base/font-log.lua b/tex/context/base/font-log.lua index d89482737..8bc12a215 100644 --- a/tex/context/base/font-log.lua +++ b/tex/context/base/font-log.lua @@ -51,7 +51,7 @@ end function loggers.register(tfmdata,source,specification) -- save file name in spec here ! ! ! ! ! ! if tfmdata and specification and specification.specification then local name = lower(specification.name) - if trace_defining and not fonts.used[name] then + if trace_defining and not usedfonts[name] then report_defining("registering %s as %s (used: %s)",file.basename(specification.name),source,file.basename(specification.filename)) end specification.source = source diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua index 368eb4b9e..3de1cd30d 100644 --- a/tex/context/base/font-mis.lua +++ b/tex/context/base/font-mis.lua @@ -22,7 +22,7 @@ local handlers = fonts.handlers handlers.otf = handlers.otf or { } local otf = handlers.otf -otf.version = otf.version or 2.721 +otf.version = otf.version or 2.722 otf.cache = otf.cache or containers.define("fonts", "otf", otf.version, true) function otf.loadcached(filename,format,sub) diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua index a820236fd..cb41194ee 100644 --- a/tex/context/base/font-ota.lua +++ b/tex/context/base/font-ota.lua @@ -14,14 +14,15 @@ if not trackers then trackers = { register = function() end } end local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) -local fonts, nodes = fonts, nodes -local node = node +local fonts, nodes, node = fonts, nodes, node + +local allocate = utilities.storage.allocate local otf = fonts.handlers.otf local analyzers = fonts.analyzers -local initializers = { } -local methods = { } +local initializers = allocate() +local methods = allocate() analyzers.initializers = initializers analyzers.methods = methods diff --git a/tex/context/base/font-otc.lua b/tex/context/base/font-otc.lua index 5fdcf203b..1b4983ce0 100644 --- a/tex/context/base/font-otc.lua +++ b/tex/context/base/font-otc.lua @@ -19,6 +19,7 @@ local fonts = fonts local otf = fonts.handlers.otf local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register +local setmetatableindex = table.setmetatableindex -- In the userdata interface we can not longer tweak the loaded font as -- conveniently as before. For instance, instead of pushing extra data in @@ -26,118 +27,49 @@ local registerotffeature = otffeatures.register -- the mkiv representation. And as the fontloader interface is modelled -- after fontforge we cannot change that one too much either. -local extra_lists = { - tlig = { - { - endash = "hyphen hyphen", - emdash = "hyphen hyphen hyphen", - -- quotedblleft = "quoteleft quoteleft", - -- quotedblright = "quoteright quoteright", - -- quotedblleft = "grave grave", - -- quotedblright = "quotesingle quotesingle", - -- quotedblbase = "comma comma", - }, - }, - trep = { - { - -- [0x0022] = 0x201D, - [0x0027] = 0x2019, - -- [0x0060] = 0x2018, - }, - }, - anum = { - { -- arabic - [0x0030] = 0x0660, - [0x0031] = 0x0661, - [0x0032] = 0x0662, - [0x0033] = 0x0663, - [0x0034] = 0x0664, - [0x0035] = 0x0665, - [0x0036] = 0x0666, - [0x0037] = 0x0667, - [0x0038] = 0x0668, - [0x0039] = 0x0669, - }, - { -- persian - [0x0030] = 0x06F0, - [0x0031] = 0x06F1, - [0x0032] = 0x06F2, - [0x0033] = 0x06F3, - [0x0034] = 0x06F4, - [0x0035] = 0x06F5, - [0x0036] = 0x06F6, - [0x0037] = 0x06F7, - [0x0038] = 0x06F8, - [0x0039] = 0x06F9, - }, - }, +local types = { + substitution = "gsub_single", + ligature = "gsub_ligature", + alternate = "gsub_alternate", } -local extra_features = { -- maybe just 1..n so that we prescribe order - tlig = { - { - features = { ["*"] = { ["*"] = true } }, - name = "ctx_tlig_1", - subtables = { "ctx_tlig_1_s" }, - type = "gsub_ligature", - flags = { }, - }, - }, - trep = { - { - features = { ["*"] = { ["*"] = true } }, - name = "ctx_trep_1", - subtables = { "ctx_trep_1_s" }, - type = "gsub_single", - flags = { }, - }, - }, - anum = { - { - features = { arab = { URD = true, dflt = true } }, - name = "ctx_anum_1", - subtables = { "ctx_anum_1_s" }, - type = "gsub_single", - flags = { }, - }, - { - features = { arab = { URD = true } }, - name = "ctx_anum_2", - subtables = { "ctx_anum_2_s" }, - type = "gsub_single", - flags = { }, - }, - }, -} +setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key" -otf.extrafeatures = extra_features -otf.extralists = extra_lists +local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } +local noflags = { } -local function enhancedata(data,filename,raw) +local function addfeature(data,feature,specifications) local descriptions = data.descriptions local resources = data.resources local lookups = resources.lookups local gsubfeatures = resources.features.gsub - local sequences = resources.sequences - local fontfeatures = resources.features - local unicodes = resources.unicodes - local lookuptypes = resources.lookuptypes - local splitter = lpeg.splitter(" ",unicodes) - for feature, specifications in next, extra_features do - if gsub and gsub[feature] then - -- already present - else - local done = 0 - for s=1,#specifications do - local specification = specifications[s] - local askedfeatures = specification.features - local subtables = specification.subtables - local featurename = specification.name - local featuretype = specification.type - local featureflags = specification.flags - local full = subtables[1] - local list = extra_lists[feature][s] - local added = false + if gsubfeatures and gsubfeatures[feature] then + -- already present + else + local sequences = resources.sequences + local fontfeatures = resources.features + local unicodes = resources.unicodes + local lookuptypes = resources.lookuptypes + local splitter = lpeg.splitter(" ",unicodes) + local done = 0 + if not specifications[1] then + -- so we accept a one entry specification + specifications = { specifications } + end + -- subtables are tables themselves but we also accept flattened singular subtables + for s=1,#specifications do + local specification = specifications[s] + local askedfeatures = specification.features or everywhere + local subtables = specification.subtables or { specification.data } or { } + local featuretype = types[specification.type or "substitution"] + local featureflags = specification.flags or noflags + local added = false + local featurename = format("ctx_%s_%s",feature,s) + local st = { } + for t=1,#subtables do + local list = subtables[t] + local full = format("%s_%s",featurename,t) + st[t] = full if featuretype == "gsub_ligature" then lookuptypes[full] = "ligature" for code, ligature in next, list do @@ -173,58 +105,160 @@ local function enhancedata(data,filename,raw) end end end - if added then - sequences[#sequences+1] = { - chain = 0, - features = { [feature] = askedfeatures }, - flags = featureflags, - name = featurename, - subtables = subtables, - type = featuretype, - } - -- register in metadata (merge as there can be a few) - if not gsubfeatures then - gsubfeatures = { } - fontfeatures.gsub = gsubfeatures + end + if added then + -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... } + for k, v in next, askedfeatures do + if v[1] then + askedfeatures[k] = table.tohash(v) end - local k = gsubfeatures[feature] - if not k then - k = { } - gsubfeatures[feature] = k + end + sequences[#sequences+1] = { + chain = 0, + features = { [feature] = askedfeatures }, + flags = featureflags, + name = featurename, + subtables = st, + type = featuretype, + } + -- register in metadata (merge as there can be a few) + if not gsubfeatures then + gsubfeatures = { } + fontfeatures.gsub = gsubfeatures + end + local k = gsubfeatures[feature] + if not k then + k = { } + gsubfeatures[feature] = k + end + for script, languages in next, askedfeatures do + local kk = k[script] + if not kk then + kk = { } + k[script] = kk end - for script, languages in next, askedfeatures do - local kk = k[script] - if not kk then - kk = { } - k[script] = kk - end - for language, value in next, languages do - kk[language] = value - end + for language, value in next, languages do + kk[language] = value end end end - if done > 0 and trace_loading then - report_otf("enhance: registering %s feature (%s glyphs affected)",feature,done) - end end + if done > 0 and trace_loading then + report_otf("enhance: registering %s feature (%s glyphs affected)",feature,done) + end + end +end + +otf.enhancers.addfeature = addfeature + +local extrafeatures = { } + +function otf.addfeature(name,specification) + extrafeatures[name] = specification +end + +local function enhance(data,filename,raw) + for feature, specification in next, extrafeatures do + addfeature(data,feature,specification) end end -otf.enhancers.register("check extra features",enhancedata) +otf.enhancers.register("check extra features",enhance) + +-- tlig -- + +local tlig = { + endash = "hyphen hyphen", + emdash = "hyphen hyphen hyphen", + -- quotedblleft = "quoteleft quoteleft", + -- quotedblright = "quoteright quoteright", + -- quotedblleft = "grave grave", + -- quotedblright = "quotesingle quotesingle", + -- quotedblbase = "comma comma", +} + +local tlig_specification = { + type = "ligature", + features = everywhere, -- { ["*"] = { ["*"] = true } }, + data = tlig, + flags = noflags, -- { }, +} + +otf.addfeature("tlig",tlig_specification) registerotffeature { name = 'tlig', description = 'tex ligatures', } +-- trep + +local trep = { + -- [0x0022] = 0x201D, + [0x0027] = 0x2019, + -- [0x0060] = 0x2018, +} + +local trep_specification = { + type = "substitution", + features = everywhere, -- { ["*"] = { ["*"] = true } }, + data = trep, + flags = noflags, -- { }, +} + +otf.addfeature("trep",trep_specification) + registerotffeature { name = 'trep', description = 'tex replacements', } +-- anum + +local anum_arabic = { + [0x0030] = 0x0660, + [0x0031] = 0x0661, + [0x0032] = 0x0662, + [0x0033] = 0x0663, + [0x0034] = 0x0664, + [0x0035] = 0x0665, + [0x0036] = 0x0666, + [0x0037] = 0x0667, + [0x0038] = 0x0668, + [0x0039] = 0x0669, +} + +local anum_persian = { + [0x0030] = 0x06F0, + [0x0031] = 0x06F1, + [0x0032] = 0x06F2, + [0x0033] = 0x06F3, + [0x0034] = 0x06F4, + [0x0035] = 0x06F5, + [0x0036] = 0x06F6, + [0x0037] = 0x06F7, + [0x0038] = 0x06F8, + [0x0039] = 0x06F9, +} + +local anum_specification = { + { + type = "substitution", + features = { arab = { URD = true, dflt = true } }, + data = anum_arabic, + flags = noflags, -- { }, + }, + { + type = "substitution", + features = { arab = { URD = true } }, + data = anum_persian, + flags = noflags, -- { }, + }, +} + +otf.addfeature("anum",anum_specification) + registerotffeature { name = 'anum', description = 'arabic digits', } - diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index 59c050e10..84811f0e1 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -25,6 +25,8 @@ local contextsetups = specifiers.contextsetups local contextnumbers = specifiers.contextnumbers local contextmerged = specifiers.contextmerged +local setmetatableindex = table.setmetatableindex + local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -34,13 +36,11 @@ fonts.hashes.dynamics = fontdynamics local a_to_script = { } local a_to_language = { } -setmetatable(fontdynamics, { __index = - function(t,font) - local d = fontdata[font].shared.dynamics or false - t[font] = d - return d - end -}) +setmetatableindex(fontdynamics, function(t,font) + local d = fontdata[font].shared.dynamics or false + t[font] = d + return d +end) function otf.setdynamics(font,attribute) local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller @@ -206,11 +206,11 @@ function otf.dataset(tfmdata,sequences,font,attr) if ra == nil then -- attr can be false ra = { } rl[attr] = ra - setmetatable(ra, { __index = function(t,k) + setmetatableindex(ra, function(t,k) local v = initialize(sequences[k],script,language,s_enabled,a_enabled,attr,dynamic) t[k] = v return v - end}) + end) end return ra diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index 65b868045..e66e3c01b 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -47,7 +47,7 @@ local otf = fonts.handlers.otf otf.glists = { "gsub", "gpos" } -otf.version = 2.721 -- beware: also sync font-mis.lua +otf.version = 2.722 -- beware: also sync font-mis.lua otf.cache = containers.define("fonts", "otf", otf.version, true) local fontdata = fonts.hashes.identifiers @@ -1172,13 +1172,55 @@ end -- to be checked italic_correction +local function check_variants(unicode,the_variants,splitter,unicodes) + local variants = the_variants.variants + if variants then -- use splitter + local glyphs = lpegmatch(splitter,variants) + local done = { [unicode] = true } + local n = 0 + for i=1,#glyphs do + local g = glyphs[i] + if done[g] then + report_otf("skipping cyclic reference U+%05X in math variant U+%05X",g,unicode) + elseif n == 0 then + n = 1 + variants = { g } + else + n = n + 1 + variants[n] = g + end + end + if n == 0 then + variants = nil + end + end + local parts = the_variants.parts + if parts then + local p = #parts + if p > 0 then + for i=1,p do + local pi = parts[i] + pi.glyph = unicodes[pi.component] or 0 + pi.component = nil + end + else + parts = nil + end + end + local italic_correction = the_variants.italic_correction + if italic_correction and italic_correction == 0 then + italic_correction = nil + end + return variants, parts, italic_correction +end + actions["analyze math"] = function(data,filename,raw) if raw.math then data.metadata.math = raw.math local unicodes = data.resources.unicodes local splitter = data.helpers.tounicodetable for unicode, description in next, data.descriptions do - local glyph = description.glyph + local glyph = description.glyph local mathkerns = glyph.mathkern -- singular local horiz_variants = glyph.horiz_variants local vert_variants = glyph.vert_variants @@ -1203,56 +1245,10 @@ actions["analyze math"] = function(data,filename,raw) math.kerns = mathkerns end if horiz_variants then - local variants = horiz_variants.variants - if variants then -- use splitter - local glyphs = lpegmatch(splitter,variants) - for i=1,#glyphs do - if glyphs[i] == u then - remove(glyphs,i) - break - end - end - math.horiz_variants = glyphs - end - local parts = horiz_variants.parts - if parts and #parts > 0 then - for i=1,#parts do - local pi = parts[i] - pi.glyph = unicodes[pi.component] or 0 - pi.component = nil - end - math.horiz_parts = parts - end - local italic_correction = horiz_variants.italic_correction - if italic_correction and italic_correction ~= 0 then - math.horiz_italic_correction = italic_correction - end + math.horiz_variants, math.horiz_parts, math.horiz_italic_correction = check_variants(unicode,horiz_variants,splitter,unicodes) end if vert_variants then - local variants = vert_variants.variants - if variants then - local glyphs = lpegmatch(splitter,variants) - for i=1,#glyphs do - if glyphs[i] == u then - remove(glyphs,i) - break - end - end - math.vert_variants = glyphs - end - local p = vert_variants.parts - if parts and #parts > 0 then - for i=1,#parts do - local pi = parts[i] - pi.glyph = unicodes[pi.component] or 0 - pi.component = nil - end - math.vert_parts = parts - end - local italic_correction = vert_variants.italic_correction - if italic_correction and italic_correction ~= 0 then - math.vert_italic_correction = italic_correction - end + math.vert_variants, math.vert_parts, math.vert_italic_correction = check_variants(unicode,vert_variants,splitter,unicodes) end local italic_correction = description.italic if italic_correction and italic_correction ~= 0 then @@ -1610,25 +1606,39 @@ local function copytotfm(data,cache_id) local m = d.math if m then -- watch out: luatex uses horiz_variants for the parts - local variants, parts = m.horiz_variants, m.horiz_parts + local variants = m.horiz_variants + local parts = m.horiz_parts + -- local done = { [unicode] = true } if variants then local c = character for i=1,#variants do local un = variants[i] - c.next = un - c = characters[un] + -- if done[un] then + -- -- report_otf("skipping cyclic reference U+%05X in math variant U+%05X",un,unicode) + -- else + c.next = un + c = characters[un] + -- done[un] = true + -- end end -- c is now last in chain c.horiz_variants = parts elseif parts then character.horiz_variants = parts end - local variants, parts = m.vert_variants, m.vert_parts + local variants = m.vert_variants + local parts = m.vert_parts + -- local done = { [unicode] = true } if variants then local c = character for i=1,#variants do local un = variants[i] - c.next = un - c = characters[un] + -- if done[un] then + -- -- report_otf("skipping cyclic reference U+%05X in math variant U+%05X",un,unicode) + -- else + c.next = un + c = characters[un] + -- done[un] = true + -- end end -- c is now last in chain c.vert_variants = parts elseif parts then diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua index a5de4ea46..17c1a92e9 100644 --- a/tex/context/base/font-otn.lua +++ b/tex/context/base/font-otn.lua @@ -166,6 +166,8 @@ local find_node_tail = node.tail or node.slide local set_attribute = node.set_attribute local has_attribute = node.has_attribute +local setmetatableindex = table.setmetatableindex + local zwnj = 0x200C local zwj = 0x200D local wildcard = "*" @@ -462,7 +464,7 @@ function handlers.gsub_multiple(start,kind,lookupname,multiple) return multiple_glyphs(start,multiple) end -function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or maybe pass lookup ref +function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) local s, stop, discfound = start.next, nil, false local startchar = start.char if marks[startchar] then @@ -483,14 +485,18 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma end if stop then local lig = ligature.ligature - if trace_ligatures then - local stopchar = stop.char - start = markstoligature(kind,lookupname,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + if lig then + if trace_ligatures then + local stopchar = stop.char + start = markstoligature(kind,lookupname,start,stop,lig) + logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + else + start = markstoligature(kind,lookupname,start,stop,lig) + end + return start, true else - start = markstoligature(kind,lookupname,start,stop,lig) + -- ok, goto next lookup end - return start, true end else local skipmark = sequence.flags[1] @@ -523,14 +529,18 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma end if stop then local lig = ligature.ligature - if trace_ligatures then - local stopchar = stop.char - start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + if lig then + if trace_ligatures then + local stopchar = stop.char + start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + else + start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + end + return start, true else - start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + -- ok, goto next lookup end - return start, true end end return start, false @@ -1843,16 +1853,14 @@ local resolved = { } -- we only resolve a font,script,language pair once local lookuphashes = { } -setmetatable(lookuphashes, { __index = - function(t,font) - local lookuphash = fontdata[font].resources.lookuphash - if not lookuphash or not next(lookuphash) then - lookuphash = false - end - t[font] = lookuphash - return lookuphash +setmetatableindex(lookuphashes, function(t,font) + local lookuphash = fontdata[font].resources.lookuphash + if not lookuphash or not next(lookuphash) then + lookuphash = false end -}) + t[font] = lookuphash + return lookuphash +end) -- fonts.hashes.lookups = lookuphashes @@ -1899,11 +1907,11 @@ function otf.dataset(ftfmdata,sequences,font) -- generic variant, overloaded in if not rl then rl = { } rs[language] = rl - setmetatable(rl, { __index = function(t,k) + setmetatableindex(rl, function(t,k) local v = enabled and initialize(sequences[k],script,language,enabled) t[k] = v return v - end}) + end) end return rl end diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index 1dbf626ca..800fd3c65 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -6,20 +6,21 @@ if not modules then modules = { } end modules ['font-otf'] = { license = "see context related readme files" } -local type, next, tonumber, tostring, rawget, setmetatable = type, next, tonumber, tostring, rawget, setmetatable +local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget local gsub, lower, format, match = string.gsub, string.lower, string.format, string.match local is_boolean = string.is_boolean -local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local allocate = utilities.storage.allocate -local fonts = fonts -local otf = fonts.handlers.otf +local fonts = fonts +local otf = fonts.handlers.otf +local tables = { } +otf.tables = tables -local tables = { } -otf.tables = tables - -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register +local otffeatures = fonts.constructors.newfeatures("otf") +local registerotffeature = otffeatures.register local scripts = allocate { ['arab'] = 'arabic', @@ -672,10 +673,10 @@ local function resolve(t,k) return "dflt" end -setmetatable(verbosescripts, { __index = resolve }) -setmetatable(verboselanguages, { __index = resolve }) -setmetatable(verbosefeatures, { __index = resolve }) -setmetatable(verbosebaselines, { __index = resolve }) +setmetatableindex(verbosescripts, resolve) +setmetatableindex(verboselanguages, resolve) +setmetatableindex(verbosefeatures, resolve) +setmetatableindex(verbosebaselines, resolve) local function resolve(t,k) if k then @@ -688,13 +689,13 @@ local function resolve(t,k) return "dflt" end -local function assign(t,k,v) - -- forget about it -end +setmetatableindex(scripts, resolve) +setmetatableindex(scripts, resolve) +setmetatableindex(languages, resolve) -setmetatable(scripts, { __index = resolve, __newindex = assign }) -setmetatable(languages, { __index = resolve, __newindex = assign }) -setmetatable(baselines, { __index = resolve, __newindex = assign }) +setmetatablenewindex(languages, "ignore") +setmetatablenewindex(baselines, "ignore") +setmetatablenewindex(baselines, "ignore") local function resolve(t,k) if k then @@ -719,6 +720,8 @@ local function resolve(t,k) return "dflt" end +setmetatableindex(features, resolve) + local function assign(t,k,v) if k then v = lower(v) @@ -727,7 +730,7 @@ local function assign(t,k,v) end end -setmetatable(features, { __index = resolve, __newindex = assign }) +setmetatablenewindex(features, assign) local checkers = { rand = function(v) diff --git a/tex/context/base/font-vf.lua b/tex/context/base/font-vf.lua index 8eab88b40..287d073d6 100644 --- a/tex/context/base/font-vf.lua +++ b/tex/context/base/font-vf.lua @@ -12,14 +12,15 @@ changes. This will change.

--ldx]]-- local next = next -local fastcopy = table.fastcopy -local allocate = utilities.storage.allocate +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local fastcopy = table.fastcopy -local fonts = fonts -local constructors = fonts.constructors -local vf = { } -fonts.handlers.vf = vf +local fonts = fonts +local constructors = fonts.constructors +local vf = { } +fonts.handlers.vf = vf -- general code @@ -60,9 +61,13 @@ local methods = definers.methods local variants = allocate() local combinations = { } local combiner = { } -local whatever = allocate() -- can be used to store data -local predefined = allocate() -- can be used to store data -local helpers = allocate() -- can be used to store data +local whatever = allocate() +local helpers = allocate() +local predefined = allocate { + dummy = { "comment" }, + push = { "push" }, + pop = { "pop" }, +} methods.variants = variants -- todo .. wrong namespace vf.combinations = combinations @@ -71,11 +76,7 @@ vf.whatever = whatever vf.helpers = helpers vf.predefined = predefined -setmetatable(whatever, { __index = function(t,k) local v = { } t[k] = v return v end }) - -predefined.dummy = { "comment" } -predefined.push = { "push" } -predefined.pop = { "pop" } +setmetatableindex(whatever, function(t,k) local v = { } t[k] = v return v end) local function checkparameters(g,f) if f and g and not g.parameters and #g.fonts > 0 then diff --git a/tex/context/base/grph-fil.lua b/tex/context/base/grph-fil.lua index e036cf9a1..0856f5b08 100644 --- a/tex/context/base/grph-fil.lua +++ b/tex/context/base/grph-fil.lua @@ -12,9 +12,10 @@ local trace_run = false trackers.register("graphic.runfile",function(v) trace_r local report_run = logs.reporter("graphics","run") -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate -local collected, tobesaved = allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() local jobfiles = { collected = collected, @@ -24,8 +25,8 @@ local jobfiles = { job.files = jobfiles local function initializer() - tobesaved = mark(jobfiles.tobesaved) - collected = mark(jobfiles.collected) + tobesaved = jobfiles.tobesaved + collected = jobfiles.collected end job.register('job.files.collected', tobesaved, initializer) diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua index bb29e6142..48cc2e4b0 100644 --- a/tex/context/base/grph-inc.lua +++ b/tex/context/base/grph-inc.lua @@ -44,20 +44,23 @@ local texbox = tex.box local contains = table.contains local concat, insert, remove = table.concat, table.insert, table.remove local todimen = string.todimen -local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash -local allocate = utilities.storage.allocate -local variables = interfaces.variables -local codeinjections = backends.codeinjections -local nodeinjections = backends.nodeinjections +local settings_to_array = utilities.parsers.settings_to_array +local settings_to_hash = utilities.parsers.settings_to_hash +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -local trace_figures = false trackers.register("graphics.locating", function(v) trace_figures = v end) -local trace_bases = false trackers.register("graphics.bases", function(v) trace_bases = v end) -local trace_programs = false trackers.register("graphics.programs", function(v) trace_programs = v end) -local trace_conversion = false trackers.register("graphics.conversion", function(v) trace_conversion = v end) -local trace_inclusion = false trackers.register("graphics.inclusion", function(v) trace_inclusion = v end) +local variables = interfaces.variables +local codeinjections = backends.codeinjections +local nodeinjections = backends.nodeinjections -local report_inclusion = logs.reporter("graphics","inclusion") +local trace_figures = false trackers.register("graphics.locating", function(v) trace_figures = v end) +local trace_bases = false trackers.register("graphics.bases", function(v) trace_bases = v end) +local trace_programs = false trackers.register("graphics.programs", function(v) trace_programs = v end) +local trace_conversion = false trackers.register("graphics.conversion", function(v) trace_conversion = v end) +local trace_inclusion = false trackers.register("graphics.inclusion", function(v) trace_inclusion = v end) + +local report_inclusion = logs.reporter("graphics","inclusion") local context, img = context, img @@ -290,8 +293,8 @@ local function new() -- we could use metatables status -> used -> request but it fullname = false, format = false, } - -- setmetatable(status, { __index = used }) - -- setmetatable(used, { __index = request }) + -- setmetatableindex(status, used) + -- setmetatableindex(used, request) return { request = request, used = used, diff --git a/tex/context/base/l-dimen.lua b/tex/context/base/l-dimen.lua deleted file mode 100644 index f8a999cc9..000000000 --- a/tex/context/base/l-dimen.lua +++ /dev/null @@ -1,434 +0,0 @@ -if not modules then modules = { } end modules ['l-dimen'] = { - version = 1.001, - comment = "support for dimensions", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ldx-- -

Internally work with scaled point, which are -represented by integers. However, in practice, at east at the - end we work with more generic units like points (pt). Going -from scaled points (numbers) to one of those units can be -done by using the conversion factors collected in the following -table.

---ldx]]-- - -local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable -local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match - -number = number or { } -local number = number - -number.tonumberf = function(n) return match(format("%.20f",n),"(.-0?)0*$") end -- one zero too much but alas -number.tonumberg = function(n) return format("%.20g",n) end - -local dimenfactors = { - ["pt"] = 1/65536, - ["in"] = ( 100/ 7227)/65536, - ["cm"] = ( 254/ 7227)/65536, - ["mm"] = ( 2540/ 7227)/65536, - ["sp"] = 1, -- 65536 sp in 1pt - ["bp"] = ( 7200/ 7227)/65536, - ["pc"] = ( 1/ 12)/65536, - ["dd"] = ( 1157/ 1238)/65536, - ["cc"] = ( 1157/14856)/65536, - ["nd"] = (20320/21681)/65536, - ["nc"] = ( 5080/65043)/65536 -} - ---~ print(table.serialize(dimenfactors)) ---~ ---~ %.99g: ---~ ---~ t={ ---~ ["bp"]=1.5201782378580324e-005, ---~ ["cc"]=1.1883696112892098e-006, ---~ ["cm"]=5.3628510057769479e-007, ---~ ["dd"]=1.4260435335470516e-005, ---~ ["em"]=0.000152587890625, ---~ ["ex"]=6.103515625e-005, ---~ ["in"]=2.1113586636917117e-007, ---~ ["mm"]=5.3628510057769473e-008, ---~ ["nc"]=1.1917446679504327e-006, ---~ ["nd"]=1.4300936015405194e-005, ---~ ["pc"]=1.2715657552083333e-006, ---~ ["pt"]=1.52587890625e-005, ---~ ["sp"]=1, ---~ } ---~ ---~ patched %s and tonumber ---~ ---~ t={ ---~ ["bp"]=0.00001520178238, ---~ ["cc"]=0.00000118836961, ---~ ["cm"]=0.0000005362851, ---~ ["dd"]=0.00001426043534, ---~ ["em"]=0.00015258789063, ---~ ["ex"]=0.00006103515625, ---~ ["in"]=0.00000021113587, ---~ ["mm"]=0.00000005362851, ---~ ["nc"]=0.00000119174467, ---~ ["nd"]=0.00001430093602, ---~ ["pc"]=0.00000127156576, ---~ ["pt"]=0.00001525878906, ---~ ["sp"]=1, ---~ } - ---[[ldx-- -

A conversion function that takes a number, unit (string) and optional -format (string) is implemented using this table.

---ldx]]-- - -local function numbertodimen(n,unit,fmt) - if type(n) == 'string' then - return n - else - unit = unit or 'pt' - return format(fmt or "%s%s",n*dimenfactors[unit],unit) - -- if fmt then - -- return format(fmt,n*dimenfactors[unit],unit) - -- else - -- return match(format("%.20f",n*dimenfactors[unit]),"(.-0?)0*$") .. unit - -- end - end -end - ---[[ldx-- -

We collect a bunch of converters in the number namespace.

---ldx]]-- - -number.maxdimen = 1073741823 -number.todimen = numbertodimen -number.dimenfactors = dimenfactors - -function number.topoints (n) return numbertodimen(n,"pt") end -function number.toinches (n) return numbertodimen(n,"in") end -function number.tocentimeters (n) return numbertodimen(n,"cm") end -function number.tomillimeters (n) return numbertodimen(n,"mm") end -function number.toscaledpoints(n) return numbertodimen(n,"sp") end -function number.toscaledpoints(n) return n .. "sp" end -function number.tobasepoints (n) return numbertodimen(n,"bp") end -function number.topicas (n) return numbertodimen(n "pc") end -function number.todidots (n) return numbertodimen(n,"dd") end -function number.tociceros (n) return numbertodimen(n,"cc") end -function number.tonewdidots (n) return numbertodimen(n,"nd") end -function number.tonewciceros (n) return numbertodimen(n,"nc") end - ---[[ldx-- -

More interesting it to implement a (sort of) dimen datatype, one -that permits calculations too. First we define a function that -converts a string to scaledpoints. We use . We capture -a number and optionally a unit. When no unit is given a constant -capture takes place.

---ldx]]-- - -local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0") -local unit = R("az")^1 - -local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new - -lpeg.patterns.dimenpair = dimenpair - ---[[ldx-- -

We use a metatable to intercept errors. When no key is found in -the table with factors, the metatable will be consulted for an -alternative index function.

---ldx]]-- - -local mt = { } setmetatable(dimenfactors,mt) - -mt.__index = function(t,s) - -- error("wrong dimension: " .. (s or "?")) -- better a message - return false -end - - ---[[ldx-- -

We redefine the following function later on, so we comment it -here (which saves us bytecodes.

---ldx]]-- - --- function string.todimen(str) --- if type(str) == "number" then --- return str --- else --- local value, unit = lpegmatch(dimenpair,str) --- return value/unit --- end --- end --- --- local stringtodimen = string.todimen - -local stringtodimen -- assigned later (commenting saves bytecode) - -local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0 -local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") + - P("pc") + P("dd") + P("cc") + P("nd") + P("nc") - -local validdimen = amount * unit - -lpeg.patterns.validdimen = validdimen - ---[[ldx-- -

This converter accepts calls like:

- - -string.todimen("10") -string.todimen(".10") -string.todimen("10.0") -string.todimen("10.0pt") -string.todimen("10pt") -string.todimen("10.0pt") - - -

With this in place, we can now implement a proper datatype for dimensions, one -that permits us to do this:

- - -s = dimen "10pt" + dimen "20pt" + dimen "200pt" - - dimen "100sp" / 10 + "20pt" + "0pt" - - -

We create a local metatable for this new type:

---ldx]]-- - -local dimensions = { } - ---[[ldx-- -

The main (and globally) visible representation of a dimen is defined next: it is -a one-element table. The unit that is returned from the match is normally a number -(one of the previously defined factors) but we also accept functions. Later we will -see why. This function is redefined later.

---ldx]]-- - --- function dimen(a) --- if a then --- local ta= type(a) --- if ta == "string" then --- local value, unit = lpegmatch(pattern,a) --- if type(unit) == "function" then --- k = value/unit() --- else --- k = value/unit --- end --- a = k --- elseif ta == "table" then --- a = a[1] --- end --- return setmetatable({ a }, dimensions) --- else --- return setmetatable({ 0 }, dimensions) --- end --- end - ---[[ldx-- -

This function return a small hash with a metatable attached. It is -through this metatable that we can do the calculations. We could have -shared some of the code but for reasons of speed we don't.

---ldx]]-- - -function dimensions.__add(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a + b }, dimensions) -end - -function dimensions.__sub(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a - b }, dimensions) -end - -function dimensions.__mul(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a * b }, dimensions) -end - -function dimensions.__div(a, b) - local ta, tb = type(a), type(b) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end - return setmetatable({ a / b }, dimensions) -end - -function dimensions.__unm(a) - local ta = type(a) - if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end - return setmetatable({ - a }, dimensions) -end - ---[[ldx-- -

It makes no sense to implement the power and modulo function but -the next two do make sense because they permits is code like:

- - -local a, b = dimen "10pt", dimen "11pt" -... -if a > b then - ... -end - ---ldx]]-- - --- makes no sense: dimensions.__pow and dimensions.__mod - -function dimensions.__lt(a, b) - return a[1] < b[1] -end - -function dimensions.__eq(a, b) - return a[1] == b[1] -end - ---[[ldx-- -

We also need to provide a function for conversion to string (so that -we can print dimensions). We print them as points, just like .

---ldx]]-- - -function dimensions.__tostring(a) - return a[1]/65536 .. "pt" -- instead of todimen(a[1]) -end - ---[[ldx-- -

Since it does not take much code, we also provide a way to access -a few accessors

- - -print(dimen().pt) -print(dimen().sp) - ---ldx]]-- - -function dimensions.__index(tab,key) - local d = dimenfactors[key] - if not d then - error("illegal property of dimen: " .. key) - d = 1 - end - return 1/d -end - ---[[ldx-- -

In the converter from string to dimension we support functions as -factors. This is because in we have a few more units: -ex and em. These are not constant factors but -depend on the current font. They are not defined by default, but need -an explicit function call. This is because at the moment that this code -is loaded, the relevant tables that hold the functions needed may not -yet be available.

---ldx]]-- - - dimenfactors["ex"] = 4 * 1/65536 -- 4pt - dimenfactors["em"] = 10 * 1/65536 -- 10pt --- dimenfactors["%"] = 4 * 1/65536 -- 400pt/100 - ---[[ldx-- -

The previous code is rather efficient (also thanks to ) but we -can speed it up by caching converted dimensions. On my machine (2008) the following -loop takes about 25.5 seconds.

- - -for i=1,1000000 do - local s = dimen "10pt" + dimen "20pt" + dimen "200pt" - - dimen "100sp" / 10 + "20pt" + "0pt" -end - - -

When we cache converted strings this becomes 16.3 seconds. In order not -to waste too much memory on it, we tag the values of the cache as being -week which mean that the garbage collector will collect them in a next -sweep. This means that in most cases the speed up is mostly affecting the -current couple of calculations and as such the speed penalty is small.

- -

We redefine two previous defined functions that can benefit from -this:

---ldx]]-- - -local known = { } setmetatable(known, { __mode = "v" }) - -function dimen(a) - if a then - local ta= type(a) - if ta == "string" then - local k = known[a] - if k then - a = k - else - local value, unit = lpegmatch(dimenpair,a) - if type(unit) == "function" then - k = value/unit() - else - k = value/unit - end - known[a] = k - a = k - end - elseif ta == "table" then - a = a[1] - end - return setmetatable({ a }, dimensions) - else - return setmetatable({ 0 }, dimensions) - end -end - -function string.todimen(str) -- maybe use tex.sp when available - if type(str) == "number" then - return str - else - local k = known[str] - if not k then - local value, unit = lpegmatch(dimenpair,str) - if value and unit then - k = value/unit -- to be considered: round - else - k = 0 - end - -- print(str,value,unit) - known[str] = k - end - return k - end -end - ---~ local known = { } - ---~ function string.todimen(str) -- maybe use tex.sp ---~ local k = known[str] ---~ if not k then ---~ k = tex.sp(str) ---~ known[str] = k ---~ end ---~ return k ---~ end - -stringtodimen = string.todimen -- local variable defined earlier - -function number.toscaled(d) - return format("%0.5f",d/2^16) -end - ---[[ldx-- -

In a similar fashion we can define a glue datatype. In that case we -probably use a hash instead of a one-element table.

---ldx]]-- - ---[[ldx-- -

Goodie:s

---ldx]]-- - -function number.percent(n) -- will be cleaned up once luatex 0.30 is out - local hsize = tex.hsize - if type(hsize) == "string" then - hsize = stringtodimen(hsize) - end - return (n/100) * hsize -end - -number["%"] = number.percent diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index fe69c9181..c3199f022 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -253,8 +253,6 @@ function file.collapsepath(str,anchor) end end -file.collapse_path = file.collapsepath - --~ local function test(str) --~ print(string.format("%-20s %-15s %-15s",str,file.collapsepath(str),file.collapsepath(str,true))) --~ end diff --git a/tex/context/base/l-md5.lua b/tex/context/base/l-md5.lua index f9197c56e..1d471c966 100644 --- a/tex/context/base/l-md5.lua +++ b/tex/context/base/l-md5.lua @@ -31,14 +31,12 @@ if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end --~ function md5.dec(str) return (gsub(md5.sum(str),".",remap)) end --~ end -file.needs_updating_threshold = 1 - -function file.needs_updating(oldname,newname) -- size modification access change +function file.needs_updating(oldname,newname,threshold) -- size modification access change local oldtime = lfs.attributes(oldname, modification) local newtime = lfs.attributes(newname, modification) if newtime >= oldtime then return false - elseif oldtime - newtime < file.needs_updating_threshold then + elseif oldtime - newtime < (threshold or 1) then return false else return true diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 727d80df7..9de3c5502 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -306,10 +306,6 @@ function table.fromhash(t) return hsh end -table.serialize_functions = true -table.serialize_compact = true -table.serialize_inline = true - local noquotes, hexify, handle, reduce, compact, inline, functions local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key @@ -595,15 +591,36 @@ end -- replacing handle by a direct t[#t+1] = ... (plus test) is not much -- faster (0.03 on 1.00 for zapfino.tma) -local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) - noquotes = _noquotes - hexify = _hexify - handle = _handle or print - reduce = _reduce or false - compact = table.serialize_compact - inline = compact and table.serialize_inline - functions = table.serialize_functions +local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) -- I might drop the _'s some day. local tname = type(name) + if tname == "table" then + noquotes = name.noquotes + hexify = name.hexify + handle = name.handle or print + reduce = name.reduce or false + functions = name.functions + compact = name.compact + inline = name.inline and compact + name = name.name + tname = type(name) + if functions == nil then + functions = true + end + if compact == nil then + compact = true + end + if inline == nil then + inline = compact + end + else + noquotes = _noquotes + hexify = _hexify + handle = _handle or print + reduce = _reduce or false + compact = true + inline = true + functions = true + end if tname == "string" then if name == "return" then handle("return {") @@ -670,12 +687,11 @@ end -- -- so this is on the todo list -table.tofile_maxtab = 2*1024 +local maxtab = 2*1024 function table.tofile(filename,root,name,reduce,noquotes,hexify) local f = io.open(filename,'w') if f then - local maxtab = table.tofile_maxtab if maxtab > 1 then local t, n = { }, 0 local function flush(s) @@ -893,8 +909,12 @@ function table.sequenced(t,sep,simple) -- hash only return concat(s, sep or " | ") end -function table.print(...) - table.tohandle(print,...) +function table.print(t,...) + if type(t) ~= "table" then + print(tostring(t)) + else + table.tohandle(print,t,...) + end end -- -- -- obsolete but we keep them for a while and might comment them later -- -- -- diff --git a/tex/context/base/lang-def.lua b/tex/context/base/lang-def.lua index 4fdcdf8a7..78c8eecbd 100644 --- a/tex/context/base/lang-def.lua +++ b/tex/context/base/lang-def.lua @@ -8,11 +8,12 @@ if not modules then modules = { } end modules ['lang-ini'] = { local lower = string.lower -languages = languages or { } -local languages = languages +languages = languages or { } +local languages = languages +local data = languages.data -languages.data = languages.data or utilities.storage.allocate { } -local data = languages.data +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -- The specifications are based on an analysis done by Arthur. The -- names of tags were changed by Hans. The data is not yet used but @@ -62,7 +63,7 @@ local data = languages.data -- -- todo: add default features -local specifications = { +local specifications = allocate { { ["description"] = "Basque", ["script"] = "latn", @@ -360,16 +361,13 @@ local specifications = { data.specifications = specifications -storage.mark(specifications) - local variants = { } data.variants = variants local opentypes = { } data.opentypes = opentypes local contexts = { } data.contexts = contexts local records = { } data.records = records - for k=1,#specifications do - local v = languagedata[k] + local v = specifications[k] if v.variant then variants[v.variant] = v end @@ -388,31 +386,31 @@ for k=1,#specifications do end end -setmetatable(variants, { __index = function(t,k) +setmetatableindex(variants, function(t,k) str = lower(str) local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant.en).language t[k] = v return v -end } ) +end) -setmetatable(opentypes, { __index = function(t,k) +setmetatableindex(opentypes, function(t,k) str = lower(str) local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant.en).opentype t[k] = v return v -end +end) -setmetatable(contexts, { __index = function(t,k) +setmetatableindex(contexts, function(t,k) str = lower(str) local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant[languages.default]).context v = (type(v) == "table" and v[1]) or v t[k] = v return v -end +end) -setmetatable(records, { __index = function(t,k) -- how useful is this one? +setmetatableindex(records, function(t,k) -- how useful is this one? str = lower(str) local v = variants[str] or opentypes[str] or contexts[str] or variants.en t[k] = v return v -end +end) diff --git a/tex/context/base/lang-def.mkiv b/tex/context/base/lang-def.mkiv index 871e4f528..401065adb 100644 --- a/tex/context/base/lang-def.mkiv +++ b/tex/context/base/lang-def.mkiv @@ -190,34 +190,6 @@ \installlanguage [swedish] [\s!sv] \installlanguage [afrikaans] [\s!af] -%D Next we implement couple of ordinal mumber converters: - -\def\enordinaldaynumber#1% - {#1\ifnum\lasttwodigits{#1}=11 - \highordinalstr{th}% - \else\ifnum\lasttwodigits{#1}=12 - \highordinalstr{th}% - \else\ifnum\lasttwodigits{#1}=13 - \highordinalstr{th}% - \else\ifcase\lastdigit{#1}% - \highordinalstr{th}% - \or % 1 - \highordinalstr{st}% - \or % 2 - \highordinalstr{nd}% - \or % 3 - \highordinalstr{rd}% - \else - \highordinalstr{th}% - \fi\fi\fi\fi} - -% \def\enordinaldaynumber#1% -% {#1\ordinalstr{\ifnum\lasttwodigits{#1}=11 th\else\ifcase\lastdigit{#1} -% th\or st\or nd\or rd\else th\fi\fi}} - -\def\nlordinaldaynumber#1% - {#1\highordinalstr{e}} - % Slavic Languages: Belarussian, Russian, Ukrainian, Bulgarian, % Macedonian, Serbian, Croatian, Slovenian, Czech, Kushubian, % Lusatian/Sorbian/Wendish, Polish, Slovak, Albanian, Illyrian, @@ -699,13 +671,6 @@ \installlanguage [portuguese] [\s!pt] \installlanguage [romanian] [\s!ro] -%D Ordinal converters: - -\def\frordinaldaynumber#1% date is masculine - {\number#1\ifcase#1\or - \highordinalstr{er}% - \fi} - \defineconversion [\s!fr] [\v!day+] [\frordinaldaynumber] % Vietnamese Language diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua index 0a2d76508..305b429e1 100644 --- a/tex/context/base/lang-ini.lua +++ b/tex/context/base/lang-ini.lua @@ -23,16 +23,19 @@ local format, gsub = string.format, string.gsub local concat = table.concat local lpegmatch = lpeg.match local texwrite = tex.write + local settings_to_array = utilities.parsers.settings_to_array local trace_patterns = false trackers.register("languages.patterns", function(v) trace_patterns = v end) local report_initialization = logs.reporter("languages","initialization") -local prehyphenchar, posthyphenchar = lang.prehyphenchar, lang.posthyphenchar -- global per language -local lefthyphenmin, righthyphenmin = lang.lefthyphenmin, lang.righthyphenmin +local prehyphenchar = lang.prehyphenchar -- global per language +local posthyphenchar = lang.posthyphenchar -- global per language +local lefthyphenmin = lang.lefthyphenmin +local righthyphenmin = lang.righthyphenmin -lang.exceptions = lang.hyphenation +lang.exceptions = lang.hyphenation languages = languages or {} local languages = languages @@ -48,9 +51,13 @@ local associated = languages.associated languages.numbers = languages.numbers or { } local numbers = languages.numbers +languages.data = languages.data or { } +local data = languages.data + storage.register("languages/numbers", numbers, "languages.numbers") storage.register("languages/registered",registered,"languages.registered") storage.register("languages/associated",associated,"languages.associated") +storage.register("languages/data", data, "languages.data") local nofloaded = 0 diff --git a/tex/context/base/lang-lab.lua b/tex/context/base/lang-lab.lua index 58fff29cd..1947616a9 100644 --- a/tex/context/base/lang-lab.lua +++ b/tex/context/base/lang-lab.lua @@ -65,7 +65,6 @@ local texsprint = tex.sprint local prtcatcodes = tex.prtcatcodes languages.labels = languages.labels or { } -languages.data = languages.data or { } local trace_labels = false trackers.register("languages.labels", function(v) trace_labels = v end) diff --git a/tex/context/base/lang-url.lua b/tex/context/base/lang-url.lua index ecde7f3ae..e401e4148 100644 --- a/tex/context/base/lang-url.lua +++ b/tex/context/base/lang-url.lua @@ -68,7 +68,7 @@ hyphenatedurl.discretionary = nil local chars = hyphenatedurl.characters -function hyphenatedurl.action(str, left, right, disc) +local function action(hyphenatedurl, str, left, right, disc) local n = 0 local b = math.max( left or hyphenatedurl.lefthyphenmin, 2) local e = math.min(#str-(right or hyphenatedurl.righthyphenmin)+2,#str) @@ -90,6 +90,10 @@ function hyphenatedurl.action(str, left, right, disc) end end +-- hyphenatedurl.action = function(_,...) action(...) end -- sort of obsolete + +table.setmetatablecall(hyphenatedurl,action) + -- todo, no interface in mkiv yet function hyphenatedurl.setcharacters(str,value) -- 1, 2 == before, after diff --git a/tex/context/base/lang-url.mkiv b/tex/context/base/lang-url.mkiv index a3cf466de..cba013324 100644 --- a/tex/context/base/lang-url.mkiv +++ b/tex/context/base/lang-url.mkiv @@ -81,7 +81,7 @@ \let\b\dohyphenatedurlbefore \let\a\dohyphenatedurlafter \let\d\dohyphenatedurldisc - \normalexpanded{\noexpand\ctxcommand{hyphenatedurl.action( + \normalexpanded{\noexpand\ctxcommand{hyphenatedurl( \!!bs\noexpand\detokenize{#1}\!!es, \number\hyphenatedurllefthyphenmin, \number\hyphenatedurlrighthyphenmin, diff --git a/tex/context/base/luat-bas.mkiv b/tex/context/base/luat-bas.mkiv index d9c857211..d5075b4cb 100644 --- a/tex/context/base/luat-bas.mkiv +++ b/tex/context/base/luat-bas.mkiv @@ -27,10 +27,8 @@ \registerctxluafile{l-dir} {1.001} \registerctxluafile{l-unicode}{1.001} %registerctxluafile{l-utils} {1.001} -\registerctxluafile{l-dimen} {1.001} \registerctxluafile{l-url} {1.001} \registerctxluafile{l-set} {1.001} -\registerctxluafile{l-dimen} {1.001} % \registerctxluafile{socket.lua}{} % \registerctxluafile{ltn12.lua} {} diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv index 29de9a0ea..83b96639b 100644 --- a/tex/context/base/luat-lib.mkiv +++ b/tex/context/base/luat-lib.mkiv @@ -16,13 +16,14 @@ \registerctxluafile{util-str}{1.001} \registerctxluafile{util-tab}{1.001} \registerctxluafile{util-pck}{1.001} +\registerctxluafile{util-sto}{1.001} % could also be done in trac-deb.mkiv \registerctxluafile{util-seq}{1.001} %registerctxluafile{util-mrg}{1.001} % not needed in context itself, only mtxrun \registerctxluafile{util-lua}{1.001} \registerctxluafile{util-prs}{1.001} \registerctxluafile{util-fmt}{1.001} \registerctxluafile{util-deb}{1.001} % could also be done in trac-deb.mkiv -\registerctxluafile{util-sto}{1.001} % could also be done in trac-deb.mkiv +\registerctxluafile{util-dim}{1.001} \registerctxluafile{trac-inf}{1.001} \registerctxluafile{trac-set}{1.001} diff --git a/tex/context/base/luat-mac.lua b/tex/context/base/luat-mac.lua index 775e8a3b5..0dc6593c6 100644 --- a/tex/context/base/luat-mac.lua +++ b/tex/context/base/luat-mac.lua @@ -258,4 +258,14 @@ end --~ % \hbox attr \referenceattribute \lastreferenceattribute {\localframed[#namespace:#current]{#text}}} --~ \hbox attr \referenceattribute \lastreferenceattribute {\directlocalframed[#namespace:#current]{#text}}} --~ ]])) - +--~ +--~ print(macros.preprocessed([[ +--~ \def\definefoo[#name]% +--~ {\setvalue{start#name}{\dostartfoo{#name}}} +--~ \def\dostartfoo#name% +--~ {\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname{#name : #content}% +--~ \next} +--~ \def\dostartfoo#name% +--~ {\normalexpanded{\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname}{#name : #content}% +--~ \next} +--~ ]])) diff --git a/tex/context/base/lxml-aux.lua b/tex/context/base/lxml-aux.lua index a8223c4b4..4798fe06a 100644 --- a/tex/context/base/lxml-aux.lua +++ b/tex/context/base/lxml-aux.lua @@ -19,8 +19,8 @@ local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name local xmlinheritedconvert = xml.inheritedconvert local xmlapplylpath = xml.applylpath -local type = type -local insert, remove = table.insert, table.remove +local type, setmetatable, getmetatable = type, setmetatable, getmetatable +local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy local gmatch, gsub = string.gmatch, string.gsub local function report(what,pattern,c,e) @@ -234,6 +234,41 @@ function xml.replace(root,pattern,whatever) end end +local function wrap(e,wrapper) + local t = { + rn = e.rn, + tg = e.tg, + ns = e.ns, + at = e.at, + dt = e.dt, + __p__ = e, + } + setmetatable(t,getmetatable(e)) + e.rn = wrapper.rn or e.rn or "" + e.tg = wrapper.tg or e.tg or "" + e.ns = wrapper.ns or e.ns or "" + e.at = fastcopy(wrapper.at) + e.dt = { t } +end + +function xml.wrap(root,pattern,whatever) + if whatever then + local wrapper = xmltoelement(whatever,root) + local collected = xmlapplylpath(root,pattern) + if collected then + for c=1,#collected do + local e = collected[c] + if trace_manipulations then + report('wrapping',pattern,c,e) + end + wrap(e,wrapper) + end + end + else + wrap(root,xmltoelement(pattern)) + end +end + local function inject_element(root,pattern,whatever,prepend) local element = root and xmltoelement(whatever,root) local collected = element and xmlapplylpath(root,pattern) @@ -304,7 +339,7 @@ local function include(xmldata,pattern,attribute,recursive,loaddata) local ekat = ek.at local epdt = ek.__p__.dt if not attribute or attribute == "" then - name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- ckeck, probably always tab or str + name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str end if not name then for a in gmatch(attribute or "href","([^|]+)") do diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua index f25d13eed..3384f80ee 100644 --- a/tex/context/base/lxml-lpt.lua +++ b/tex/context/base/lxml-lpt.lua @@ -14,6 +14,8 @@ local type, next, tonumber, tostring, setmetatable, loadstring = type, next, ton local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local setmetatableindex = table.setmetatableindex + -- beware, this is not xpath ... e.g. position is different (currently) and -- we have reverse-sibling as reversed preceding sibling @@ -86,8 +88,8 @@ local function fallback (t, name) return fn end -setmetatable(finalizers.xml, { __index = fallback }) -setmetatable(finalizers.tex, { __index = fallback }) +setmetatableindex(finalizers.xml, fallback) +setmetatableindex(finalizers.tex, fallback) xml.defaultprotocol = "xml" @@ -821,14 +823,13 @@ xml.nodesettostring = nodesettostring local lpath -- we have a harmless kind of circular reference +local lshowoptions = { name = false, functions = false } + local function lshow(parsed) if type(parsed) == "string" then parsed = lpath(parsed) end - local s = table.serialize_functions -- ugly - table.serialize_functions = false -- ugly - report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,false)) - table.serialize_functions = s -- ugly + report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,lshowoptions)) end xml.lshow = lshow diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua index 278e3b9cb..e5ad30be0 100644 --- a/tex/context/base/math-tag.lua +++ b/tex/context/base/math-tag.lua @@ -8,9 +8,9 @@ if not modules then modules = { } end modules ['math-tag'] = { local attributes, nodes = attributes, nodes -local has_attribute = nodes.has_attribute -local set_attribute = nodes.set_attribute -local set_attributes = nodes.set_attributes +local get_attribute = nodes.getattribute +local set_attribute = nodes.setattribute +local set_attributes = nodes.setattributes local traverse_nodes = node.traverse local nodecodes = nodes.nodecodes @@ -101,7 +101,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) elseif id == math_box_code or id == hlist_code or id == vlist_code then -- keep an eye on math_box_code and see what ends up in there - local attr = has_attribute(start,a_tagged) + local attr = get_attribute(start,a_tagged) local text = start_tagged("mtext") set_attribute(start,a_tagged,text) local list = start.list @@ -124,7 +124,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer if id == hlist_code or id == vlist_code then runner(n.list) elseif id == glyph_code then - local aa = has_attribute(n,a_tagged) -- only glyph needed + local aa = get_attribute(n,a_tagged) -- only glyph needed if aa then local ac = cache[aa] if not ac then diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua index 190a89c71..afb4c1be2 100644 --- a/tex/context/base/math-vfu.lua +++ b/tex/context/base/math-vfu.lua @@ -13,23 +13,24 @@ if not modules then modules = { } end modules ['math-vfu'] = { local type, next = type, next local max = math.max +local fonts, nodes, mathematics = fonts, nodes, mathematics + local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end) local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end) -local report_virtual = logs.reporter("fonts","virtual math") - -local fonts, nodes, mathematics = fonts, nodes, mathematics +local report_virtual = logs.reporter("fonts","virtual math") -local allocate = utilities.storage.allocate +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -local mathencodings = allocate() -fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vectors -local vfmath = allocate() -fonts.handlers.vf.math = vfmath +local mathencodings = allocate() +fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vectors +local vfmath = allocate() +fonts.handlers.vf.math = vfmath -vfmath.optional = false +vfmath.optional = false -local shared = { } +local shared = { } --~ local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 } @@ -346,7 +347,7 @@ local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \st local reported = { } local reverse = { } -- index -> unicode -setmetatable ( reverse, { __index = function(t,name) +setmetatableindex(reverse, function(t,name) if trace_virtual then report_virtual("initializing math vector '%s'",name) end @@ -356,7 +357,7 @@ setmetatable ( reverse, { __index = function(t,name) end reverse[name] = r return r -end } ) +end) function vfmath.define(specification,set,goodies) local name = specification.name -- symbolic name @@ -460,14 +461,14 @@ function vfmath.define(specification,set,goodies) end -- local description = { name = "" } - setmetatable(descriptions, { __index = function() return description end }) + setmetatableindex(descriptions,function() return description end) -- if parent.properties then - setmetatable(properties, { __index = parent.properties }) + setmetatableindex(properties,parent.properties) end -- if parent.goodies then - setmetatable(goodies, { __index = parent.goodies }) + setmetatableindex(goodies,parent.goodies) end -- properties.virtualized = true diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua index e1f85e804..bbdd0bbd5 100644 --- a/tex/context/base/mlib-pps.lua +++ b/tex/context/base/mlib-pps.lua @@ -15,43 +15,47 @@ if not modules then modules = { } end modules ['mlib-pps'] = { local format, gmatch, concat, round, match = string.format, string.gmatch, table.concat, math.round, string.match local tonumber, type = tonumber, type -local lpegmatch = lpeg.match -local texbox = tex.box -local copy_list, free_list = node.copy_list, node.flush_list - local Cs, Cf, C, Cg, Ct, P, S, V, Carg = lpeg.Cs, lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.V, lpeg.Carg +local lpegmatch = lpeg.match -local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming +local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context -local context = context +local texbox = tex.box +local copy_list = node.copy_list +local free_list = node.flush_list +local setmetatableindex = table.setmetatableindex +local sortedhash = table.sortedhash -local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end) +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming -local report_metapost = logs.reporter("metapost") -local report_textexts = logs.reporter("metapost","textexts") +local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end) -local colors = attributes.colors +local report_metapost = logs.reporter("metapost") +local report_textexts = logs.reporter("metapost","textexts") -local rgbtocmyk = colors.rgbtocmyk or function() return 0,0,0,1 end -local cmyktorgb = colors.cmyktorgb or function() return 0,0,0 end -local rgbtogray = colors.rgbtogray or function() return 0 end -local cmyktogray = colors.cmyktogray or function() return 0 end +local colors = attributes.colors -local mplib, metapost, lpdf = mplib, metapost, lpdf +local rgbtocmyk = colors.rgbtocmyk or function() return 0,0,0,1 end +local cmyktorgb = colors.cmyktorgb or function() return 0,0,0 end +local rgbtogray = colors.rgbtogray or function() return 0 end +local cmyktogray = colors.cmyktogray or function() return 0 end -metapost.makempy = metapost.makempy or { nofconverted = 0 } -local makempy = metapost.makempy +metapost.makempy = metapost.makempy or { nofconverted = 0 } +local makempy = metapost.makempy -local nooutercolor = "0 g 0 G" -local nooutertransparency = "/Tr0 gs" -- only when set -local outercolormode = 0 -local outercolor = nooutercolor -local outertransparency = nooutertransparency -local innercolor = nooutercolor -local innertransparency = nooutertransparency +local nooutercolor = "0 g 0 G" +local nooutertransparency = "/Tr0 gs" -- only when set +local outercolormode = 0 +local outercolor = nooutercolor +local outertransparency = nooutertransparency +local innercolor = nooutercolor +local innertransparency = nooutertransparency -local pdfcolor, pdftransparency = lpdf.color, lpdf.transparency -local registercolor, registerspotcolor = colors.register, colors.registerspotcolor +local pdfcolor = lpdf.color +local pdftransparency = lpdf.transparency +local registercolor = colors.register +local registerspotcolor = colors.registerspotcolor local transparencies = attributes.transparencies local registertransparency = transparencies.register @@ -352,11 +356,11 @@ function models.gray(cr) return checked_color_pair(format("%.3f g %.3f G",s,s)) end -setmetatable(models, { __index = function(t,k) +setmetatableindex(models, function(t,k) local v = models.gray t[k] = v return v -end }) +end) local function colorconverter(cs) return models[colors.model](cs) @@ -839,15 +843,15 @@ local value = Cs ( ( ) local function tr_process(object,prescript,before,after) + -- before can be shortcut to t + local tr_alternative = prescript.tr_alternative + if tr_alternative then + tr_alternative = tonumber(tr_alternative) + local tr_transparency = tonumber(prescript.tr_transparency) + before[#before+1], after[#after+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true)), "/Tr0 gs" -- outertransparency + end local cs = object.color if cs and #cs > 0 then - -- before can be shortcut to t - local tr_alternative = prescript.tr_alternative - if tr_alternative then - tr_alternative = tonumber(tr_alternative) - local tr_transparency = tonumber(prescript.tr_transparency) - before[#before+1], after[#after+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true)), "/Tr0 gs" -- outertransparency - end local sp_name = prescript.sp_name if sp_name then local sp_fractions = prescript.sp_fractions or 1 diff --git a/tex/context/base/mult-ini.lua b/tex/context/base/mult-ini.lua index fbb986017..4156e813d 100644 --- a/tex/context/base/mult-ini.lua +++ b/tex/context/base/mult-ini.lua @@ -10,16 +10,19 @@ local format, gmatch, gsub = string.format, string.gmatch, string.gsub local lpegmatch = lpeg.match local serialize = table.serialize -local texsprint = tex.sprint +local allocate = utilities.storage.allocate +local mark = utilities.storage.mark +local texsprint = tex.sprint +local setmetatableindex = table.setmetatableindex -local report_interface = logs.reporter("interface","initialization") +local report_interface = logs.reporter("interface","initialization") -interfaces = interfaces or { } -interfaces.constants = interfaces.constants or { } -interfaces.variables = interfaces.variables or { } -interfaces.elements = interfaces.elements or { } -interfaces.formats = interfaces.formats or { } -interfaces.translations = interfaces.translations or { } +interfaces = interfaces or { } +interfaces.constants = mark(interfaces.constants or { }) +interfaces.variables = mark(interfaces.variables or { }) +interfaces.elements = mark(interfaces.elements or { }) +interfaces.formats = mark(interfaces.formats or { }) +interfaces.translations = mark(interfaces.translations or { }) storage.register("interfaces/constants", interfaces.constants, "interfaces.constants") storage.register("interfaces/variables", interfaces.variables, "interfaces.variables") @@ -37,16 +40,19 @@ storage.shared.currentresponse = storage.shared.currentresponse or "en" local currentinterface = storage.shared.currentinterface local currentresponse = storage.shared.currentresponse -local complete = { } interfaces.complete = complete +local complete = allocate() +interfaces.complete = complete -setmetatable(complete, { __index = function(t,k) -- one access needed to get loaded +local function resolve(t,k) -- one access needed to get loaded report_interface("loading interface definitions from 'mult-def.lua'") complete = dofile(resolvers.findfile("mult-def.lua")) report_interface("loading interface messages from 'mult-mes.lua'") complete.messages = dofile(resolvers.findfile("mult-mes.lua")) interfaces.complete = complete return rawget(complete,k) -end } ) +end + +setmetatableindex(complete, resolve) local constants = interfaces.constants local variables = interfaces.variables @@ -55,15 +61,24 @@ local formats = interfaces.formats local translations = interfaces.translations local reporters = { } -- just an optimization -local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper +local function valueiskey(t,k) -- will be helper + t[k] = k + return k +end -setmetatable(variables, valueiskey) -setmetatable(constants, valueiskey) -setmetatable(elements, valueiskey) -setmetatable(formats, valueiskey) -setmetatable(translations, valueiskey) +setmetatableindex(variables, valueiskey) +setmetatableindex(constants, valueiskey) +setmetatableindex(elements, valueiskey) +setmetatableindex(formats, valueiskey) +setmetatableindex(translations, valueiskey) + +local function resolve(t,k) + local v = logs.reporter(k) + t[k] = v + return v +end -setmetatable(reporters, { __index = function(t,k) local v = logs.reporter(k) ; t[k] = v ; return v end }) +setmetatableindex(reporters, resolve) for category, _ in next, translations do -- We pre-create reporters for already defined messages diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua index 65a47939b..0b44f7724 100644 --- a/tex/context/base/node-aux.lua +++ b/tex/context/base/node-aux.lua @@ -39,7 +39,7 @@ local isnode = node.is_node local texbox = tex.box -function nodes.repack_hlist(list,...) +function nodes.repackhlist(list,...) --~ nodes.showsimplelist(list) local temp, b = hpack_nodes(list,...) list = temp.list @@ -80,22 +80,15 @@ local function unset_attributes(head,attr) end end -nodes.set_attribute = set_attribute -nodes.unset_attribute = unset_attribute -nodes.has_attribute = has_attribute -nodes.first_glyph = first_glyph +nodes.firstglyph = first_glyph +nodes.setattribute = set_attribute +nodes.getattribute = has_attribute +nodes.unsetattribute = unset_attribute +nodes.setattributes = set_attributes +nodes.setunsetattributes = set_unset_attributes +nodes.unsetattributes = unset_attributes -nodes.set_attributes = set_attributes -nodes.set_unset_attributes = set_unset_attributes -nodes.unset_attributes = unset_attributes - -nodes.setattribute = set_attribute -nodes.unsetattribute = unset_attribute -nodes.hasattribute = has_attribute - -nodes.setattributes = set_attributes -nodes.setunsetattributes = set_unset_attributes -nodes.unsetattributes = unset_attributes +nodes.has_attribute = has_attribute -- function nodes.is_skipable(a,id) -- skipable nodes at the margins during character protrusion -- return ( diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua index 77aa79396..7ceb96f80 100644 --- a/tex/context/base/node-fnt.lua +++ b/tex/context/base/node-fnt.lua @@ -11,26 +11,28 @@ if not context then os.exit() end -- generic function in node-dum local next, type = next, type local concat = table.concat -local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end) -local trace_fontrun = false trackers.register("nodes.fontrun", function(v) trace_fontrun = v end) +local nodes, node, fonts = nodes, node, fonts -local report_fonts = logs.reporter("fonts","processing") +local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end) +local trace_fontrun = false trackers.register("nodes.fontrun", function(v) trace_fontrun = v end) -local nodes, node, fonts = nodes, node, fonts +local report_fonts = logs.reporter("fonts","processing") + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers +local otf = fonts.handlers.otf -local otf = fonts.handlers.otf +local traverse_id = node.traverse_id +local has_attribute = node.has_attribute +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming +local nodecodes = nodes.nodecodes +local handlers = nodes.handlers -local traverse_id = node.traverse_id -local has_attribute = node.has_attribute -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming -local nodecodes = nodes.nodecodes -local handlers = nodes.handlers +local glyph_code = nodecodes.glyph -local glyph_code = nodecodes.glyph +local setmetatableindex = table.setmetatableindex -- some tests with using an array of dynamics[id] and processes[id] demonstrated -- that there was nothing to gain (unless we also optimize other parts) @@ -47,30 +49,26 @@ local run = 0 local setfontdynamics = { } local fontprocesses = { } -setmetatable(setfontdynamics, { __index = - function(t,font) - local tfmdata = fontdata[font] - local shared = tfmdata.shared - local v = shared and shared.dynamics and otf.setdynamics or false - t[font] = v - return v - end -}) - -setmetatable(fontprocesses, { __index = - function(t,font) - local tfmdata = fontdata[font] - local shared = tfmdata.shared -- we need to check shared, only when same features - local processes = shared and shared.processes - if processes and #processes > 0 then - t[font] = processes - return processes - else - t[font] = false - return false - end +setmetatableindex(setfontdynamics, function(t,font) + local tfmdata = fontdata[font] + local shared = tfmdata.shared + local v = shared and shared.dynamics and otf.setdynamics or false + t[font] = v + return v +end) + +setmetatableindex(fontprocesses, function(t,font) + local tfmdata = fontdata[font] + local shared = tfmdata.shared -- we need to check shared, only when same features + local processes = shared and shared.processes + if processes and #processes > 0 then + t[font] = processes + return processes + else + t[font] = false + return false end -}) +end) fonts.hashes.setdynamics = setfontdynamics fonts.hashes.processes = fontprocesses diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index fbf528629..19d602ed6 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -436,7 +436,7 @@ function nodes.references.handler(head) end end --- destinations (we can clean up once set!) +-- destinations (we can clean up once set, unless tagging!) local stack = { } local done = { } diff --git a/tex/context/base/node-spl.lua b/tex/context/base/node-spl.lua index ddb4a26a8..0fe3f759d 100644 --- a/tex/context/base/node-spl.lua +++ b/tex/context/base/node-spl.lua @@ -53,7 +53,7 @@ local protect_glyphs = nodes.handlers.protectglyphs or node.protect_glyphs local hpack_nodes = node.hpack local insert_node_before = node.insert_before local insert_node_after = node.insert_after -local repack_hlist = nodes.repack_hlist +local repack_hlist = nodes.repackhlist local setnodecolor = nodes.tracers.colors.set diff --git a/tex/context/base/pack-obj.lua b/tex/context/base/pack-obj.lua index 088ad6add..2dabfa784 100644 --- a/tex/context/base/pack-obj.lua +++ b/tex/context/base/pack-obj.lua @@ -12,9 +12,10 @@ reusable components.

--ldx]]-- local texsprint, texcount = tex.sprint, tex.count -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate -local collected, tobesaved = allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() local jobobjects = { collected = collected, @@ -24,8 +25,8 @@ local jobobjects = { job.objects = jobobjects local function initializer() - collected = mark(jobobjects.collected) - tobesaved = mark(jobobjects.tobesaved) + collected = jobobjects.collected + tobesaved = jobobjects.tobesaved end job.register('job.objects.collected', tobesaved, initializer, nil) diff --git a/tex/context/base/regi-ini.lua b/tex/context/base/regi-ini.lua index fbbfda75a..a440b6577 100644 --- a/tex/context/base/regi-ini.lua +++ b/tex/context/base/regi-ini.lua @@ -14,11 +14,12 @@ runtime.

local utfchar = utf.char local char, gsub, format = string.char, string.gsub, string.format -local next, setmetatable = next, setmetatable +local next = next local insert, remove = table.insert, table.remove -local sequencers = utilities.sequencers -local textlineactions = resolvers.openers.helpers.textlineactions +local sequencers = utilities.sequencers +local textlineactions = resolvers.openers.helpers.textlineactions +local setmetatableindex = table.setmetatableindex --[[ldx--

We will hook regime handling code into the input methods.

@@ -108,7 +109,7 @@ local function loadregime(mapping,regime) return vector end -setmetatable(mapping, { __index = loadregime }) +setmetatableindex(mapping, loadregime) local function translate(line,regime) if line and #line > 0 then diff --git a/tex/context/base/s-inf-03.mkiv b/tex/context/base/s-inf-03.mkiv new file mode 100644 index 000000000..bfcf5650b --- /dev/null +++ b/tex/context/base/s-inf-03.mkiv @@ -0,0 +1,352 @@ +% \nopdfcompression + +% \enablemode[ipad] + +\doifmodeelse {ipad} { + + \setuppapersize + [S6,landscape] + [S6,landscape] + + \definefont + [TitlePageFont] + [MonoBold at 20pt] + +} { + + \definefont + [TitlePageFont] + [MonoBold at 26pt] + +} + +\setuplayout + [header=0cm, + footer=1cm, + backspace=.5cm, + topspace=.5cm, + width=middle, + height=middle] + +\setuphead + [title] + [style=\ttc, + interaction=reference] + +\definehead + [xtitle] + [title] + +\setuphead + [xtitle] + [color=darkgreen] + +\setupbodyfont + [tt] + +\setupfootertexts + [\llap{\goto{\hbox to 5cm{\hss previous}}[previouspage]}% + \quad\pagenumber\quad + \rlap{\goto{\hbox to 5cm{next\hss}}[nextpage]}] + +\setupinteraction + [state=start, + style=, + color=, + title={ConTeXt MkIV}, + subtitle={Lua modules and functions}, + author={Hans Hagen - automatically generated}, + contrastcolor=] + +\setupinteractionscreen + [option=bookmark] + +\placebookmarks + [title,xtitle] + [force=yes] + +\definecolor[darkyellow][r=.5,g=.5,b=0] +\definecolor[darkgray] [s=.15] + +\nonknuthmode + +\starttext + +\startbuffer +\startluacode +local basiclua = libraries.basiclua +local basictex = libraries.basictex +local extratex = libraries.extratex +local extralua = libraries.extralua +local obsolete = libraries.obsolete + +local find = string.find +local color, goto = context.color, context.goto + +for k, v in table.sortedpairs(_G) do + if obsolete[k] or find(k,"_") or k == "arg" or k == "utf" then + -- + elseif basiclua[k] then + goto(function() color( { "darkred" }, k) end, { k } ) + elseif extralua[k] then + goto(function() color( { "darkgreen" }, k) end, { k } ) + elseif basictex[k] then + goto(function() color( { "darkblue" }, k) end, { k } ) + elseif extratex[k] then + goto(function() color( { "darkyellow" }, k) end, { k } ) + elseif type(v) == "table" then + goto(function() color( { "white" }, k) end, { k } ) + end + context(" ") +end +\stopluacode +\stopbuffer + +\setupbackgrounds + [page] + [background=color, + backgroundcolor=darkgray, + backgroundoffset=2mm] + +\setuplayout + [page] + +\startstandardmakeup + \vfill + \startnarrower[5mm] + \raggedcenter + \TitlePageFont \setupinterlinespace + \getbuffer + \par + \stopnarrower + \vfill + \vfill + \hskip10mm\scale[width=\dimexpr\paperwidth-20mm\relax]{\ttbf\white\ConTeXt\ MkIV} + \par + % \hskip10mm\scale[width=\dimexpr\paperwidth-20mm\relax]{\white \strut Lua infrastructure \emdash\ \currentdate} + \vfill +\stopstandardmakeup + +\setuplayout + +\setupbackgrounds + [page] + [background=] + +\startluacode +local builtin = libraries.builtin +local globals = libraries.globals +local basiclua = libraries.basiclua +local basictex = libraries.basictex +local extratex = libraries.extratex +local extralua = libraries.extralua +local obsolete = libraries.obsolete + +local sortedkeys = table.sortedkeys +local mark = storage.mark +local marked = storage.marked +local gsub = string.gsub +local sub = string.sub +local byte = string.byte +local upper = string.upper + +local skipglobal = table.tohash { + "_G", "context", "modules", "global", "arg", "utf", 1, + "_ptbs_", "_pcol_", "_plib_", "_clib_", "_tlib_", + "_M", "kpse", +} + +local skipkeys = table.tohash { + "_pcol_", "_plib_", "_clib_", "_tlib_", "_bpnf_", "_ptbs_", + "_cldf_", "_cldn_", + "_clmb_", "_clme_", "_clmm_", "_clmn_", "_clma_", "_clmh_", + "_G", "_M", "_VERSION", "_COPYRIGHT", "_DESCRIPTION", "_NAME", "_PACKAGE", "__unload", +} + +local sameglobal = { + ["global"] = "_G", + -- ["commands"] = "cs", -- already gone +} + +-- -- -- -- -- -- -- -- -- -- -- -- -- +-- this should be done internally +-- -- -- -- -- -- -- -- -- -- -- -- -- + +for k,v in next, modules do + mark(v) +end + +mark(document.arguments) +mark(environment.arguments) +mark(environment.engineflags) +mark(characters.data) + +-- -- -- -- -- -- -- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- -- -- -- -- -- + +local variant = 1 -- all parents +local variant = 2 -- parent name too +local variant = 3 -- no parents + +local function childtables(key,tab,handler,depth) + depth = depth or 1 + local keys = sortedkeys(tab) -- no sorted_pairs + for i=1,#keys do + local k = keys[i] +-- if k ~= "_G" and k ~= "_M" and type(k) == "string" then + if not skipkeys[k] and type(k) == "string" then + local v = tab[k] + local t = type(v) + local s = k + if variant ~= 3 then + s = key and (key .. "." .. s) or s + end + if t == "table" then + if marked(v) then + t = "data" + handler(s,t,depth) + else + handler(s,t,depth) + if variant == 3 then + childtables(false,v,handler,depth+1) + elseif variant == 2 then + childtables(k,v,handler,depth+1) + else + childtables(s,v,handler,depth+1) + end + end + else + handler(s,t,depth) + end + end + end +end + +local NC, NR = context.NC, context.NR +local overstrike, rlap, bf = context.overstrike, context.rlap, context.bf +local color, goto = context.color, context.goto + +local function cleanup(s) + return "\\char" ..byte(s) .. " " +end + +local function handler(k,t,depth) + k = gsub(k,"([~#$%%^&{}\\\|])",cleanup) +-- NC() rlap("\\quad\\tx " .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR() + NC() rlap("\\quad\\tx\\kern" .. (depth or 0).. "em" .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR() +end + +local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mark,obsolete) + -- todo: table as argument + local keys = sortedkeys(t) -- no sorted_pairs + if #keys > 0 then + local fulltitle = title + if subtitle and subtitle ~= "" then + fulltitle = fulltitle .. " (" .. subtitle .. ")" + end + if alias and alias ~= "" then + fulltitle = fulltitle .. " (alias: " .. alias .. ")" + end + if builtin then + context.startxtitle { reference = title, title = fulltitle, backreference = "global" } + else + context.starttitle { reference = title, title = fulltitle, backreference = "global" } + end + context.startcolumns { n = 2 } + context.starttabulate { "|||" } + local t_obsolete = t.obsolete + if type(t_obsolete) ~= "table" then + t_obsolete = nil + end + for i=1,#keys do + local k = keys[i] + local v = t[k] + if k ~= "obsolete" and not skipkeys[k] and (not obsolete or not obsolete[k]) then + local inlib = lib and lib[k] + local inglo = glo and glo[k] + if k then + local t = type(v) + local kstr, tstr = k, t + local obs = t_obsolete and t_obsolete[k] + if obs then + tstr = function() overstrike(t) end + kstr = function() overstrike(k) end + end + local marked = marked(v) + if marked then + tstr = "data table" + end + if t == "table" then + local m = getmetatable(v) + if m and m.__call then + tstr = "function" + end + end + if not mark then + -- + elseif inlib and tostring(inlib) ~= tostring(v) then + tstr = "overloaded ".. tstr + elseif inglo and tostring(inglo) ~= tostring(v) then + tstr = "overloaded ".. tstr + end + NC() bf() + if inlib then + if not mark and t == "table" then + goto(function() color( { libcolor }, kstr) end, { k } ) + else + color( { libcolor }, kstr) + end + elseif inglo then + if not mark and t == "table" then + goto(function() color( { glocolor }, kstr) end, { k } ) + else + color( { glocolor }, kstr) + end + else + if not mark and t == "table" then + goto(k, { kstr } ) + else + context(kstr) + end + end + NC() + if inlib then + color( { libcolor }, tstr) + elseif inglo then + color( { glocolor }, tstr) + else + context(tstr) + end + NC() NR() + if mark and t == "table" and title ~= "libraries" and title ~= "package" and not marked then + childtables(false,v,handler) -- (k,v,handler) + end + end + end + end + context.stoptabulate() + context.stopcolumns() + if builtin then + context.stopxtitle() + else + context.stoptitle() + end + end +end + +show("global","",sameglobal.global,false,_G,builtin,"darkgreen",globals,"darkblue",false,obsolete) + +for k, v in table.sortedpairs(_G) do + if not skipglobal[k] and not obsolete[k] and type(v) == "table" and not marked(v) then + if basiclua[k] then show(k,"basic lua",sameglobal[k],basiclua[k],v,builtin[k],"darkred", false,false,true) + elseif extralua[k] then show(k,"extra lua",sameglobal[k],extralua[k],v,builtin[k],"darkred", false,false,true) + elseif basictex[k] then show(k,"basic tex",sameglobal[k],basictex[k],v,builtin[k],"darkred", false,false,true) + elseif extratex[k] then show(k,"extra tex",sameglobal[k],extratex[k],v,builtin[k],"darkred", false,false,true) + else show(k,"context", sameglobal[k],false, v,builtin[k],"darkyellow",false,false,true) + end + end +end + +\stopluacode + +\stoptext diff --git a/tex/context/base/scrn-ini.lua b/tex/context/base/scrn-ini.lua index 76696eed0..2836362df 100644 --- a/tex/context/base/scrn-ini.lua +++ b/tex/context/base/scrn-ini.lua @@ -12,10 +12,19 @@ local general = interactions.general local codeinjections = backends.codeinjections +local identitydata = { } + local function setupidentity(specification) + for k, v in next, specification do + identitydata[k] = v + end codeinjections.setupidentity(specification) end +function general.getidentity() + return identitydata +end + general.setupidentity = setupidentity commands.setupidentity = setupidentity diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua index 3ff6f1d96..4462ddb9c 100644 --- a/tex/context/base/sort-ini.lua +++ b/tex/context/base/sort-ini.lua @@ -50,12 +50,13 @@ local utfbyte, utfchar = utf.byte, utf.char local utfcharacters = string.utfcharacters local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset -local allocate = utilities.storage.allocate +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -local trace_tests = false trackers.register("sorters.tests", function(v) trace_tests = v end) -local trace_methods = false trackers.register("sorters.methods", function(v) trace_methods = v end) +local trace_tests = false trackers.register("sorters.tests", function(v) trace_tests = v end) +local trace_methods = false trackers.register("sorters.methods", function(v) trace_methods = v end) -local report_sorters = logs.reporter("languages","sorters") +local report_sorters = logs.reporter("languages","sorters") local comparers = { } local splitters = { } @@ -278,7 +279,7 @@ local function update() -- prepare parent chains, needed when new languages are for language, data in next, definitions do local parent = data.parent or "default" if language ~= "default" then - setmetatable(data,{ __index = definitions[parent] or definitions.default }) + setmetatableindex(data,definitions[parent] or definitions.default) end data.language = language data.parent = parent diff --git a/tex/context/base/sort-lan.lua b/tex/context/base/sort-lan.lua index 7bfa0d86b..e7556c1de 100644 --- a/tex/context/base/sort-lan.lua +++ b/tex/context/base/sort-lan.lua @@ -862,7 +862,7 @@ definitions["et"] = { local fschars = characters.fschars -function firstofsplit(first) +local function firstofsplit(first) local fs = fschars[first] or first -- print(string.format("%04x %04x",utfbyte(first),utfbyte(fs))) return fs, fs -- entry, tag diff --git a/tex/context/base/spac-ali.mkiv b/tex/context/base/spac-ali.mkiv index 297302808..cccfe181a 100644 --- a/tex/context/base/spac-ali.mkiv +++ b/tex/context/base/spac-ali.mkiv @@ -473,8 +473,8 @@ \def\setraggedparagraphmode {\doifrightpageelse - {\ifdoublesided\signalinnerrealign\firstoftwoarguments \fi} - {\ifdoublesided\signalouterrealign\secondoftwoarguments\fi}} + {\ifdoublesided\signalinnerrealign\expandafter\firstoftwoarguments \fi} + {\ifdoublesided\signalouterrealign\expandafter\secondoftwoarguments\fi}} \def\installalign#1#2{\setvalue{@@align@@#1}{#2}} % can be used for overloads diff --git a/tex/context/base/spac-grd.mkiv b/tex/context/base/spac-grd.mkiv index 91fcf3207..8701f4d7e 100644 --- a/tex/context/base/spac-grd.mkiv +++ b/tex/context/base/spac-grd.mkiv @@ -267,12 +267,19 @@ \def\donegtopbaselinecorrection{\blank[\thenegtopbaselinecorrection]} \def\donegbotbaselinecorrection{\blank[\thenegbotbaselinecorrection]} +% nointerlineskip +% +% startpacked +% \startlinecorrection \framed{test} \stoplinecorrection +% \startlinecorrection \framed{test} \stoplinecorrection +% \stoppacked + \def\forcedtopbaselinecorrection {\ifvmode \bgroup \setbaselinecorrections \vspacing[white] - \nointerlineskip +% \nointerlineskip % \dotopbaselinecorrection \egroup \fi} diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv index 220e1c15c..de16fa286 100644 --- a/tex/context/base/spac-ver.mkiv +++ b/tex/context/base/spac-ver.mkiv @@ -457,9 +457,6 @@ % laatste skip over de lege tekst heen gehaald. Dit komt goed % van pas bij het plaatsen van (mogelijk lege) lijsten. -\newsignal \noparskipsignal % \def\noparskipsignal {0.00001pt} -\def\lastdoneparskip {0pt} - \newconditional\noblankinpacked \newcount\packeddepth diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf index 277169501..d15ff4264 100644 Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf new file mode 100644 index 000000000..5e11911be Binary files /dev/null and b/tex/context/base/status-lua.pdf differ diff --git a/tex/context/base/strc-blk.lua b/tex/context/base/strc-blk.lua index 0c94af5bb..cbdc8c6ea 100644 --- a/tex/context/base/strc-blk.lua +++ b/tex/context/base/strc-blk.lua @@ -18,19 +18,21 @@ local structures, context = structures, context structures.blocks = structures.blocks or { } -local blocks = structures.blocks -local sections = structures.sections -local lists = structures.lists +local blocks = structures.blocks +local sections = structures.sections +local lists = structures.lists -local collected, tobesaved, states = allocate(), allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() +local states = allocate() -blocks.collected = collected -blocks.tobesaved = tobesaved -blocks.states = states +blocks.collected = collected +blocks.tobesaved = tobesaved +blocks.states = states local function initializer() - collected = mark(blocks.collected) - tobesaved = mark(blocks.tobesaved) + collected = blocks.collected + tobesaved = blocks.tobesaved end job.register('structures.blocks.collected', tobesaved, initializer) diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index 40b01fcbe..d50d49b92 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -41,6 +41,8 @@ local processors = structures.processors local sprintprocessor = processors.sprint local ignoreprocessor = processors.ignore +local a_internal = attributes.private('internal') + -- -- -- document -- -- -- local data @@ -73,14 +75,15 @@ documents.initialize() -- -- -- sections -- -- -- -local collected, tobesaved = allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() sections.collected = collected sections.tobesaved = tobesaved --~ local function initializer() ---~ collected = mark(sections.collected) ---~ tobesaved = mark(sections.tobesaved) +--~ collected = sections.collected +--~ tobesaved = sections.tobesaved --~ end --~ job.register('structures.sections.collected', tobesaved, initializer) @@ -316,9 +319,12 @@ function sections.somelevel(given) report_structure("name '%s', numbers '%s', own numbers '%s'",givenname,concat(numberdata.numbers, " "),concat(numberdata.ownnumbers, " ")) end - given.references.tag = tags.last and tags.last("section") -- (metadata.kind) sort of forward usage (section -> structure) + local metadata = given.metadata + local references = given.references + + references.tag = references.tag or tags.getid(metadata.kind,metadata.name) - given.references.section = sections.save(given) + references.section = sections.save(given) -- given.numberdata = nil end diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua index d213c925e..a9013c641 100644 --- a/tex/context/base/strc-ini.lua +++ b/tex/context/base/strc-ini.lua @@ -25,7 +25,7 @@ local count, texwrite, texprint, texsprint = tex.count, tex.write, tex.print, te local type, next, tonumber, tostring = type, next, tonumber, tostring local lpegmatch = lpeg.match local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate local ctxcatcodes, xmlcatcodes, notcatcodes = tex.ctxcatcodes, tex.xmlcatcodes, tex.notcatcodes -- tricky as we're in notcatcodes @@ -81,14 +81,15 @@ structures.synonyms = structures.synonyms or { } local specials = structures.specials -local collected, tobesaved = allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() specials.collected = collected specials.tobesaved = tobesaved local function initializer() - collected = mark(specials.collected) - tobesaved = mark(specials.tobesaved) + collected = specials.collected + tobesaved = specials.tobesaved end if job then diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua index f09444f26..6a7a7d8c7 100644 --- a/tex/context/base/strc-lst.lua +++ b/tex/context/base/strc-lst.lua @@ -17,7 +17,7 @@ local texsprint, texprint, texwrite, texcount = tex.sprint, tex.print, tex.write local concat, insert, remove = table.concat, table.insert, table.remove 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, mark, checked = utilities.storage.allocate, utilities.storage.mark, utilities.storage.checked +local allocate, checked = utilities.storage.allocate, utilities.storage.checked local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end) @@ -75,7 +75,7 @@ end local function initializer() -- create a cross reference between internal references -- and list entries - local collected = mark(lists.collected) + local collected = lists.collected local internals = checked(references.internals) local ordered = lists.ordered for i=1,#collected do @@ -110,14 +110,12 @@ end job.register('structures.lists.collected', tobesaved, initializer) function lists.push(t) + local m = t.metadata local r = t.references local i = (r and r.internal) or 0 -- brrr local p = pushed[i] if not p then p = #cached + 1 - if r.tag == nil then - r.tag = tags.last and tags.last(t.metadata.kind) -- maybe kind but then also check elsewhere - end cached[p] = helpers.simplify(t) pushed[i] = p end @@ -134,14 +132,21 @@ function lists.enhance(n) -- todo: symbolic names for counters local l = cached[n] if l then + local metadata = l.metadata + local references = l.references -- l.directives = nil -- might change -- save in the right order (happens at shipout) lists.tobesaved[#lists.tobesaved+1] = l -- default enhancer (cross referencing) - l.references.realpage = texcount.realpageno + references.realpage = texcount.realpageno + -- tags + local kind = metadata.kind + local name = metadata.name + if references then + references.tag = tags.getid(kind,name) + end -- specific enhancer (kind of obsolete) - local kind = l.metadata.kind local enhancer = kind and lists.enhancers[kind] if enhancer then enhancer(l) diff --git a/tex/context/base/strc-lst.mkiv b/tex/context/base/strc-lst.mkiv index b14297e26..c764b889b 100644 --- a/tex/context/base/strc-lst.mkiv +++ b/tex/context/base/strc-lst.mkiv @@ -141,7 +141,7 @@ {\ctxlua{structures.lists.realpage("\currentlist",\currentlistindex)}} \def\structurelistfirst - {\dostarttagged\t!listdata{first} % ot always ok + {\dostarttagged\t!listdata{first}% not always ok \ctxlua{structures.lists.userdata("\currentlist",\currentlistindex,"first")}% \dostoptagged} @@ -499,7 +499,7 @@ \unexpanded\def\listsymbol[#1]#2% {\begingroup \edef\currentlist{#1}% - \edef\currentlistnumber{#2}% + \def\currentlistnumber{#2}% no edef else tag problems \currentlistsymbol \endgroup} @@ -633,7 +633,7 @@ \def\dodolistelement#1#2#3#4#5#6% {\edef\currentlist{#1}% - \edef\currentlistnumber{#3}% + \def\currentlistnumber{#3}% no edef else tag problem \docurrentlistalternative \letinteractionparameter\c!width\zeropoint \dontcomplain @@ -999,7 +999,7 @@ \ctxlua{structures.lists.title("\currentlist",\currentlistindex)}% \dostoptagged} -\def\structurelistgenericnumber +\def\structurelistgenericnumber % tricky, we need to delay tagging as we have nested lua calls {\dostarttagged\t!listtag\empty \ctxlua{structures.lists.prefixednumber("\currentlist",\currentlistindex, { prefix = "\listparameter\c!prefix", diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua index 983ffe97e..5bb40fa94 100644 --- a/tex/context/base/strc-mar.lua +++ b/tex/context/base/strc-mar.lua @@ -9,15 +9,18 @@ if not modules then modules = { } end modules ['strc-mar'] = { -- todo: cleanup stack (structures.marks.reset(v_all) also does the job) local insert, concat = table.insert, table.concat -local tostring, next, setmetatable, rawget = tostring, next, setmetatable, rawget +local tostring, next, rawget = tostring, next, rawget local lpegmatch = lpeg.match +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local hasattribute = nodes.hasattribute +local getattribute = nodes.getattribute local traversenodes = node.traverse local texsetattribute = tex.setattribute local texbox = tex.box @@ -58,7 +61,7 @@ local lists = structures.lists local settings_to_array = utilities.parsers.settings_to_array -marks.data = marks.data or { } +marks.data = marks.data or allocate() storage.register("structures/marks/data", marks.data, "structures.marks.data") @@ -85,7 +88,7 @@ local function resolve(t,k) end end -setmetatable(data, { __index = resolve} ) +setmetatableindex(data, resolve) function marks.exists(name) return rawget(data,name) ~= nil @@ -97,7 +100,7 @@ local function sweep(head,first,last) for n in traversenodes(head) do local id = n.id if id == glyph_code then - local a = hasattribute(n,a_marks) + local a = getattribute(n,a_marks) if not a then -- next elseif first == 0 then @@ -106,7 +109,7 @@ local function sweep(head,first,last) last = a end elseif id == hlist_code or id == vlist_code then - local a = hasattribute(n,a_marks) + local a = getattribute(n,a_marks) if not a then -- next elseif first == 0 then @@ -125,7 +128,7 @@ end local classes = { } -setmetatable(classes, { __index = function(t,k) local s = settings_to_array(k) t[k] = s return s end } ) +setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end) function marks.synchronize(class,n) local box = texbox[n] @@ -187,11 +190,11 @@ function marks.define(name,settings) settings.parent = dp.parent end end - setmetatable(settings, { __index = resolve } ) + setmetatableindex(settings, resolve) end for k, v in next, data do - setmetatable(v, { __index = resolve } ) -- runtime loaded table + setmetatableindex(v,resolve) -- runtime loaded table end local function parentname(name) diff --git a/tex/context/base/strc-num.lua b/tex/context/base/strc-num.lua index b8a62d152..95cf6d941 100644 --- a/tex/context/base/strc-num.lua +++ b/tex/context/base/strc-num.lua @@ -12,25 +12,25 @@ local format = string.format local next, type = next, type local min, max = math.min, math.max local texsprint, texcount = tex.sprint, tex.count -local allocate, mark = utilities.storage.allocate, utilities.storage.mark -local trace_counters = false trackers.register("structures.counters", function(v) trace_counters = v end) +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -local report_counters = logs.reporter("structure","counters") +local trace_counters = false trackers.register("structures.counters", function(v) trace_counters = v end) +local report_counters = logs.reporter("structure","counters") -local structures = structures +local structures = structures +local helpers = structures.helpers +local sections = structures.sections +local counters = structures.counters +local documents = structures.documents -local helpers = structures.helpers -local sections = structures.sections -local counters = structures.counters -local documents = structures.documents - -local variables = interfaces.variables +local variables = interfaces.variables -- state: start stop none reset -counters.specials = counters.specials or { } -local counterspecials = counters.specials +counters.specials = counters.specials or { } +local counterspecials = counters.specials local counterranges, tbs = { }, 0 @@ -113,7 +113,7 @@ local function enhance() local data = cd.data for i=1,#data do local ci = data[i] - setmetatable(ci, { __index = function(t,s) return constructor(t,s,name,i) end }) + setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end) end end enhance = nil @@ -145,7 +145,7 @@ local function allocate(name,i) -- can be metatable offset = false, stop = 0, -- via metatable: last, first, stop only for tracing } - setmetatable(ci, { __index = function(t,s) return constructor(t,s,name,i) end }) + setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end) cd[i] = ci tobesaved[name][i] = { } else diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua index b899b924b..bce8a2c3a 100644 --- a/tex/context/base/strc-pag.lua +++ b/tex/context/base/strc-pag.lua @@ -37,8 +37,8 @@ pages.collected = collected pages.tobesaved = tobesaved local function initializer() - collected = mark(pages.collected) - tobesaved = mark(pages.tobesaved) + collected = pages.collected + tobesaved = pages.tobesaved end job.register('structures.pages.collected', tobesaved, initializer) diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index 3379bbbdb..ee32353f0 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -9,10 +9,11 @@ if not modules then modules = { } end modules ['strc-ref'] = { local format, find, gmatch, match, concat = string.format, string.find, string.gmatch, string.match, table.concat local lpegmatch, lpegP, lpegCs = lpeg.match, lpeg.P, lpeg.Cs local texcount, texsetcount = tex.count, tex.setcount -local allocate, mark = utilities.storage.allocate, utilities.storage.mark -local setmetatable, rawget = setmetatable, rawget +local rawget = rawget -local allocate = utilities.storage.allocate +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) @@ -44,8 +45,8 @@ references.defined = references.defined or allocate() local defined = references.defined local derived = allocate() -local specials = { } -- allocate() -local runners = { } -- allocate() +local specials = allocate() +local runners = allocate() local internals = allocate() local exporters = allocate() local imported = allocate() @@ -86,15 +87,14 @@ function references.registerfinalizer(func) -- we could use a token register ins end local function initializer() -- can we use a tobesaved as metatable for collected? - tobesaved = mark(references.tobesaved) - collected = mark(references.collected) + tobesaved = references.tobesaved + collected = references.collected for i=1,#initializers do initializers[i](tobesaved,collected) end end local function finalizer() - -- tobesaved = mark(references.tobesaved) for i=1,#finalizers do finalizers[i](tobesaved) end @@ -105,10 +105,9 @@ job.register('structures.references.collected', tobesaved, initializer, finalize local maxreferred = 1 local function initializer() -- can we use a tobesaved as metatable for collected? - tobereferred = mark(references.tobereferred) - referred = mark(references.referred) - - function get(t,n) -- catch sparse, a bit slow but who cares + tobereferred = references.tobereferred + referred = references.referred + local function get(t,n) -- catch sparse, a bit slow but who cares for i=n,1,-1 do -- we could make a tree ... too much work local p = rawget(t,i) if p then @@ -116,7 +115,7 @@ local function initializer() -- can we use a tobesaved as metatable for collecte end end end - setmetatable(referred, { __index = get }) + setmetatableindex(referred, get) end local function finalizer() -- make sparse @@ -133,6 +132,8 @@ local function finalizer() -- make sparse end end +job.register('structures.references.referred', tobereferred, initializer, finalizer) + function references.referredpage(n) return referred[n] or referred[n] or texcount.realpageno end @@ -146,8 +147,6 @@ function references.registerpage(n) end end -job.register('structures.references.referred', tobereferred, initializer, finalizer) - -- todo: delay split till later as in destinations we split anyway local orders, lastorder = { }, 0 @@ -305,7 +304,7 @@ local function register_from_lists(collected,derived) if kind and realpage then local d = derived[prefix] if not d then d = { } derived[prefix] = d end local t = { kind, i } - for s in gmatch(reference,"[^, ]+") do + 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 @@ -1109,7 +1108,7 @@ set.n = n bug = bug or var.error set[i] = var end - references.currentset = set + references.currentset = mark(set) -- mark, else in api doc --~ table.print(set,tostring(bug)) return set, bug end @@ -1440,7 +1439,7 @@ end local plist -function realpageofpage(p) +local function realpageofpage(p) if not plist then local pages = structures.pages.collected plist = { } diff --git a/tex/context/base/strc-ref.mkiv b/tex/context/base/strc-ref.mkiv index 60a02c171..bec96e05c 100644 --- a/tex/context/base/strc-ref.mkiv +++ b/tex/context/base/strc-ref.mkiv @@ -1157,12 +1157,12 @@ \attribute\referenceattribute\attributeunsetvalue \global\lastsavedreferenceattribute\attributeunsetvalue \iflocation - \dostarttagged\t!link\empty % not here \ctxlua{structures.references.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% \setlocationattributes\??ia \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute \attribute\referenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty % not here #1% \dostoptagged \else @@ -1176,14 +1176,16 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \dostarttagged\t!link\empty \ctxlua{structures.references.inject("\referenceprefix","#2",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% - \dostoptagged \setlocationattributes\??ia \attribute\referenceattribute\lastreferenceattribute \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + #1% + \dostoptagged + \else + #1% \fi - #1% \endgroup} \def\dogoto#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok @@ -1195,16 +1197,18 @@ \iflocation \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference - \dostarttagged\t!link\empty \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% - \dostoptagged \setlocationattributes\??ia \setstrut % can be option \global\lastsavedreferenceattribute\lastreferenceattribute - \attribute\referenceattribute\lastreferenceattribute}% - {}% + \attribute\referenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + #1% + \dostoptagged}% + {#1}% + \else + #1% \fi - #1% %\egroup\unhbox\referencebox} \endgroup} @@ -1216,15 +1220,17 @@ \iflocation \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference - \dostarttagged\t!link\empty \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% - \dostoptagged \setlocationattributes\??ia \global\lastsavedreferenceattribute\lastreferenceattribute - \attribute\referenceattribute\lastreferenceattribute}% - {}% + \attribute\referenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + #1% + \dostoptagged}% + {#1}% + \else + #1% \fi - #1% \endgroup} \unexpanded\def\directgotobox#1[#2]% no test for valid references @@ -1233,12 +1239,12 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \dostarttagged\t!link\empty \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% - \dostoptagged \setlocationattributes\??ia \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#1}% + \dostoptagged \else #1% \fi @@ -1250,12 +1256,12 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \dostarttagged\t!link\empty \ctxlua{structures.references.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}% - \dostoptagged \setlocationcolorspec{#1}% no consequence for strut \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#2}% + \dostoptagged \else #2% \fi @@ -1267,11 +1273,11 @@ \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \iflocation - \dostarttagged\t!link\empty \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% - \dostoptagged \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty \hbox attr \referenceattribute \lastreferenceattribute {#1}% + \dostoptagged \else #1% \fi @@ -1285,13 +1291,13 @@ \iflocation \ctxlua{structures.references.doifelse("\referenceprefix","#2",\extrareferencearguments)}% {\expandtexincurrentreference - \dostarttagged\t!link\empty \ctxlua{structures.references.injectcurrentset(nil,nil)}% - \dostoptagged \setlocationattributes\??ia \global\lastsavedreferenceattribute\lastreferenceattribute - \hbox attr \referenceattribute \lastreferenceattribute {#1}}% - {}% + \dostarttagged\t!link\empty + \hbox attr \referenceattribute \lastreferenceattribute {#1}% + \dostoptagged}% + {#1}% \else #1% \fi @@ -1300,14 +1306,14 @@ \unexpanded\def\gotowdhtbox#1#2[#3]% fast variant for overlays {\dontleavehmode \begingroup + \setbox\scratchbox\emptyhbox\wd\scratchbox#1\ht\scratchbox#2% \global\lastsavedreferenceattribute\attributeunsetvalue \attribute\referenceattribute\attributeunsetvalue \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\ctxlua{structures.references.injectcurrentset(nil,nil)}% - \setbox\scratchbox\emptyhbox\wd\scratchbox#1\ht\scratchbox#2% \global\lastsavedreferenceattribute\lastreferenceattribute - \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}% - {}% + \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} + {\box\scratchbox}% \endgroup} %D An reference to another document can be specified as a file diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua index b2deb0605..c19ae12d6 100644 --- a/tex/context/base/strc-reg.lua +++ b/tex/context/base/strc-reg.lua @@ -12,7 +12,7 @@ local format, gmatch = string.format, string.gmatch local equal, concat, remove = table.are_equal, table.concat, table.remove local utfchar = utf.char local lpegmatch = lpeg.match -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate local trace_registers = false trackers.register("structures.registers", function(v) trace_registers = v end) @@ -177,11 +177,11 @@ local function filtercollected(names,criterium,number,collected,prevmode) return result end -local tobesaved, collected = allocate(), allocate() - -registers.collected = collected -registers.tobesaved = tobesaved +local tobesaved = allocate() +local collected = allocate() +registers.collected = collected +registers.tobesaved = tobesaved registers.filtercollected = filtercollected -- we follow a different strategy than by lists, where we have a global @@ -189,8 +189,8 @@ registers.filtercollected = filtercollected -- older we delay that decision local function initializer() - tobesaved = mark(registers.tobesaved) - collected = mark(registers.collected) + tobesaved = registers.tobesaved + collected = registers.collected local internals = references.internals for name, list in next, collected do local entries = list.entries @@ -650,7 +650,7 @@ local function collapsedpage(pages) return false end -function collapsepages(pages) +local function collapsepages(pages) while collapsedpage(pages) do end return #pages end diff --git a/tex/context/base/strc-ren.mkiv b/tex/context/base/strc-ren.mkiv index 84f8b34dd..73eb0ccd2 100644 --- a/tex/context/base/strc-ren.mkiv +++ b/tex/context/base/strc-ren.mkiv @@ -120,12 +120,14 @@ {\iflocation attr \destinationattribute \currentstructureattribute attr \referenceattribute \currentstructurereferenceattribute - \fi} + % attr \internalattribute \nextinternalreference + \fi} \def\setinlinestructureheadreferenceattributes {\ifconditional\structureheadisdisplay \else \iflocation - \attribute\destinationattribute\currentstructureattribute - \attribute\referenceattribute \currentstructurereferenceattribute + \attribute\destinationattribute\currentstructureattribute + \attribute\referenceattribute \currentstructurereferenceattribute + % \attribute\internalattribute \nextinternalreference \fi \fi} \def\docheckstructureheadreference diff --git a/tex/context/base/strc-syn.lua b/tex/context/base/strc-syn.lua index 599f15311..f3ba97ffc 100644 --- a/tex/context/base/strc-syn.lua +++ b/tex/context/base/strc-syn.lua @@ -8,21 +8,23 @@ if not modules then modules = { } end modules ['str-syn'] = { local next, type = next, type local texwrite, format = tex.write, string.format -local allocate, mark = utilities.storage.allocate, utilities.storage.mark +local allocate = utilities.storage.allocate -- interface to tex end -local structures = structures -local synonyms = structures.synonyms +local structures = structures +local synonyms = structures.synonyms +local tags = structures.tags -local collected, tobesaved = allocate(), allocate() +local collected = allocate() +local tobesaved = allocate() synonyms.collected = collected synonyms.tobesaved = tobesaved local function initializer() - collected = mark(synonyms.collected) - tobesaved = mark(synonyms.tobesaved) + collected = synonyms.collected + tobesaved = synonyms.tobesaved end local function finalizer() @@ -33,6 +35,8 @@ end job.register('structures.synonyms.collected', tobesaved, initializer, finalizer) +-- todo: allocate becomes metatable + local function allocate(class) local d = tobesaved[class] if not d then diff --git a/tex/context/base/strc-syn.mkiv b/tex/context/base/strc-syn.mkiv index 1cb1bb1f6..f063ef087 100644 --- a/tex/context/base/strc-syn.mkiv +++ b/tex/context/base/strc-syn.mkiv @@ -20,6 +20,9 @@ \unprotect +\let\dotagsynonym\relax +\let\dotagsorting\relax + % general help, can be shared % simplifiedcommands -> flag in lua @@ -171,8 +174,12 @@ \unexpanded\def\doinsertsynonym#1#2% name tag {\begingroup \def\currentsynonym{#1}% + \def\currentsynonymtag{#2}% + \dotagsynonym + \dostarttagged\t!synonym\currentsynonym \dosetsynonymattributes\c!synonymstyle\c!synonymcolor \synonymparameter\c!synonymcommand{\ctxlua{structures.synonyms.synonym("#1","#2")}}% + \dostoptagged \normalexpanded{\endgroup\synonymparameter\c!next}} \unexpanded\def\placelistofsynonyms @@ -328,8 +335,12 @@ {\begingroup % no kap currently, of .. we need to map cap onto WORD \edef\currentsorting{#1}% + \def\currentsortingtag{#2}% + \dotagsorting + \dostarttagged\t!sorting\currentsorting \dosetsortingattributes\c!style\c!color \ctxlua{structures.synonyms.synonym("#1","#2")}% + \dostoptagged \normalexpanded{\endgroup\sortingparameter\c!next}} \def\registersort diff --git a/tex/context/base/strc-tag.lua b/tex/context/base/strc-tag.lua index 1c30541c3..f1381dad5 100644 --- a/tex/context/base/strc-tag.lua +++ b/tex/context/base/strc-tag.lua @@ -33,10 +33,12 @@ local stack = { } local chain = { } local ids = { } local enabled = false +local tagdata = { } -- used in export local tags = structures.tags tags.taglist = taglist -- can best be hidden tags.labels = labels +tags.data = tagdata local properties = allocate { @@ -62,9 +64,13 @@ local properties = allocate { descriptionsymbol = { pdf = "Span", nature = "inline" }, -- note reference verbatimblock = { pdf = "Code", nature = "display" }, - verbatimline = { pdf = "Code", nature = "display" }, + verbatimlines = { pdf = "Code", nature = "display" }, + verbatimline = { pdf = "Code", nature = "mixed" }, verbatim = { pdf = "Code", nature = "inline" }, + synonym = { pdf = "Span", nature = "inline" }, + sort = { pdf = "Span", nature = "inline" }, + register = { pdf = "Div", nature = "display" }, registersection = { pdf = "Div", nature = "display" }, registertag = { pdf = "Span", nature = "mixed" }, @@ -175,7 +181,7 @@ function tags.start(tag,specification) stack[#stack+1] = t -- insert(stack,t) taglist[t] = { unpack(chain) } -- we can add key values for alt and actualtext if needed if user and user ~= "" then - -- maybe we should merge this into taglistor or whatever ... anyway there is room to optimize + -- maybe we should merge this into taglist or whatever ... anyway there is room to optimize -- taglist.userdata = settings_to_hash(user) userdata[completetag] = settings_to_hash(user) end @@ -197,10 +203,29 @@ function tags.stop() return t end +function tags.getid(tag,detail) + if detail and detail ~= "" then + return ids[tag .. ":" .. detail] or "?" + else + return ids[tag] or "?" + end +end + function tags.last(tag) return lasttags[tag] -- or false end +function tags.lastinchain() + return chain[#chain] +end + +function tags.registerdata(data) + local fulltag = chain[#chain] + if fulltag then + tagdata[fulltag] = data + end +end + function structures.atlocation(str) local location = gsub(concat(taglist[texattribute[a_tagged]],"-"),"%-%d+","") return find(location,topattern(str)) ~= nil diff --git a/tex/context/base/strc-tag.mkiv b/tex/context/base/strc-tag.mkiv index addff193b..8bc8d9f69 100644 --- a/tex/context/base/strc-tag.mkiv +++ b/tex/context/base/strc-tag.mkiv @@ -43,9 +43,13 @@ \def\t!descriptionsymbol {descriptionsymbol} % Span \def\t!verbatimblock {verbatimblock} % Code +\def\t!verbatimlines {verbatimlines} % Code \def\t!verbatimline {verbatimline} % Code \def\t!verbatim {verbatim} % Code +\def\t!sorting {sorting} % Span +\def\t!synonym {synonym} % Span + \def\t!register {register} % Div \def\t!registersection {registersection} % Div \def\t!registertag {registertag} % Span diff --git a/tex/context/base/supp-box.lua b/tex/context/base/supp-box.lua index 4d496d8de..48baecf6f 100644 --- a/tex/context/base/supp-box.lua +++ b/tex/context/base/supp-box.lua @@ -24,7 +24,7 @@ local copynodelist = node.copy_list local copynode = node.copy local texbox = tex.box -function hyphenatedlist(list) +local function hyphenatedlist(list) while list do local id, next, prev = list.id, list.next, list.prev if id == disc_code then @@ -50,7 +50,7 @@ function commands.showhyphenatedinlist(list) report_hyphenation("show: %s",nodes.listtoutf(list)) end -function checkedlist(list) +local function checkedlist(list) if type(list) == "number" then return texbox[list].list else diff --git a/tex/context/base/supp-fil.lua b/tex/context/base/supp-fil.lua index 91fa446b9..a2c0b5d7d 100644 --- a/tex/context/base/supp-fil.lua +++ b/tex/context/base/supp-fil.lua @@ -111,11 +111,11 @@ local function readfilename(specification,backtrack,treetoo) if not fnd then if isfile(name) then if trace_files then - report_files("found local: %s",fname) + report_files("found local: %s",name) end fnd = name end - if backtrack then + if not fnd and backtrack then local fname = name for i=1,backtrack,1 do fname = "../" .. fname diff --git a/tex/context/base/trac-log.lua b/tex/context/base/trac-log.lua index fdc57eba1..13bb18b06 100644 --- a/tex/context/base/trac-log.lua +++ b/tex/context/base/trac-log.lua @@ -18,6 +18,8 @@ local escapedpattern = string.escapedpattern local texcount = tex and tex.count local next, type = next, type +local setmetatableindex = table.setmetatableindex + --[[ldx--

This is a prelude to a more extensive logging module. We no longer provide based logging a sparsing is relatively easy anyway.

@@ -38,11 +40,11 @@ wiki : http://contextgarden.net local function ignore() end -setmetatable(logs, { __index = function(t,k) t[k] = ignore ; return ignore end }) +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) -local report, subreport, status, settarget, setformatter +local report, subreport, status, settarget, setformats, settranslations -local direct, subdirect, writer +local direct, subdirect, writer, pushtarget, poptarget if tex and tex.jobname or tex.formatname then diff --git a/tex/context/base/util-deb.lua b/tex/context/base/util-deb.lua index d61ac0f02..5eabbc8c4 100644 --- a/tex/context/base/util-deb.lua +++ b/tex/context/base/util-deb.lua @@ -145,7 +145,7 @@ end local is_node = node and node.is_node -function inspect(i) +function inspect(i) -- global function local ti = type(i) if ti == "table" then table.print(i,"table") diff --git a/tex/context/base/util-dim.lua b/tex/context/base/util-dim.lua new file mode 100644 index 000000000..4e2cc1662 --- /dev/null +++ b/tex/context/base/util-dim.lua @@ -0,0 +1,436 @@ +if not modules then modules = { } end modules ['util-dim'] = { + version = 1.001, + comment = "support for dimensions", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ldx-- +

Internally work with scaled point, which are +represented by integers. However, in practice, at east at the + end we work with more generic units like points (pt). Going +from scaled points (numbers) to one of those units can be +done by using the conversion factors collected in the following +table.

+--ldx]]-- + +local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable +local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match + +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + +--this might become another namespace + +number = number or { } +local number = number + +number.tonumberf = function(n) return match(format("%.20f",n),"(.-0?)0*$") end -- one zero too much but alas +number.tonumberg = function(n) return format("%.20g",n) end + +local dimenfactors = allocate { + ["pt"] = 1/65536, + ["in"] = ( 100/ 7227)/65536, + ["cm"] = ( 254/ 7227)/65536, + ["mm"] = ( 2540/ 7227)/65536, + ["sp"] = 1, -- 65536 sp in 1pt + ["bp"] = ( 7200/ 7227)/65536, + ["pc"] = ( 1/ 12)/65536, + ["dd"] = ( 1157/ 1238)/65536, + ["cc"] = ( 1157/14856)/65536, + ["nd"] = (20320/21681)/65536, + ["nc"] = ( 5080/65043)/65536 +} + +--~ print(table.serialize(dimenfactors)) +--~ +--~ %.99g: +--~ +--~ t={ +--~ ["bp"]=1.5201782378580324e-005, +--~ ["cc"]=1.1883696112892098e-006, +--~ ["cm"]=5.3628510057769479e-007, +--~ ["dd"]=1.4260435335470516e-005, +--~ ["em"]=0.000152587890625, +--~ ["ex"]=6.103515625e-005, +--~ ["in"]=2.1113586636917117e-007, +--~ ["mm"]=5.3628510057769473e-008, +--~ ["nc"]=1.1917446679504327e-006, +--~ ["nd"]=1.4300936015405194e-005, +--~ ["pc"]=1.2715657552083333e-006, +--~ ["pt"]=1.52587890625e-005, +--~ ["sp"]=1, +--~ } +--~ +--~ patched %s and tonumber +--~ +--~ t={ +--~ ["bp"]=0.00001520178238, +--~ ["cc"]=0.00000118836961, +--~ ["cm"]=0.0000005362851, +--~ ["dd"]=0.00001426043534, +--~ ["em"]=0.00015258789063, +--~ ["ex"]=0.00006103515625, +--~ ["in"]=0.00000021113587, +--~ ["mm"]=0.00000005362851, +--~ ["nc"]=0.00000119174467, +--~ ["nd"]=0.00001430093602, +--~ ["pc"]=0.00000127156576, +--~ ["pt"]=0.00001525878906, +--~ ["sp"]=1, +--~ } + +--[[ldx-- +

A conversion function that takes a number, unit (string) and optional +format (string) is implemented using this table.

+--ldx]]-- + +local function numbertodimen(n,unit,fmt) + if type(n) == 'string' then + return n + else + unit = unit or 'pt' + return format(fmt or "%s%s",n*dimenfactors[unit],unit) + -- if fmt then + -- return format(fmt,n*dimenfactors[unit],unit) + -- else + -- return match(format("%.20f",n*dimenfactors[unit]),"(.-0?)0*$") .. unit + -- end + end +end + +--[[ldx-- +

We collect a bunch of converters in the number namespace.

+--ldx]]-- + +number.maxdimen = 1073741823 +number.todimen = numbertodimen +number.dimenfactors = dimenfactors + +function number.topoints (n) return numbertodimen(n,"pt") end +function number.toinches (n) return numbertodimen(n,"in") end +function number.tocentimeters (n) return numbertodimen(n,"cm") end +function number.tomillimeters (n) return numbertodimen(n,"mm") end +function number.toscaledpoints(n) return numbertodimen(n,"sp") end +function number.toscaledpoints(n) return n .. "sp" end +function number.tobasepoints (n) return numbertodimen(n,"bp") end +function number.topicas (n) return numbertodimen(n "pc") end +function number.todidots (n) return numbertodimen(n,"dd") end +function number.tociceros (n) return numbertodimen(n,"cc") end +function number.tonewdidots (n) return numbertodimen(n,"nd") end +function number.tonewciceros (n) return numbertodimen(n,"nc") end + +--[[ldx-- +

More interesting it to implement a (sort of) dimen datatype, one +that permits calculations too. First we define a function that +converts a string to scaledpoints. We use . We capture +a number and optionally a unit. When no unit is given a constant +capture takes place.

+--ldx]]-- + +local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0") +local unit = R("az")^1 + +local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new + +lpeg.patterns.dimenpair = dimenpair + +--[[ldx-- +

We use a metatable to intercept errors. When no key is found in +the table with factors, the metatable will be consulted for an +alternative index function.

+--ldx]]-- + +setmetatableindex(dimenfactors, function(t,s) + -- error("wrong dimension: " .. (s or "?")) -- better a message + return false +end) + +--[[ldx-- +

We redefine the following function later on, so we comment it +here (which saves us bytecodes.

+--ldx]]-- + +-- function string.todimen(str) +-- if type(str) == "number" then +-- return str +-- else +-- local value, unit = lpegmatch(dimenpair,str) +-- return value/unit +-- end +-- end +-- +-- local stringtodimen = string.todimen + +local stringtodimen -- assigned later (commenting saves bytecode) + +local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0 +local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") + + P("pc") + P("dd") + P("cc") + P("nd") + P("nc") + +local validdimen = amount * unit + +lpeg.patterns.validdimen = validdimen + +--[[ldx-- +

This converter accepts calls like:

+ + +string.todimen("10") +string.todimen(".10") +string.todimen("10.0") +string.todimen("10.0pt") +string.todimen("10pt") +string.todimen("10.0pt") + + +

With this in place, we can now implement a proper datatype for dimensions, one +that permits us to do this:

+ + +s = dimen "10pt" + dimen "20pt" + dimen "200pt" + - dimen "100sp" / 10 + "20pt" + "0pt" + + +

We create a local metatable for this new type:

+--ldx]]-- + +local dimensions = { } + +--[[ldx-- +

The main (and globally) visible representation of a dimen is defined next: it is +a one-element table. The unit that is returned from the match is normally a number +(one of the previously defined factors) but we also accept functions. Later we will +see why. This function is redefined later.

+--ldx]]-- + +-- function dimen(a) +-- if a then +-- local ta= type(a) +-- if ta == "string" then +-- local value, unit = lpegmatch(pattern,a) +-- if type(unit) == "function" then +-- k = value/unit() +-- else +-- k = value/unit +-- end +-- a = k +-- elseif ta == "table" then +-- a = a[1] +-- end +-- return setmetatable({ a }, dimensions) +-- else +-- return setmetatable({ 0 }, dimensions) +-- end +-- end + +--[[ldx-- +

This function return a small hash with a metatable attached. It is +through this metatable that we can do the calculations. We could have +shared some of the code but for reasons of speed we don't.

+--ldx]]-- + +function dimensions.__add(a, b) + local ta, tb = type(a), type(b) + if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end + if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end + return setmetatable({ a + b }, dimensions) +end + +function dimensions.__sub(a, b) + local ta, tb = type(a), type(b) + if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end + if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end + return setmetatable({ a - b }, dimensions) +end + +function dimensions.__mul(a, b) + local ta, tb = type(a), type(b) + if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end + if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end + return setmetatable({ a * b }, dimensions) +end + +function dimensions.__div(a, b) + local ta, tb = type(a), type(b) + if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end + if tb == "string" then b = stringtodimen(b) elseif tb == "table" then b = b[1] end + return setmetatable({ a / b }, dimensions) +end + +function dimensions.__unm(a) + local ta = type(a) + if ta == "string" then a = stringtodimen(a) elseif ta == "table" then a = a[1] end + return setmetatable({ - a }, dimensions) +end + +--[[ldx-- +

It makes no sense to implement the power and modulo function but +the next two do make sense because they permits is code like:

+ + +local a, b = dimen "10pt", dimen "11pt" +... +if a > b then + ... +end + +--ldx]]-- + +-- makes no sense: dimensions.__pow and dimensions.__mod + +function dimensions.__lt(a, b) + return a[1] < b[1] +end + +function dimensions.__eq(a, b) + return a[1] == b[1] +end + +--[[ldx-- +

We also need to provide a function for conversion to string (so that +we can print dimensions). We print them as points, just like .

+--ldx]]-- + +function dimensions.__tostring(a) + return a[1]/65536 .. "pt" -- instead of todimen(a[1]) +end + +--[[ldx-- +

Since it does not take much code, we also provide a way to access +a few accessors

+ + +print(dimen().pt) +print(dimen().sp) + +--ldx]]-- + +function dimensions.__index(tab,key) + local d = dimenfactors[key] + if not d then + error("illegal property of dimen: " .. key) + d = 1 + end + return 1/d +end + +--[[ldx-- +

In the converter from string to dimension we support functions as +factors. This is because in we have a few more units: +ex and em. These are not constant factors but +depend on the current font. They are not defined by default, but need +an explicit function call. This is because at the moment that this code +is loaded, the relevant tables that hold the functions needed may not +yet be available.

+--ldx]]-- + + dimenfactors["ex"] = 4 * 1/65536 -- 4pt + dimenfactors["em"] = 10 * 1/65536 -- 10pt +-- dimenfactors["%"] = 4 * 1/65536 -- 400pt/100 + +--[[ldx-- +

The previous code is rather efficient (also thanks to ) but we +can speed it up by caching converted dimensions. On my machine (2008) the following +loop takes about 25.5 seconds.

+ + +for i=1,1000000 do + local s = dimen "10pt" + dimen "20pt" + dimen "200pt" + - dimen "100sp" / 10 + "20pt" + "0pt" +end + + +

When we cache converted strings this becomes 16.3 seconds. In order not +to waste too much memory on it, we tag the values of the cache as being +week which mean that the garbage collector will collect them in a next +sweep. This means that in most cases the speed up is mostly affecting the +current couple of calculations and as such the speed penalty is small.

+ +

We redefine two previous defined functions that can benefit from +this:

+--ldx]]-- + +local known = { } setmetatable(known, { __mode = "v" }) + +function dimen(a) + if a then + local ta= type(a) + if ta == "string" then + local k = known[a] + if k then + a = k + else + local value, unit = lpegmatch(dimenpair,a) + if type(unit) == "function" then + k = value/unit() + else + k = value/unit + end + known[a] = k + a = k + end + elseif ta == "table" then + a = a[1] + end + return setmetatable({ a }, dimensions) + else + return setmetatable({ 0 }, dimensions) + end +end + +function string.todimen(str) -- maybe use tex.sp when available + if type(str) == "number" then + return str + else + local k = known[str] + if not k then + local value, unit = lpegmatch(dimenpair,str) + if value and unit then + k = value/unit -- to be considered: round + else + k = 0 + end + -- print(str,value,unit) + known[str] = k + end + return k + end +end + +--~ local known = { } + +--~ function string.todimen(str) -- maybe use tex.sp +--~ local k = known[str] +--~ if not k then +--~ k = tex.sp(str) +--~ known[str] = k +--~ end +--~ return k +--~ end + +stringtodimen = string.todimen -- local variable defined earlier + +function number.toscaled(d) + return format("%0.5f",d/2^16) +end + +--[[ldx-- +

In a similar fashion we can define a glue datatype. In that case we +probably use a hash instead of a one-element table.

+--ldx]]-- + +--[[ldx-- +

Goodie:s

+--ldx]]-- + +function number.percent(n) -- will be cleaned up once luatex 0.30 is out + local hsize = tex.hsize + if type(hsize) == "string" then + hsize = stringtodimen(hsize) + end + return (n/100) * hsize +end + +number["%"] = number.percent diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua index 617dc0c78..591453760 100644 --- a/tex/context/base/util-prs.lua +++ b/tex/context/base/util-prs.lua @@ -6,18 +6,20 @@ if not modules then modules = { } end modules ['util-prs'] = { license = "see context related readme files" } +local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg +local lpegmatch = lpeg.match +local concat, format, gmatch = table.concat, string.format, string.gmatch +local tostring, type, next = tostring, type, next + utilities = utilities or {} utilities.parsers = utilities.parsers or { } local parsers = utilities.parsers parsers.patterns = parsers.patterns or { } --- we could use a Cf Cg construct +local setmetatableindex = table.setmetatableindex +local sortedhash = table.sortedhash -local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg -local lpegmatch = lpeg.match -local concat, format, gmatch = table.concat, string.format, string.gmatch -local tostring, type, next, setmetatable = tostring, type, next, setmetatable -local sortedhash = table.sortedhash +-- we could use a Cf Cg construct local escape, left, right = P("\\"), P('{'), P('}') @@ -216,7 +218,7 @@ function parsers.getparameters(self,class,parentclass,settings) sp = { } self[parentclass] = sp end - setmetatable(sc, { __index = sp }) + setmetatableindex(sc,sp) end end parsers.settings_to_hash(settings,sc) diff --git a/tex/context/base/util-seq.lua b/tex/context/base/util-seq.lua index f36d1d640..22733b022 100644 --- a/tex/context/base/util-seq.lua +++ b/tex/context/base/util-seq.lua @@ -22,10 +22,12 @@ local type, loadstring = type, loadstring utilities = utilities or { } local tables = utilities.tables +local allocate = utilities.storage.allocate local sequencers = { } utilities.sequencers = sequencers -local functions = { } + +local functions = allocate() sequencers.functions = functions local removevalue, insertaftervalue, insertbeforevalue = tables.removevalue, tables.insertaftervalue, tables.insertbeforevalue diff --git a/tex/context/base/util-sto.lua b/tex/context/base/util-sto.lua index 19b8093c9..f4521c91f 100644 --- a/tex/context/base/util-sto.lua +++ b/tex/context/base/util-sto.lua @@ -50,20 +50,6 @@ function storage.checked(t) return t end -function setmetatablekey(t,key,value) - local m = getmetatable(t) - if not m then - m = { } - setmetatable(t,m) - end - m[key] = value -end - -function getmetatablekey(t,key,value) - local m = getmetatable(t) - return m and m[key] -end - --~ function utilities.storage.delay(parent,name,filename) --~ local m = getmetatable(parent) --~ m.__list[name] = filename @@ -109,3 +95,74 @@ function storage.sparse(t) setmetatable(t,keyisvalue) return t end + +-- table namespace ? + +local function f_empty () return "" end -- t,k +local function f_self (t,k) t[k] = k return k end +local function f_ignore() end -- t,k,v + +local t_empty = { __index = empty } +local t_self = { __index = self } +local t_ignore = { __newindex = ignore } + +function table.setmetatableindex(t,f) + local m = getmetatable(t) + if m then + if f == "empty" then + m.__index = f_empty + elseif f == "key" then + m.__index = f_self + else + m.__index = f + end + else + if f == "empty" then + setmetatable(t, t_empty) + elseif f == "key" then + setmetatable(t, t_self) + else + setmetatable(t,{ __index = f }) + end + end +end + +function table.setmetatablenewindex(t,f) + local m = getmetatable(t) + if m then + if f == "ignore" then + m.__newindex = f_ignore + else + m.__newindex = f + end + else + if f == "ignore" then + setmetatable(t, t_ignore) + else + setmetatable(t,{ __newindex = f }) + end + end +end + +function table.setmetatablecall(t,f) + local m = getmetatable(t) + if m then + m.__call = f + else + setmetatable(t,{ __call = f }) + end +end + +function table.setmetatablekey(t,key,value) + local m = getmetatable(t) + if not m then + m = { } + setmetatable(t,m) + end + m[key] = value +end + +function table.getmetatablekey(t,key,value) + local m = getmetatable(t) + return m and m[key] +end diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index f8422c626..818266d3c 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -12,7 +12,7 @@ local tables = utilities.tables local format, gmatch = string.format, string.gmatch local concat, insert, remove = table.concat, table.insert, table.remove -local setmetatable, tonumber, tostring = setmetatable, tonumber, tostring +local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring function tables.definetable(target) -- defines undefined tables local composed, t, n = nil, { }, 0 @@ -77,12 +77,6 @@ function tables.insertaftervalue(t,value,extra) insert(t,#t+1,extra) end -local _empty_table_ = { __index = function(t,k) return "" end } - -function table.setemptymetatable(t) - setmetatable(t,_empty_table_) -end - -- experimental local function toxml(t,d,result) @@ -99,8 +93,13 @@ local function toxml(t,d,result) end end -function table.toxml(t,name) - local result = { "" } - toxml( { [name or "root"] = t }, "", result) +function table.toxml(t,name,nobanner) + local noroot = name == false + local result = (nobanner or noroot) and { } or { "" } + if noroot then + toxml( t, "", result) + else + toxml( { [name or "root"] = t }, "", result) + end return concat(result,"\n") end diff --git a/tex/context/base/x-set-11.mkiv b/tex/context/base/x-set-11.mkiv index 4db75ef06..ceba34f3d 100644 --- a/tex/context/base/x-set-11.mkiv +++ b/tex/context/base/x-set-11.mkiv @@ -29,7 +29,7 @@ % \setup{setupinterlinespace:1} % \setup{setupinterlinespace:2} % -% cd:include -> @file +% cd:include -> filename % cd:choice % % register, interaction @@ -304,13 +304,13 @@ % general -\unexpanded\def\setupnumfont {} -\unexpanded\def\setuptxtfont {} -\unexpanded\def\setupintfont {\WORD} -\unexpanded\def\setupvarfont {\sl} -\unexpanded\def\setupoptfont {\sl} -\unexpanded\def\setupalwcolor {} -\unexpanded\def\setupoptcolor {darkgray} +\unexpanded\def\setupnumfont {} +\unexpanded\def\setuptxtfont {} +\unexpanded\def\setupintfont {\WORD} +\unexpanded\def\setupvarfont {\sl} +\unexpanded\def\setupoptfont {\sl} +\unexpanded\def\setupalwcolor{} +\unexpanded\def\setupoptcolor{darkgray} \def\c!setup!definereserved#1#2% {\setvalue{c!setup!:r:#1}{#2}} @@ -394,6 +394,7 @@ \stopxmlsetups \startxmlsetups xml:setups:basics + \xmlinclude{#1}{include}{filename}% \xmlsetsetup {#1} { sequence|string|variable|assignments|keywords|content|displaymath|index|math| nothing|file|position|reference|csname|destination|triplet|word| @@ -415,7 +416,7 @@ {\doonlyonce{setups:#1} {\doglobal\prependtocommalist{setups:#1}\loadedsetups % last overloads first \xmlloadonly{setups:#1}{#1}{setups}% - \xmlfilter{setups:#1}{/interface/command/command(xml:setups:register)}}}} % qualified path saves > 50% runtime + \xmlfilter{setups:#1}{interface/command/command(xml:setups:register)}}}} % qualified path saves > 50% runtime \newif\ifshortsetup @@ -444,10 +445,10 @@ \showsetupindeed{#1}} % \def\showsetupindeed#1% -% {\xmlfilterlist{\loadedsetups}{/interface/command[@name='#1']/command(xml:setups:typeset)}} +% {\xmlfilterlist{\loadedsetups}{interface/command[@name='#1']/command(xml:setups:typeset)}} \def\showsetupindeed#1% - {\xmlfilterlist{\loadedsetups}{/interface/command['#1' == (@type=='environment' and 'start' or '') .. @name]/command(xml:setups:typeset)}} + {\xmlfilterlist{\loadedsetups}{interface/command['#1' == (@type=='environment' and 'start' or '') .. @name]/command(xml:setups:typeset)}} \unexpanded\def\placesetup {\placelistofsorts[texcommand][\c!criterium=\v!used]} \unexpanded\def\placeallsetups{\placelistofsorts[texcommand][\c!criterium=\v!all ]} @@ -475,6 +476,7 @@ \doglobal\newcounter\currentSETUPargument \xdef\maximumSETUPargument{\xmlcount{#1}{/arguments/*}} \bgroup + \enablemode[setups-pass-one]% \doif {\xmlatt{#1}{generated}} {yes} { \ttsl } @@ -496,6 +498,7 @@ } \doif {\xmlatt{#1}{type}} {environment} { \bgroup + \enablemode[setups-pass-one]% \hskip.5em\unknown\hskip.5em \doif {\xmlatt{#1}{generated}} {yes} { \ttsl @@ -526,7 +529,7 @@ \startxmlsetups xml:setups:resolve \ignorespaces - \xmlfilterlist{\loadedsetups}{/interface/define[@name='\xmlatt{#1}{name}']/first()} + \xmlfilterlist{\loadedsetups}{interface/define[@name='\xmlatt{#1}{name}']/first()} \stopxmlsetups %D This is the first pass; here we generate the top line. diff --git a/tex/context/base/x-set-12.mkiv b/tex/context/base/x-set-12.mkiv index d79901433..d95aff4a3 100644 --- a/tex/context/base/x-set-12.mkiv +++ b/tex/context/base/x-set-12.mkiv @@ -87,34 +87,32 @@ [\hbox to \paperwidth{\reuseMPgraphic{cover+back}\hss}] \startreusableMPgraphic{cover+back} - numeric h, w ; path p, q, r ; color f, d ; pair s ; - h := OverlayHeight ; w := 2*OverlayWidth ; - r := unitsquare xyscaled (w,h) ; - fill r withcolor \MPcolor{lightgray} ; - set_grid(w,h,w/8,w/16) ; - forever : - s := center r randomized (w,h) ; - if new_on_grid(xpart s, ypart s) : - s := (dx,dy) ; - p := fullsquare xyscaled(w/4,w/8) ; - q := (-4w,ypart ulcorner p) -- - .5[ulcorner p, urcorner p] -- - (4w,ypart urcorner p) ; - q := q shifted (0,-w/24) ; - p := p randomized (w/40,w/40) ; - q := q randomized (0,w/100) ; - q := q cutafter (p cutafter point 3 of p) ; - q := q cutbefore (p cutbefore point 3 of p) ; - d := .5[\MPcolor{LocalColor},\MPcolor{lightgray}] randomized (.5,.9) ; - f := \MPcolor{lightgray} randomized (.5,.9) ; - pickup pencircle scaled (w/100) ; - fill p shifted s withcolor f ; - draw p shifted s withcolor d ; - draw q shifted s withcolor d ; - fi ; - exitif grid_full ; - endfor ; - setbounds currentpicture to r ; + numeric h, w ; path p, q, r ; color f, d ; pair s ; + h := OverlayHeight ; w := 2*OverlayWidth ; + r := unitsquare xyscaled (w,h) ; + fill r withcolor \MPcolor{lightgray} ; + set_grid(w,h,w/8,w/16) ; + forever : + s := center r randomized (w,h) ; + if new_on_grid(xpart s, ypart s) : + s := (dx,dy) ; + p := fullsquare xyscaled(w/4,w/8) ; + q := (-4w,ypart ulcorner p) -- .5[ulcorner p, urcorner p] -- (4w,ypart urcorner p) ; + q := q shifted (0,-w/24) ; + p := p randomized (w/40,w/40) ; + q := q randomized (0,w/100) ; + q := q cutafter (p cutafter point 3 of p) ; + q := q cutbefore (p cutbefore point 3 of p) ; + d := .5[\MPcolor{LocalColor},\MPcolor{lightgray}] randomized (.5,.9) ; + f := \MPcolor{lightgray} randomized (.5,.9) ; + pickup pencircle scaled (w/100) ; + fill p shifted s withcolor f ; + draw p shifted s withcolor d ; + draw q shifted s withcolor d ; + fi ; + exitif grid_full ; + endfor ; + setbounds currentpicture to r ; \stopreusableMPgraphic \definelayout @@ -143,7 +141,9 @@ \setupframedtexts [setuptext] - [\c!frame=\v!on, + [\c!before=\blank, + \c!after=\blank, + \c!frame=\v!on, \c!rulethickness=1pt, \c!framecolor=TitleColor] @@ -161,47 +161,47 @@ [titlepage] \startsetups text:commands - \startinterface dutch \strut commando's \par \stopinterface - \startinterface english \strut commands \par \stopinterface - \startinterface german \strut befehle \par \stopinterface - \startinterface french \strut commandes \par \stopinterface - \startinterface czech \strut p\v{r}ikazy \par \stopinterface - \startinterface italian \strut comandi \par \stopinterface - \startinterface romanian \strut comenzile \par \stopinterface + \startinterface dutch \strut commando's \par \stopinterface + \startinterface english \strut commands \par \stopinterface + \startinterface german \strut befehle \par \stopinterface + \startinterface french \strut commandes \par \stopinterface + \startinterface czech \strut p\v{r}ikazy \par \stopinterface + \startinterface italian \strut comandi \par \stopinterface + \startinterface romanian \strut comenzile \par \stopinterface \stopsetups \startsetups text:uppercase - \startinterface dutch NL\stopinterface - \startinterface english EN\stopinterface - \startinterface german DE\stopinterface - \startinterface french FR\stopinterface - \startinterface czech CS\stopinterface - \startinterface italian IT\stopinterface - \startinterface romanian RO\stopinterface + \startinterface dutch NL\stopinterface + \startinterface english EN\stopinterface + \startinterface german DE\stopinterface + \startinterface french FR\stopinterface + \startinterface czech CS\stopinterface + \startinterface italian IT\stopinterface + \startinterface romanian RO\stopinterface \stopsetups \startsetups text:lowercase - \startinterface dutch \strut nl / nederlands \par \stopinterface - \startinterface english \strut en / english \par \stopinterface - \startinterface german \strut de / deutsch \par \stopinterface - \startinterface french \strut fr / fran\c{c}ais \par \stopinterface - \startinterface czech \strut cs / \v{c}esk\'y \par \stopinterface - \startinterface italian \strut it / italiano \par \stopinterface - \startinterface romanian \strut ro / rom\^{a}n\u{a} \par \stopinterface + \startinterface dutch \strut nl / nederlands \par \stopinterface + \startinterface english \strut en / english \par \stopinterface + \startinterface german \strut de / deutsch \par \stopinterface + \startinterface french \strut fr / fran\c{c}ais \par \stopinterface + \startinterface czech \strut cs / \v{c}esk\'y \par \stopinterface + \startinterface italian \strut it / italiano \par \stopinterface + \startinterface romanian \strut ro / rom\^{a}n\u{a} \par \stopinterface \stopsetups \startmakeup[\v!standard] - \dontcomplain - \setupalign[\v!left] - \startcolor[TitleColor] - \definedfont[RegularBold at 100pt]\setstrut - \strut Con\TeX t \par - \definedfont[RegularBold at 50pt]\setstrut - \setups[text:commands] - \vfill - \definedfont[RegularBold at 150pt]\setstrut - \setups[text:uppercase] - \stopcolor + \dontcomplain + \setupalign[\v!left] + \startcolor[TitleColor] + \definedfont[RegularBold at 100pt]\setstrut + \strut Con\TeX t \par + \definedfont[RegularBold at 50pt]\setstrut + \setups[text:commands] + \vfill + \definedfont[RegularBold at 150pt]\setstrut + \setups[text:uppercase] + \stopcolor \stopmakeup \setuplayout % needed ? @@ -211,18 +211,18 @@ [\c!background=] \startmakeup[\v!standard] - \dontcomplain - \startcolor[TitleColor] - \definedfont[RegularBold at 100pt]\setstrut - \setupalign[\v!left] - \strut Con\TeX t \par - \definedfont[RegularBold at 50pt]\setstrut - \setups[text:commands] - \vfill - \definedfont[RegularBold at 24pt]\setupinterlinespace - \setups[text:lowercase] - \par \strut \currentdate \par - \stopcolor + \dontcomplain + \startcolor[TitleColor] + \definedfont[RegularBold at 100pt]\setstrut + \setupalign[\v!left] + \strut Con\TeX t \par + \definedfont[RegularBold at 50pt]\setstrut + \setups[text:commands] + \vfill + \definedfont[RegularBold at 24pt]\setupinterlinespace + \setups[text:lowercase] + \par \strut \currentdate \par + \stopcolor \stopmakeup \protect @@ -241,16 +241,16 @@ [\c!background=back] \startmakeup[\v!standard][\c!page=] - \dontcomplain - \startcolor[TitleColor] - \definedfont[RegularBold at 24pt]\setupinterlinespace - \setupalign[\v!left] - \vfill - PRAGMA ADE \par - Ridderstraat 27 \par - 8061GH Hasselt NL \par - www.pragma-ade.com \par - \stopcolor + \dontcomplain + \startcolor[TitleColor] + \definedfont[RegularBold at 24pt]\setupinterlinespace + \setupalign[\v!left] + \vfill + PRAGMA ADE \par + Ridderstraat 27 \par + 8061GH Hasselt NL \par + www.pragma-ade.com \par + \stopcolor \stopmakeup \protect diff --git a/tex/generic/context/luatex-basics-gen.lua b/tex/generic/context/luatex-basics-gen.lua index df5e7e6c4..ad12daa4e 100644 --- a/tex/generic/context/luatex-basics-gen.lua +++ b/tex/generic/context/luatex-basics-gen.lua @@ -218,3 +218,9 @@ function caches.savedata(path,name,data) table.tofile(fullname,data,'return',false,true,false) end end + +-- + +local table.setmetatableindex(t,f) + setmetatable(t,{ __index = f }) +end diff --git a/tex/generic/context/luatex-fonts-demo-vf-1.lua b/tex/generic/context/luatex-fonts-demo-vf-1.lua index b9f2a2c76..3878ae648 100644 --- a/tex/generic/context/luatex-fonts-demo-vf-1.lua +++ b/tex/generic/context/luatex-fonts-demo-vf-1.lua @@ -5,8 +5,8 @@ return function(specification) local f2, id2 = fonts.constructors.readanddefine('lmsans10-regular', specification.size) local f3, id3 = fonts.constructors.readanddefine('lmtypewriter10-regular',specification.size) if f1 and f2 and f3 then - f1.name = specification.name - f1.virtualized = true + f1.properties.name = specification.name + f1.properties.virtualized = true f1.fonts = { { id = id1 }, { id = id2 }, diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua index b1c147c96..3c6391e92 100644 --- a/tex/generic/context/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 04/03/11 22:32:45 +-- merge date : 04/11/11 16:45:23 do -- begin closure to overcome local limits and interference @@ -1079,10 +1079,6 @@ function table.fromhash(t) return hsh end -table.serialize_functions = true -table.serialize_compact = true -table.serialize_inline = true - local noquotes, hexify, handle, reduce, compact, inline, functions local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key @@ -1368,15 +1364,36 @@ end -- replacing handle by a direct t[#t+1] = ... (plus test) is not much -- faster (0.03 on 1.00 for zapfino.tma) -local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) - noquotes = _noquotes - hexify = _hexify - handle = _handle or print - reduce = _reduce or false - compact = table.serialize_compact - inline = compact and table.serialize_inline - functions = table.serialize_functions +local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) -- I might drop the _'s some day. local tname = type(name) + if tname == "table" then + noquotes = name.noquotes + hexify = name.hexify + handle = name.handle or print + reduce = name.reduce or false + functions = name.functions + compact = name.compact + inline = name.inline and compact + name = name.name + tname = type(name) + if functions == nil then + functions = true + end + if compact == nil then + compact = true + end + if inline == nil then + inline = compact + end + else + noquotes = _noquotes + hexify = _hexify + handle = _handle or print + reduce = _reduce or false + compact = true + inline = true + functions = true + end if tname == "string" then if name == "return" then handle("return {") @@ -1443,12 +1460,11 @@ end -- -- so this is on the todo list -table.tofile_maxtab = 2*1024 +local maxtab = 2*1024 function table.tofile(filename,root,name,reduce,noquotes,hexify) local f = io.open(filename,'w') if f then - local maxtab = table.tofile_maxtab if maxtab > 1 then local t, n = { }, 0 local function flush(s) @@ -1666,8 +1682,12 @@ function table.sequenced(t,sep,simple) -- hash only return concat(s, sep or " | ") end -function table.print(...) - table.tohandle(print,...) +function table.print(t,...) + if type(t) ~= "table" then + print(tostring(t)) + else + table.tohandle(print,t,...) + end end -- -- -- obsolete but we keep them for a while and might comment them later -- -- -- @@ -1947,8 +1967,6 @@ function file.collapsepath(str,anchor) end end -file.collapse_path = file.collapsepath - --~ local function test(str) --~ print(string.format("%-20s %-15s %-15s",str,file.collapsepath(str),file.collapsepath(str,true))) --~ end @@ -2585,6 +2603,12 @@ function caches.savedata(path,name,data) end end +-- + +local table.setmetatableindex(t,f) + setmetatable(t,{ __index = f }) +end + end -- closure do -- begin closure to overcome local limits and interference @@ -2883,13 +2907,11 @@ if not modules then modules = { } end modules ['font-con'] = { local utf = unicode.utf8 -local next, tostring, setmetatable, rawget = next, tostring, setmetatable, rawget +local next, tostring, rawget = next, tostring, rawget local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub local utfbyte = utf.byte local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy -local allocate = utilities.storage.allocate - local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end) @@ -2911,6 +2933,9 @@ local specifiers = fonts.specifiers local contextsetups = specifiers.contextsetups local contextnumbers = specifiers.contextnumbers +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + -- will be directives constructors.dontembed = allocate() @@ -3544,7 +3569,7 @@ function constructors.finalize(tfmdata) -- if not tfmdata.descriptions then local descriptions = { } -- yes or no - setmetatable(descriptions, { __index = function(t,k) local v = { } t[k] = v return v end }) + setmetatableindex(descriptions, function(t,k) local v = { } t[k] = v return v end) tfmdata.descriptions = descriptions end -- @@ -3742,16 +3767,14 @@ end local formats = allocate() fonts.formats = formats -setmetatable(formats, { - __index = function(t,k) - local l = lower(k) - if rawget(t,k) then - t[k] = l - return l - end - return rawget(t,file.extname(l)) +setmetatableindex(formats, function(t,k) + local l = lower(k) + if rawget(t,k) then + t[k] = l + return l end -} ) + return rawget(t,file.extname(l)) +end) local locations = { } @@ -3851,7 +3874,7 @@ function constructors.newfeatures(what) local features = handlers[what].features if not features then local tables = handlers[what].tables -- can be preloaded - features = { + features = allocate { defaults = { }, descriptions = tables and tables.features or { }, initializers = { base = { }, node = { } }, @@ -4777,7 +4800,7 @@ local otf = fonts.handlers.otf otf.glists = { "gsub", "gpos" } -otf.version = 2.721 -- beware: also sync font-mis.lua +otf.version = 2.722 -- beware: also sync font-mis.lua otf.cache = containers.define("fonts", "otf", otf.version, true) local fontdata = fonts.hashes.identifiers @@ -5902,13 +5925,55 @@ end -- to be checked italic_correction +local function check_variants(unicode,the_variants,splitter,unicodes) + local variants = the_variants.variants + if variants then -- use splitter + local glyphs = lpegmatch(splitter,variants) + local done = { [unicode] = true } + local n = 0 + for i=1,#glyphs do + local g = glyphs[i] + if done[g] then + report_otf("skipping cyclic reference U+%05X in math variant U+%05X",g,unicode) + elseif n == 0 then + n = 1 + variants = { g } + else + n = n + 1 + variants[n] = g + end + end + if n == 0 then + variants = nil + end + end + local parts = the_variants.parts + if parts then + local p = #parts + if p > 0 then + for i=1,p do + local pi = parts[i] + pi.glyph = unicodes[pi.component] or 0 + pi.component = nil + end + else + parts = nil + end + end + local italic_correction = the_variants.italic_correction + if italic_correction and italic_correction == 0 then + italic_correction = nil + end + return variants, parts, italic_correction +end + actions["analyze math"] = function(data,filename,raw) if raw.math then data.metadata.math = raw.math local unicodes = data.resources.unicodes local splitter = data.helpers.tounicodetable for unicode, description in next, data.descriptions do - local glyph = description.glyph + local glyph = description.glyph local mathkerns = glyph.mathkern -- singular local horiz_variants = glyph.horiz_variants local vert_variants = glyph.vert_variants @@ -5933,56 +5998,10 @@ actions["analyze math"] = function(data,filename,raw) math.kerns = mathkerns end if horiz_variants then - local variants = horiz_variants.variants - if variants then -- use splitter - local glyphs = lpegmatch(splitter,variants) - for i=1,#glyphs do - if glyphs[i] == u then - remove(glyphs,i) - break - end - end - math.horiz_variants = glyphs - end - local parts = horiz_variants.parts - if parts and #parts > 0 then - for i=1,#parts do - local pi = parts[i] - pi.glyph = unicodes[pi.component] or 0 - pi.component = nil - end - math.horiz_parts = parts - end - local italic_correction = horiz_variants.italic_correction - if italic_correction and italic_correction ~= 0 then - math.horiz_italic_correction = italic_correction - end + math.horiz_variants, math.horiz_parts, math.horiz_italic_correction = check_variants(unicode,horiz_variants,splitter,unicodes) end if vert_variants then - local variants = vert_variants.variants - if variants then - local glyphs = lpegmatch(splitter,variants) - for i=1,#glyphs do - if glyphs[i] == u then - remove(glyphs,i) - break - end - end - math.vert_variants = glyphs - end - local p = vert_variants.parts - if parts and #parts > 0 then - for i=1,#parts do - local pi = parts[i] - pi.glyph = unicodes[pi.component] or 0 - pi.component = nil - end - math.vert_parts = parts - end - local italic_correction = vert_variants.italic_correction - if italic_correction and italic_correction ~= 0 then - math.vert_italic_correction = italic_correction - end + math.vert_variants, math.vert_parts, math.vert_italic_correction = check_variants(unicode,vert_variants,splitter,unicodes) end local italic_correction = description.italic if italic_correction and italic_correction ~= 0 then @@ -6340,25 +6359,39 @@ local function copytotfm(data,cache_id) local m = d.math if m then -- watch out: luatex uses horiz_variants for the parts - local variants, parts = m.horiz_variants, m.horiz_parts + local variants = m.horiz_variants + local parts = m.horiz_parts + -- local done = { [unicode] = true } if variants then local c = character for i=1,#variants do local un = variants[i] - c.next = un - c = characters[un] + -- if done[un] then + -- -- report_otf("skipping cyclic reference U+%05X in math variant U+%05X",un,unicode) + -- else + c.next = un + c = characters[un] + -- done[un] = true + -- end end -- c is now last in chain c.horiz_variants = parts elseif parts then character.horiz_variants = parts end - local variants, parts = m.vert_variants, m.vert_parts + local variants = m.vert_variants + local parts = m.vert_parts + -- local done = { [unicode] = true } if variants then local c = character for i=1,#variants do local un = variants[i] - c.next = un - c = characters[un] + -- if done[un] then + -- -- report_otf("skipping cyclic reference U+%05X in math variant U+%05X",un,unicode) + -- else + c.next = un + c = characters[un] + -- done[un] = true + -- end end -- c is now last in chain c.vert_variants = parts elseif parts then @@ -7852,6 +7885,8 @@ local find_node_tail = node.tail or node.slide local set_attribute = node.set_attribute local has_attribute = node.has_attribute +local setmetatableindex = table.setmetatableindex + local zwnj = 0x200C local zwj = 0x200D local wildcard = "*" @@ -8148,7 +8183,7 @@ function handlers.gsub_multiple(start,kind,lookupname,multiple) return multiple_glyphs(start,multiple) end -function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or maybe pass lookup ref +function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) local s, stop, discfound = start.next, nil, false local startchar = start.char if marks[startchar] then @@ -8169,14 +8204,18 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma end if stop then local lig = ligature.ligature - if trace_ligatures then - local stopchar = stop.char - start = markstoligature(kind,lookupname,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + if lig then + if trace_ligatures then + local stopchar = stop.char + start = markstoligature(kind,lookupname,start,stop,lig) + logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + else + start = markstoligature(kind,lookupname,start,stop,lig) + end + return start, true else - start = markstoligature(kind,lookupname,start,stop,lig) + -- ok, goto next lookup end - return start, true end else local skipmark = sequence.flags[1] @@ -8209,14 +8248,18 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) --or ma end if stop then local lig = ligature.ligature - if trace_ligatures then - local stopchar = stop.char - start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + if lig then + if trace_ligatures then + local stopchar = stop.char + start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + else + start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + end + return start, true else - start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + -- ok, goto next lookup end - return start, true end end return start, false @@ -9529,16 +9572,14 @@ local resolved = { } -- we only resolve a font,script,language pair once local lookuphashes = { } -setmetatable(lookuphashes, { __index = - function(t,font) - local lookuphash = fontdata[font].resources.lookuphash - if not lookuphash or not next(lookuphash) then - lookuphash = false - end - t[font] = lookuphash - return lookuphash +setmetatableindex(lookuphashes, function(t,font) + local lookuphash = fontdata[font].resources.lookuphash + if not lookuphash or not next(lookuphash) then + lookuphash = false end -}) + t[font] = lookuphash + return lookuphash +end) -- fonts.hashes.lookups = lookuphashes @@ -9585,11 +9626,11 @@ function otf.dataset(ftfmdata,sequences,font) -- generic variant, overloaded in if not rl then rl = { } rs[language] = rl - setmetatable(rl, { __index = function(t,k) + setmetatableindex(rl, function(t,k) local v = enabled and initialize(sequences[k],script,language,enabled) t[k] = v return v - end}) + end) end return rl end @@ -10197,14 +10238,15 @@ if not trackers then trackers = { register = function() end } end local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) -local fonts, nodes = fonts, nodes -local node = node +local fonts, nodes, node = fonts, nodes, node + +local allocate = utilities.storage.allocate local otf = fonts.handlers.otf local analyzers = fonts.analyzers -local initializers = { } -local methods = { } +local initializers = allocate() +local methods = allocate() analyzers.initializers = initializers analyzers.methods = methods @@ -10987,18 +11029,17 @@ function definers.read(specification,size,id) -- id can be optional, name can al if not tfmdata then -- or id? report_defining( "unknown font %s, loading aborted",specification.name) elseif trace_defining and type(tfmdata) == "table" then - constructors.finalize(tfmdata) - -- local properties = tfmdata.properties or { } - -- local parameters = tfmdata.parameters or { } + local properties = tfmdata.properties or { } + local parameters = tfmdata.parameters or { } report_defining("using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s", - properties.type or "unknown", - id or "?", - properties.name or "?", - parameters.size or "default", - properties.encodingbytes or "?", - properties.encodingname or "unicode", - properties.fullname or "?", - file.basename(properties.filename or "?")) + properties.type or "unknown", + id or "?", + properties.name or "?", + parameters.size or "default", + properties.encodingbytes or "?", + properties.encodingname or "unicode", + properties.fullname or "?", + file.basename(properties.filename or "?")) end statistics.stoptiming(fonts) return tfmdata @@ -11008,7 +11049,7 @@ end

We overload the reader.

--ldx]]-- -callbacks.register('define_font' , definers.read, "definition of fonts (tfmdata preparation)") +callbacks.register('define_font', definers.read, "definition of fonts (tfmdata preparation)") end -- closure diff --git a/tex/generic/context/luatex-test.tex b/tex/generic/context/luatex-test.tex index 9f57cfea9..1c3aeb1b6 100644 --- a/tex/generic/context/luatex-test.tex +++ b/tex/generic/context/luatex-test.tex @@ -52,4 +52,8 @@ \mine \input tufte \par + +% \font\mine=file:luatex-fonts-demo-vf-2.lua at 12pt \mine [abab] \par +% \font\mine=file:luatex-fonts-demo-vf-3.lua at 12pt \mine [abab] \par + \end -- cgit v1.2.3