diff options
25 files changed, 837 insertions, 1071 deletions
diff --git a/doc/context/documents/general/manuals/languages-mkiv.pdf b/doc/context/documents/general/manuals/languages-mkiv.pdf Binary files differindex e9c9ba4d9..026acfca5 100644 --- a/doc/context/documents/general/manuals/languages-mkiv.pdf +++ b/doc/context/documents/general/manuals/languages-mkiv.pdf diff --git a/doc/context/documents/general/manuals/luatex.pdf b/doc/context/documents/general/manuals/luatex.pdf Binary files differindex a5abb8c9b..8c20ea3ca 100644 --- a/doc/context/documents/general/manuals/luatex.pdf +++ b/doc/context/documents/general/manuals/luatex.pdf diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex c696a2842..53d2e6dff 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua index 3042ea4a0..1c5b12c13 100644 --- a/tex/context/base/mkiv/anch-pos.lua +++ b/tex/context/base/mkiv/anch-pos.lua @@ -35,7 +35,7 @@ local scanners = interfaces.scanners local commands = commands local context = context -local ctxnode = context.flushnode +local ctxnode = context.nodes.flush local tex = tex local texgetcount = tex.getcount diff --git a/tex/context/base/mkiv/cldf-bas.lua b/tex/context/base/mkiv/cldf-bas.lua index 311816022..2387793c8 100644 --- a/tex/context/base/mkiv/cldf-bas.lua +++ b/tex/context/base/mkiv/cldf-bas.lua @@ -162,5 +162,5 @@ context.registers = { newtoks = function(name) return allocate(name,"toks") end, newbox = function(name) return allocate(name,"box","mathchar") end, -- not really a register but kind of belongs here - chardef = function(name,u) context([[\chardef\%s=%s\relax]],name,u) end, + newchar = function(name,u) context([[\chardef\%s=%s\relax]],name,u) end, } diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua index 3816e7755..3d8671149 100644 --- a/tex/context/base/mkiv/cldf-ini.lua +++ b/tex/context/base/mkiv/cldf-ini.lua @@ -6,42 +6,38 @@ if not modules then modules = { } end modules ['cldf-ini'] = { license = "see context related readme files" } --- also see cldf-tod.* ! --- old code moved to cldf-old.lua - --- maybe: --- --- 0.528 local foo = tex.ctxcatcodes --- 0.651 local foo = getcount("ctxcatcodes") --- 0.408 local foo = getcount(ctxcatcodes) -- local ctxcatcodes = tex.iscount("ctxcatcodes") - --- maybe (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔) - -- This started as an experiment: generating context code at the lua end. After all -- it is surprisingly simple to implement due to metatables. I was wondering if -- there was a more natural way to deal with commands at the lua end. Of course it's -- a bit slower but often more readable when mixed with lua code. It can also be handy -- when generating documents from databases or when constructing large tables or so. -- --- maybe optional checking against interface --- currently no coroutine trickery --- we could always use prtcatcodes (context.a_b_c) but then we loose protection --- tflush needs checking ... sort of weird that it's not a table +-- In cldf-tod.lua I have some code that might end up here. In cldf-old.lua the +-- code that precedes more modern solutions (made possible by features in the engine), +-- most noticeably function handling, which worked well for a decade, but by now the +-- more efficient approach is stable enough to move the original code to the obsolete +-- module. -- --- tex.print == line with endlinechar appended - --- todo: context("%bold{total: }%s",total) --- todo: context.documentvariable("title") +-- to be considered: +-- +-- 0.528 local foo = tex.ctxcatcodes +-- 0.651 local foo = getcount("ctxcatcodes") +-- 0.408 local foo = getcount(ctxcatcodes) -- local ctxcatcodes = tex.iscount("ctxcatcodes") +-- maybe: (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔) +-- note : tex.print == line with endlinechar appended +-- todo : context("%bold{total: }%s",total) +-- todo : context.documentvariable("title") +-- -- during the crited project we ran into the situation that luajittex was 10-20 times -- slower that luatex ... after 3 days of testing and probing we finally figured out that -- the the differences between the lua and luajit hashers can lead to quite a slowdown -- in some cases. - +-- -- context(lpeg.match(lpeg.patterns.texescape,"${}")) -- context(string.formatters["%!tex!"]("${}")) -- context("%!tex!","${}") - +-- -- We try not to polute the context namespace too much. For that reason the commands are -- registered in the context.core namespace. You can call all context commands using -- context.foo etc. and pipe to context with context("foo"). Defining a local command @@ -52,11 +48,19 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- ones in critical places (no one will notice of course). The standard syntax highlighter -- that I use knows how to visualize ctx related code. +-- I cleaned this code up a bit when updating the cld manual but got distracted a bit by +-- watching Trio Hiromi Uehara, Anthony Jackson & Simon Phillips (discovered via the +-- later on YT). Hopefully the video breaks made the following better in the end. + local format, stripstring = string.format, string.strip -local next, type, tostring, tonumber, setmetatable, unpack, select, rawset = next, type, tostring, tonumber, setmetatable, unpack, select, rawset +local next, type, tostring, tonumber, unpack, select, rawset = next, type, tostring, tonumber, unpack, select, rawset local insert, remove, concat = table.insert, table.remove, table.concat local lpegmatch, lpegC, lpegS, lpegP, lpegV, lpegCc, lpegCs, patterns = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.V, lpeg.Cc, lpeg.Cs, lpeg.patterns -local formatters = string.formatters -- using formatters is slower in this case + +local formatters = string.formatters -- using formatters is slower in this case +local setmetatableindex = table.setmetatableindex +local setmetatablecall = table.setmetatablecall +local setmetatablenewindex = table.setmetatablenewindex context = context or { } commands = commands or { } @@ -96,342 +100,226 @@ local flushdirect = texprint -- lines local report_context = logs.reporter("cld","tex") local report_cld = logs.reporter("cld","stack") +local report_template = logs.reporter("cld","template") local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end) -- In earlier experiments a function tables was referred to as lua.calls and the --- primitive \luafunctions was \luacall. +-- primitive \luafunctions was \luacall and we used our own implementation of +-- a function table (more indirectness). -local luafunctions = lua.get_functions_table and lua.get_functions_table() -local usedstack = nil +local knownfunctions = lua.get_functions_table() local showstackusage = false --- luafunctions = false - trackers.register("context.stack",function(v) showstackusage = v end) -local storefunction, flushfunction -local storenode, flushnode -local registerfunction, unregisterfunction, reservefunction, knownfunctions, callfunctiononce +local freed, nofused, noffreed = { }, 0, 0 -- maybe use the number of @@trialtypesetting --- if luafunctions then - - local freed, nofused, noffreed = { }, 0, 0 -- maybe use the number of @@trialtypesetting +local usedstack = function() + return nofused, noffreed +end - usedstack = function() - return nofused, noffreed +local flushfunction = function(slot,arg) + if arg() then + -- keep + elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! + noffreed = noffreed + 1 + freed[noffreed] = slot + knownfunctions[slot] = false + else + -- keep end +end - flushfunction = function(slot,arg) - if arg() then - -- keep - elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! - noffreed = noffreed + 1 - freed[noffreed] = slot - luafunctions[slot] = false - else - -- keep - end +local storefunction = function(arg) + local f = function(slot) flushfunction(slot,arg) end + if noffreed > 0 then + local n = freed[noffreed] + freed[noffreed] = nil + noffreed = noffreed - 1 + knownfunctions[n] = f + return n + else + nofused = nofused + 1 + knownfunctions[nofused] = f + return nofused end +end - storefunction = function(arg) - local f = function(slot) flushfunction(slot,arg) end - if noffreed > 0 then - local n = freed[noffreed] - freed[noffreed] = nil - noffreed = noffreed - 1 - luafunctions[n] = f - return n - else - nofused = nofused + 1 - luafunctions[nofused] = f - return nofused - end +local flushnode = function(slot,arg) + if texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! + writenode(arg) + noffreed = noffreed + 1 + freed[noffreed] = slot + knownfunctions[slot] = false + else + writenode(copynodelist(arg)) end +end - flushnode = function(slot,arg) - if texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! - writenode(arg) - noffreed = noffreed + 1 - freed[noffreed] = slot - luafunctions[slot] = false - else - writenode(copynodelist(arg)) - end +local storenode = function(arg) + local f = function(slot) flushnode(slot,arg) end + if noffreed > 0 then + local n = freed[noffreed] + freed[noffreed] = nil + noffreed = noffreed - 1 + knownfunctions[n] = f + return n + else + nofused = nofused + 1 + knownfunctions[nofused] = f + return nofused end +end - storenode = function(arg) - local f = function(slot) flushnode(slot,arg) end - if noffreed > 0 then - local n = freed[noffreed] - freed[noffreed] = nil - noffreed = noffreed - 1 - luafunctions[n] = f - return n - else - nofused = nofused + 1 - luafunctions[nofused] = f - return nofused - end - end +storage.storedfunctions = storage.storedfunctions or { } +local storedfunctions = storage.storedfunctions +local initex = environment.initex - -- registerfunction = function(f) - -- if type(f) == "string" then - -- f = loadstring(f) - -- end - -- if type(f) ~= "function" then - -- f = function() report_cld("invalid function %A",f) end - -- end - -- if noffreed > 0 then - -- local n = freed[noffreed] - -- freed[noffreed] = nil - -- noffreed = noffreed - 1 - -- luafunctions[n] = f - -- return n - -- else - -- nofused = nofused + 1 - -- luafunctions[nofused] = f - -- return nofused - -- end - -- end - - storage.storedfunctions = storage.storedfunctions or { } - local storedfunctions = storage.storedfunctions - local initex = environment.initex - - storage.register("storage/storedfunctions", storedfunctions, "storage.storedfunctions") - - local f_resolve = nil - local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1 - - local function resolvestoredfunction(str) - f_resolve = global - lpegmatch(p_resolve,str) - return f_resolve - end - - local function expose(slot,f,...) -- so we can register yet undefined functions - local func = resolvestoredfunction(f) - if not func then - func = function() report_cld("beware: unknown function %i called: %s",slot,f) end - end - luafunctions[slot] = func - return func(...) +storage.register("storage/storedfunctions", storedfunctions, "storage.storedfunctions") + +local f_resolve = nil +local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1 + +local function resolvestoredfunction(str) + f_resolve = global + lpegmatch(p_resolve,str) + return f_resolve +end + +local function expose(slot,f,...) -- so we can register yet undefined functions + local func = resolvestoredfunction(f) + if not func then + func = function() report_cld("beware: unknown function %i called: %s",slot,f) end end + knownfunctions[slot] = func + return func(...) +end - if initex then - -- todo: log stored functions - else - local slots = table.sortedkeys(storedfunctions) - local last = #slots - if last > 0 then - -- we restore the references - for i=1,last do - local slot = slots[i] - local data = storedfunctions[slot] - luafunctions[slot] = function(...) - -- print(data) -- could be trace - return expose(slot,data,...) - end +if initex then + -- todo: log stored functions +else + local slots = table.sortedkeys(storedfunctions) + local last = #slots + if last > 0 then + -- we restore the references + for i=1,last do + local slot = slots[i] + local data = storedfunctions[slot] + knownfunctions[slot] = function(...) + -- print(data) -- could be trace + return expose(slot,data,...) end - -- we now know how many are defined - nofused = slots[last] - -- normally there are no holes in the list yet - for i=1,nofused do - if not luafunctions[i] then - noffreed = noffreed + 1 - freed[noffreed] = i - end + end + -- we now know how many are defined + nofused = slots[last] + -- normally there are no holes in the list yet + for i=1,nofused do + if not knownfunctions[i] then + noffreed = noffreed + 1 + freed[noffreed] = i end - -- report_cld("%s registered functions, %s freed slots",last,noffreed) end + -- report_cld("%s registered functions, %s freed slots",last,noffreed) end +end - registerfunction = function(f,direct) -- either f=code or f=namespace,direct=name - local slot, func - if noffreed > 0 then - slot = freed[noffreed] - freed[noffreed] = nil - noffreed = noffreed - 1 - else - nofused = nofused + 1 - slot = nofused - end - if direct then - if initex then - func = function(...) - expose(slot,f,...) - end - if initex then - storedfunctions[slot] = f - end - else - func = resolvestoredfunction(f) - end - if type(func) ~= "function" then - func = function() report_cld("invalid resolve %A",f) end +local registerfunction = function(f,direct) -- either f=code or f=namespace,direct=name + local slot, func + if noffreed > 0 then + slot = freed[noffreed] + freed[noffreed] = nil + noffreed = noffreed - 1 + else + nofused = nofused + 1 + slot = nofused + end + if direct then + if initex then + func = function(...) + expose(slot,f,...) end - elseif type(f) == "string" then - func = loadstring(f) - if type(func) ~= "function" then - func = function() report_cld("invalid code %A",f) end + if initex then + storedfunctions[slot] = f end - elseif type(f) == "function" then - func = f else - func = function() report_cld("invalid function %A",f) end + func = resolvestoredfunction(f) end - luafunctions[slot] = func - return slot - end - - unregisterfunction = function(slot) - if luafunctions[slot] then - noffreed = noffreed + 1 - freed[noffreed] = slot - luafunctions[slot] = false - else - report_cld("invalid function slot %A",slot) + if type(func) ~= "function" then + func = function() report_cld("invalid resolve %A",f) end end - end - - reservefunction = function() - if noffreed > 0 then - local n = freed[noffreed] - freed[noffreed] = nil - noffreed = noffreed - 1 - return n - else - nofused = nofused + 1 - return nofused + elseif type(f) == "string" then + func = loadstring(f) + if type(func) ~= "function" then + func = function() report_cld("invalid code %A",f) end end + elseif type(f) == "function" then + func = f + else + func = function() report_cld("invalid function %A",f) end end + knownfunctions[slot] = func + return slot +end - callfunctiononce = function(slot) - luafunctions[slot](slot) +local unregisterfunction = function(slot) + if knownfunctions[slot] then noffreed = noffreed + 1 freed[noffreed] = slot - luafunctions[slot] = false + knownfunctions[slot] = false + else + report_cld("invalid function slot %A",slot) end +end - table.setmetatablecall(luafunctions,function(t,n) return luafunctions[n](n) end) +local reservefunction = function() + if noffreed > 0 then + local n = freed[noffreed] + freed[noffreed] = nil + noffreed = noffreed - 1 + return n + else + nofused = nofused + 1 + return nofused + end +end - knownfunctions = luafunctions +local callfunctiononce = function(slot) + knownfunctions[slot](slot) + noffreed = noffreed + 1 + freed[noffreed] = slot + knownfunctions[slot] = false +end - -- The next hack is a convenient way to define scanners at the Lua end and - -- get them available at the TeX end. There is some dirty magic needed to - -- prevent overload during format loading. +setmetatablecall(knownfunctions,function(t,n) return knownfunctions[n](n) end) - -- interfaces.scanners.foo = function() context("[%s]",tokens.scanners.string()) end : \scan_foo +-- The next hack is a convenient way to define scanners at the Lua end and +-- get them available at the TeX end. There is some dirty magic needed to +-- prevent overload during format loading. - interfaces.storedscanners = interfaces.storedscanners or { } - local storedscanners = interfaces.storedscanners +-- interfaces.scanners.foo = function() context("[%s]",tokens.scanners.string()) end : \scan_foo - storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners") +interfaces.storedscanners = interfaces.storedscanners or { } +local storedscanners = interfaces.storedscanners - local interfacescanners = table.setmetatablenewindex(function(t,k,v) - if storedscanners[k] then - -- report_cld("warning: scanner %a is already set",k) - -- os.exit() - -- \scan_<k> is already in the format - -- report_cld("using interface scanner: %s",k) - else - -- todo: allocate slot here and pass it - storedscanners[k] = true - -- report_cld("installing interface scanner: %s",k) - context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k) - end - rawset(t,k,v) - end) +storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners") - interfaces.scanners = interfacescanners +local interfacescanners = setmetatablenewindex(function(t,k,v) + if storedscanners[k] then + -- report_cld("warning: scanner %a is already set",k) + -- os.exit() + -- \scan_<k> is already in the format + -- report_cld("using interface scanner: %s",k) + else + -- todo: allocate slot here and pass it + storedscanners[k] = true + -- report_cld("installing interface scanner: %s",k) + context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k) + end + rawset(t,k,v) +end) --- else -- by now this is obsolete --- --- local luafunctions, noffunctions = { }, 0 --- local luanodes, nofnodes = { }, 0 --- --- usedstack = function() --- return noffunctions + nofnodes, 0 --- end --- --- flushfunction = function(n) --- local sn = luafunctions[n] --- if not sn then --- report_cld("data with id %a cannot be found on stack",n) --- elseif not sn() and texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! --- luafunctions[n] = nil --- end --- end --- --- storefunction = function(ti) --- noffunctions = noffunctions + 1 --- luafunctions[noffunctions] = ti --- return noffunctions --- end --- --- -- freefunction = function(n) --- -- luafunctions[n] = nil --- -- end --- --- flushnode = function(n) --- local sn = luanodes[n] --- if not sn then --- report_cld("data with id %a cannot be found on stack",n) --- elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! --- writenode(sn) --- luanodes[n] = nil --- else --- writenode(copynodelist(sn)) --- end --- end --- --- storenode = function(ti) --- nofnodes = nofnodes + 1 --- luanodes[nofnodes] = ti --- return nofnodes --- end --- --- _cldf_ = flushfunction -- global --- _cldn_ = flushnode -- global --- -- _cldl_ = function(n) return luafunctions[n]() end -- luafunctions(n) --- _cldl_ = luafunctions --- --- registerfunction = function(f) --- if type(f) == "string" then --- f = loadstring(f) --- end --- if type(f) ~= "function" then --- f = function() report_cld("invalid function %A",f) end --- end --- noffunctions = noffunctions + 1 --- luafunctions[noffunctions] = f --- return noffunctions --- end --- --- unregisterfunction = function(slot) --- if luafunctions[slot] then --- luafunctions[slot] = nil --- else --- report_cld("invalid function slot %A",slot) --- end --- end --- --- reservefunction = function() --- noffunctions = noffunctions + 1 --- return noffunctions --- end --- --- callfunctiononce = function(slot) --- luafunctions[slot](slot) --- luafunctions[slot] = nil --- end --- --- table.setmetatablecall(luafunctions,function(t,n) return luafunctions[n](n) end) --- --- knownfunctions = luafunctions --- --- end +interfaces.scanners = interfacescanners context.functions = { register = registerfunction, @@ -441,8 +329,6 @@ context.functions = { callonce = callfunctiononce, } -context.storenode = storenode -- private helper - function commands.ctxfunction(code,namespace) context(registerfunction(code,namespace)) end @@ -515,6 +401,27 @@ local function popcatcodes() contentcatcodes = currentcatcodes end +function context.unprotect() + -- at the lua end + catcodelevel = catcodelevel + 1 + catcodestack[catcodelevel] = currentcatcodes + currentcatcodes = prtcatcodes + contentcatcodes = prtcatcodes + -- at the tex end + flush("\\unprotect") +end + +function context.protect() + -- at the tex end + flush("\\protect") + -- at the lua end + if catcodelevel > 0 then + currentcatcodes = catcodestack[catcodelevel] or currentcatcodes + catcodelevel = catcodelevel - 1 + end + contentcatcodes = currentcatcodes +end + context.catcodes = catcodes context.pushcatcodes = pushcatcodes context.popcatcodes = popcatcodes @@ -560,7 +467,7 @@ local n_exception = "" -- better a table specification -function context.newtexthandler(specification) -- can also be used for verbose +function context.newtexthandler(specification) specification = specification or { } -- local s_catcodes = specification.catcodes @@ -816,127 +723,32 @@ end -- if performance really matters we can consider a compiler but it will never -- pay off -local function prtwriter(command,...) -- already optimized before call - flush(prtcatcodes,command) - for i=1,select("#",...) do - local ti = (select(i,...)) - if ti == nil then - -- nothing - elseif ti == "" then - flush(prtcatcodes,"{}") - else - local tp = type(ti) - if tp == "string" or tp == "number"then - flush(prtcatcodes,"{",ti,"}") - elseif tp == "function" then - flush(prtcatcodes,"{\\cldl ",storefunction(ti),"}") - -- flush(currentcatcodes,"{",storefunction(ti),"}") -- todo: ctx|prt|texcatcodes - elseif isnode(ti) then - flush(prtcatcodes,"{\\cldl",storenode(ti),"}") - -- flush(currentcatcodes,"{",storenode(ti),"}") - else - report_context("fatal error: prt %a gets a weird argument %a",command,ti) - end - end - end -end +-- local function prtwriter(command,...) -- already optimized before call +-- flush(prtcatcodes,command) +-- for i=1,select("#",...) do +-- local ti = (select(i,...)) +-- if ti == nil then +-- -- nothing +-- elseif ti == "" then +-- flush(prtcatcodes,"{}") +-- else +-- local tp = type(ti) +-- if tp == "string" or tp == "number"then +-- flush(prtcatcodes,"{",ti,"}") +-- elseif tp == "function" then +-- flush(prtcatcodes,"{\\cldl ",storefunction(ti),"}") +-- -- flush(currentcatcodes,"{",storefunction(ti),"}") -- todo: ctx|prt|texcatcodes +-- elseif isnode(ti) then +-- flush(prtcatcodes,"{\\cldl",storenode(ti),"}") +-- -- flush(currentcatcodes,"{",storenode(ti),"}") +-- else +-- report_context("fatal error: prt %a gets a weird argument %a",command,ti) +-- end +-- end +-- end +-- end --- Originally we used this: --- --- writer = function (parent,command,first,...) -- already optimized before call --- local t = { first, ... } --- flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes --- local direct = false --- for i=1,#t do --- local ti = t[i] --- local typ = type(ti) --- if direct then --- if typ == "string" or typ == "number" then --- flush(currentcatcodes,ti) --- else -- node.write --- report_context("error: invalid use of direct in %a, only strings and numbers can be flushed directly, not %a",command,typ) --- end --- direct = false --- elseif ti == nil then --- -- nothing --- elseif ti == "" then --- flush(currentcatcodes,"{}") --- elseif typ == "string" then --- -- is processelines seen ? --- if processlines and lpegmatch(containseol,ti) then --- flush(currentcatcodes,"{") --- flushlines(ti) --- flush(currentcatcodes,"}") --- elseif currentcatcodes == contentcatcodes then --- flush(currentcatcodes,"{",ti,"}") --- else --- flush(currentcatcodes,"{") --- flush(contentcatcodes,ti) --- flush(currentcatcodes,"}") --- end --- elseif typ == "number" then --- -- numbers never have funny catcodes --- flush(currentcatcodes,"{",ti,"}") --- elseif typ == "table" then --- local tn = #ti --- if tn == 0 then --- local done = false --- for k, v in next, ti do --- if done then --- if v == "" then --- flush(currentcatcodes,",",k,'=') --- else --- flush(currentcatcodes,",",k,"={",v,"}") --- end --- else --- if v == "" then --- flush(currentcatcodes,"[",k,"=") --- else --- flush(currentcatcodes,"[",k,"={",v,"}") --- end --- done = true --- end --- end --- if done then --- flush(currentcatcodes,"]") --- else --- flush(currentcatcodes,"[]") --- end --- elseif tn == 1 then -- some 20% faster than the next loop --- local tj = ti[1] --- if type(tj) == "function" then --- flush(currentcatcodes,"[\\cldf{",storefunction(tj),"}]") --- else --- flush(currentcatcodes,"[",tj,"]") --- end --- else -- is concat really faster than flushes here? probably needed anyway (print artifacts) --- for j=1,tn do --- local tj = ti[j] --- if type(tj) == "function" then --- ti[j] = "\\cldf{" .. storefunction(tj) .. "}" --- end --- end --- flush(currentcatcodes,"[",concat(ti,","),"]") --- end --- elseif typ == "function" then --- flush(currentcatcodes,"{\\cldf{",storefunction(ti),"}}") -- todo: ctx|prt|texcatcodes --- elseif typ == "boolean" then --- if ti then --- flushdirect(currentcatcodes,"\r") --- else --- direct = true --- end --- elseif typ == "thread" then --- report_context("coroutines not supported as we cannot yield across boundaries") --- elseif isnode(ti) then -- slow --- flush(currentcatcodes,"{\\cldn{",storenode(ti),"}}") --- else --- report_context("error: %a gets a weird argument %a",command,ti) --- end --- end --- end - -local core = table.setmetatableindex(function(parent,k) +local core = setmetatableindex(function(parent,k) local c = "\\" .. k -- tostring(k) local f = function(first,...) if first == nil then @@ -949,6 +761,15 @@ local core = table.setmetatableindex(function(parent,k) return f end) +core.cs = setmetatableindex(function(parent,k) + local c = "\\" .. k -- tostring(k) + local f = function() + flush(currentcatcodes,c) + end + parent[k] = f + return f +end) + local indexer = function(parent,k) if type(k) == "string" then return core[k] @@ -959,107 +780,60 @@ end context.core = core --- can only be done in non-ini mode so we'd have a bad mix and tracing --- is bad too, so we just keep it as commented +-- only for internal usage: + +-- local prtindexer = nil -- --- local create = token.create --- local twrite = token.write +-- do -- --- indexer = function(parent,k) --- if type(k) == "string" then --- local t = create(k) --- if t.cmdname == "undefined_cs" then --- report_cld("macro \\%s is not yet defined",k) --- token.set_macro(k,"") --- t = create(k) --- end --- local i = t.id --- local f = function(first,...) --- twrite(t.tok) --= we need to keep t uncollected --- if first ~= nil then --- return writer(parent,first,...) +-- -- the only variant is not much faster than the full but it's more +-- -- memory efficient +-- +-- local protected = { } +-- local protectedcs = { } +-- context.protected = protected +-- context.protectedcs = protectedcs +-- +-- local function fullindexer(t,k) +-- local c = "\\" .. k -- tostring(k) +-- local v = function(first,...) +-- if first == nil then +-- flush(prtcatcodes,c) +-- else +-- return prtwriter(c,first,...) -- end -- end --- parent[k] = f --- return f --- else --- return context -- catch +-- rawset(t,k,v) -- protected namespace +-- return v -- end --- end - --- Potential optimization: after the first call we know if there will be an --- argument. Of course there is the side effect that for instance abuse like --- context.NC(str) fails as well as optional arguments. So, we don't do this --- in practice. We just keep the next trick commented. The gain on some --- 100000 calls is not that large: 0.100 => 0.95 which is neglectable. -- --- local function constructor(parent,k,c,first,...) --- if first == nil then --- local f = function() --- flush(currentcatcodes,c) --- end --- parent[k] = f --- return f() --- else --- local f = function(...) --- return writer(parent,c,...) +-- local function onlyindexer(t,k) +-- local c = "\\" .. k -- tostring(k) +-- local v = function() +-- flush(prtcatcodes,c) -- end --- parent[k] = f --- return f(first,...) +-- rawset(protected,k,v) +-- rawset(t,k,v) +-- return v -- end --- end -- --- local function indexer(parent,k) --- local c = "\\" .. k -- tostring(k) --- local f = function(...) --- return constructor(parent,k,c,...) +-- protected.cs = setmetatableindex(function(parent,k) +-- local c = "\\" .. k -- tostring(k) +-- local v = function() +-- flush(prtcatcodes,c) +-- end +-- parent[k] = v +-- return v -- end --- parent[k] = f --- return f +-- +-- setmetatableindex(protected,fullindexer) +-- setmetatablecall (protected,prtwriter) +-- +-- setmetatableindex(protectedcs,onlyindexer) +-- setmetatablecall (protectedcs,prtwriter) +-- -- end --- only for internal usage: - -local prtindexer = nil - -do - - -- the only variant is not much faster than the full but it's more - -- memory efficient - - local protected = { } - local protectedcs = { } - context.protected = protected - context.protectedcs = protectedcs - - local function fullindexer(t,k) - local c = "\\" .. k -- tostring(k) - local v = function(first,...) - if first == nil then - flush(prtcatcodes,c) - else - return prtwriter(c,first,...) - end - end - rawset(t,k,v) -- protected namespace - return v - end - - local function onlyindexer(t,k) - local c = "\\" .. k -- tostring(k) - local v = function() - flush(prtcatcodes,c) - end - rawset(protected,k,v) - rawset(t,k,v) - return v - end - - setmetatable(protected, { __index = fullindexer, __call = prtwriter } ) - setmetatable(protectedcs, { __index = onlyindexer, __call = prtwriter } ) - -end - -- local splitformatters = utilities.strings.formatters.new(true) -- not faster (yet) local caller = function(parent,f,a,...) @@ -1118,106 +892,29 @@ local caller = function(parent,f,a,...) end end -function context.flushnode(n) - flush(currentcatcodes,"\\cldl",storenode(n)," ") - -- flush(currentcatcodes,"",storenode(n)," ") -end - --- old code, from the early days: --- --- caller = function(parent,f,a,...) --- if not parent then --- -- so we don't need to test in the calling (slower but often no issue) --- elseif f ~= nil then --- local typ = type(f) --- if typ == "string" then --- if f == "" then --- -- new, can save a bit sometimes --- -- if trace_context then --- -- report_context("empty argument to context()") --- -- end --- elseif a then --- flush(contentcatcodes,formatters[f](a,...)) -- was currentcatcodes --- -- flush(contentcatcodes,splitformatters[f](a,...)) -- was currentcatcodes --- elseif processlines and lpegmatch(containseol,f) then --- flushlines(f) --- else --- flush(contentcatcodes,f) --- end --- elseif typ == "number" then --- if a then --- flush(currentcatcodes,f,a,...) --- else --- flush(currentcatcodes,f) --- end --- elseif typ == "function" then --- -- ignored: a ... --- flush(currentcatcodes,"{\\cldf{",storefunction(f),"}}") -- todo: ctx|prt|texcatcodes --- elseif typ == "boolean" then --- if f then --- if a ~= nil then --- flushlines(a) --- else --- flushdirect(currentcatcodes,"\n") -- no \r, else issues with \startlines ... use context.par() otherwise --- end --- else --- if a ~= nil then --- -- no command, same as context(a,...) --- writer(parent,"",a,...) --- else --- -- ignored --- end --- end --- elseif typ == "thread" then --- report_context("coroutines not supported as we cannot yield across boundaries") --- elseif isnode(f) then -- slow --- -- writenode(f) --- flush(currentcatcodes,"\\cldn{",storenode(f),"}") --- else --- report_context("error: %a gets a weird argument %a","context",f) --- end --- end --- end --- --- function context.flushnode(n) --- flush(currentcatcodes,"\\cldn{",storenode(n),"}") --- end +context.nodes = { + store = storenode, + flush = function(n) + flush(currentcatcodes,"\\cldl",storenode(n)," ") + -- flush(currentcatcodes,"",storenode(n)," ") + end, +} local defaultcaller = caller -setmetatable(context, { __index = indexer, __call = caller } ) - --- now we tweak unprotect and protect - --- context.call = caller -- somehow fails - -function context.unprotect() - -- at the lua end - insert(catcodestack,currentcatcodes) - currentcatcodes = prtcatcodes - contentcatcodes = currentcatcodes - -- at the tex end - flush("\\unprotect") -end - -function context.protect() - -- at the tex end - flush("\\protect") - -- at the lua end - currentcatcodes = remove(catcodestack) or currentcatcodes - contentcatcodes = currentcatcodes -end +setmetatableindex(context,indexer) +setmetatablecall (context,caller) function context.sprint(...) -- takes catcodes as first argument flush(...) end -function context.fprint(catcodes,fmt,first,...) +function context.fprint(fmt,first,...) if type(catcodes) == "number" then if first then - flush(catcodes,formatters[fmt](first,...)) + flush(currentcatcodes,formatters[fmt](first,...)) else - flush(catcodes,fmt) + flush(currentcatcodes,fmt) end else if fmt then @@ -1228,23 +925,17 @@ function context.fprint(catcodes,fmt,first,...) end end -function tex.fprint(fmt,first,...) -- goodie - if first then - flush(currentcatcodes,formatters[fmt](first,...)) - else - flush(currentcatcodes,fmt) - end -end +tex.fprint = context.fprint -- logging -local trace_stack = { } +local trace_stack = { report_context } local normalflush = flush local normalflushdirect = flushdirect ----- normalflushraw = flushraw local normalwriter = writer -local currenttrace = nil +local currenttrace = report_context local nofwriters = 0 local nofflushes = 0 @@ -1352,68 +1043,39 @@ local tracedflushdirect = function(one,two,...) end end -local function pushlogger(trace) +function context.pushlogger(trace) trace = trace or report_context insert(trace_stack,currenttrace) currenttrace = trace - flush = tracedflush - flushdirect = tracedflushdirect - writer = tracedwriter - return flush, writer, flushdirect end -local function poplogger() - currenttrace = remove(trace_stack) - if not currenttrace then - flush = normalflush - flushdirect = normalflushdirect - writer = normalwriter +function context.poplogger() + if #trace_stack > 1 then + currenttrace = remove(trace_stack) or report_context + else + currenttrace = report_context end - return flush, writer, flushdirect end -local function settracing(v) +function context.settracing(v) if v then - return pushlogger(report_context) + flush = tracedflush + flushdirect = tracedflushdirect + writer = tracedwriter else - return poplogger() + flush = normalflush + flushdirect = normalflushdirect + writer = normalwriter end + return flush, writer, flushdirect end --- todo: share flushers so that we can define in other files - -trackers.register("context.trace",settracing) - -context.pushlogger = pushlogger -context.poplogger = poplogger -context.settracing = settracing - --- -- untested, no time now: --- --- local tracestack, tracestacktop = { }, false --- --- function context.pushtracing(v) --- insert(tracestack,tracestacktop) --- if type(v) == "function" then --- pushlogger(v) --- v = true --- else --- pushlogger() --- end --- tracestacktop = v --- settracing(v) --- end --- --- function context.poptracing() --- poplogger() --- tracestacktop = remove(tracestack) or false --- settracing(tracestacktop) --- end - function context.getlogger() - return flush, writer, flush_direct + return flush, writer, flushdirect end +trackers.register("context.trace",context.settracing) + local trace_cld = false trackers.register("context.files", function(v) trace_cld = v end) do @@ -1481,13 +1143,14 @@ do function context.stopcollecting() level = level - 1 if level < 1 then + local result = concat(collected,sentinel) flush = normalflush flushdirect = normalflushdirect tracingpermitted = permitted - viafile(concat(collected,sentinel)) collected = nil nofcollected = 0 level = 0 + viafile(result) end end @@ -1531,71 +1194,84 @@ end -- context.delayed (todo: lines) -local delayed = { } context.delayed = delayed -- creates function (maybe also store them) +do + + local delayed = { } + + local function indexer(parent,k) + local f = function(...) + local a = { ... } + return function() + -- return context[k](unpack(a)) + return core[k](unpack(a)) + end + end + parent[k] = f + return f + end -local function indexer(parent,k) - local f = function(...) + local function caller(parent,...) -- todo: nodes local a = { ... } return function() - -- return context[k](unpack(a)) - return core[k](unpack(a)) + -- return context(unpack(a)) + return defaultcaller(context,unpack(a)) end end - parent[k] = f - return f -end -local function caller(parent,...) -- todo: nodes - local a = { ... } - return function() - -- return context(unpack(a)) - return defaultcaller(context,unpack(a)) - end + setmetatableindex(delayed,indexer) + setmetatablecall (delayed,caller) + + context.delayed = delayed + end -setmetatable(delayed, { __index = indexer, __call = caller } ) +do + + -- context.nested (todo: lines), creates strings --- context.nested (todo: lines) + local nested = { } -local nested = { } context.nested = nested -- creates strings + local function indexer(parent,k) -- not ok when traced + local f = function(...) + local t, savedflush, n = { }, flush, 0 + flush = function(c,f,s,...) -- catcodes are ignored + n = n + 1 + t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 + end + -- context[k](...) + core[k](...) + flush = savedflush + return concat(t) + end + parent[k] = f + return f + end -local function indexer(parent,k) -- not ok when traced - local f = function(...) + local function caller(parent,...) local t, savedflush, n = { }, flush, 0 flush = function(c,f,s,...) -- catcodes are ignored n = n + 1 t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 end - -- context[k](...) - core[k](...) + -- context(...) + defaultcaller(context,...) flush = savedflush return concat(t) end - parent[k] = f - return f -end -local function caller(parent,...) - local t, savedflush, n = { }, flush, 0 - flush = function(c,f,s,...) -- catcodes are ignored - n = n + 1 - t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 - end - -- context(...) - defaultcaller(context,...) - flush = savedflush - return concat(t) -end + setmetatableindex(nested,indexer) + setmetatablecall (nested,caller) -setmetatable(nested, { __index = indexer, __call = caller } ) + context.nested = nested + +end -- verbatim -function context.newindexer(catcodes) +function context.newindexer(catcodes,cmdcodes) local handler = { } local function indexer(parent,k) - -- local command = context[k] local command = core[k] local f = function(...) local savedcatcodes = contentcatcodes @@ -1614,238 +1290,253 @@ function context.newindexer(catcodes) contentcatcodes = savedcatcodes end - setmetatable(handler, { __index = indexer, __call = caller } ) + handler.cs = setmetatableindex(function(parent,k) + local c = "\\" .. k -- tostring(k) + local f = function() + flush(cmdcodes,c) + end + parent[k] = f + return f + end) + + setmetatableindex(handler,indexer) + setmetatablecall (handler,caller) return handler end -context.verbatim = context.newindexer(vrbcatcodes) -context.puretext = context.newindexer(txtcatcodes) --------.protected = context.newindexer(prtcatcodes) +context.verbatim = context.newindexer(vrbcatcodes,ctxcatcodes) +context.puretext = context.newindexer(txtcatcodes,ctxcatcodes) +context.protected = context.newindexer(prtcatcodes,prtcatcodes) -- formatted -local formatted = { } context.formatted = formatted +do + + local formatted = { } --- local function indexer(parent,k) --- local command = context[k] --- local f = function(fmt,...) --- command(formatters[fmt](...)) --- end --- parent[k] = f --- return f --- end + -- formatted.command([catcodes,]format[,...]) -local function indexer(parent,k) - if type(k) == "string" then - local c = "\\" .. k - local f = function(first,second,...) - if first == nil then - flush(currentcatcodes,c) - elseif second then - return writer(parent,c,formatters[first](second,...)) + local function formattedflush(parent,c,catcodes,fmt,...) + if type(catcodes) == "number" then + if fmt then + local result + pushcatcodes(catcodes) + result = writer(parent,c,formatters[fmt](...)) + popcatcodes() + return result else - return writer(parent,c,first) + -- no need to change content catcodes + return writer(parent,c) end + else + return writer(parent,c,formatters[catcodes](fmt,...)) end - parent[k] = f - return f - else - return context -- catch end -end - --- local function caller(parent,...) --- context.fprint(...) --- end -local function caller(parent,catcodes,fmt,first,...) - if type(catcodes) == "number" then - if first then - flush(catcodes,formatters[fmt](first,...)) + local function indexer(parent,k) + if type(k) == "string" then + local c = "\\" .. k + local f = function(first,...) + if first == nil then + flush(currentcatcodes,c) + else + return formattedflush(parent,c,first,...) + end + end + parent[k] = f + return f else - flush(catcodes,fmt) + return context -- catch end - else - if fmt then - flush(formatters[catcodes](fmt,first,...)) + end + + -- formatted([catcodes,]format[,...]) + + local function caller(parent,catcodes,fmt,...) + if not catcodes then + -- nothing + elseif type(catcodes) == "number" then + if fmt then + flush(catcodes,formatters[fmt](...)) + end else - flush(catcodes) + flush(formatters[catcodes](fmt,...)) end end + + setmetatableindex(formatted,indexer) + setmetatablecall (formatted,caller) + + context.formatted = formatted + end -setmetatable(formatted, { __index = indexer, __call = caller } ) +do --- metafun (this will move to another file) + -- metafun (this will move to another file) -local metafun = { } context.metafun = metafun + local metafun = { } -local mpdrawing = "\\MPdrawing" + function metafun.start() + context.startMPcode() + end -local function caller(parent,f,a,...) - if not parent then - -- skip - elseif f then - local typ = type(f) - if typ == "string" then - if a then - flush(currentcatcodes,mpdrawing,"{",formatters[f](a,...),"}") - else - flush(currentcatcodes,mpdrawing,"{",f,"}") - end - elseif typ == "number" then - if a then - flush(currentcatcodes,mpdrawing,"{",f,a,...,"}") - else - flush(currentcatcodes,mpdrawing,"{",f,"}") - end - elseif typ == "function" then - -- ignored: a ... - flush(currentcatcodes,mpdrawing,"{\\cldl",store_(f),"}") - -- flush(currentcatcodes,mpdrawing,"{",store_(f),"}") - elseif typ == "boolean" then - -- ignored: a ... - if f then - flush(currentcatcodes,mpdrawing,"{^^M}") - else - report_context("warning: %a gets argument 'false' which is currently unsupported","metafun") - end - else - report_context("error: %a gets a weird argument %a","metafun",tostring(f)) - end + function metafun.stop() + context.stopMPcode() end -end -setmetatable(metafun, { __call = caller } ) + setmetatablecall(metafun,defaultcaller) -function metafun.start() - context.resetMPdrawing() -end + function metafun.color(name) -- obsolete + return name -- formatters[ [[\MPcolor{%s}]] ](name) + end -function metafun.stop() - context.MPdrawingdonetrue() - context.getMPdrawing() -end + -- metafun.delayed -function metafun.color(name) - return formatters[ [[\MPcolor{%s}]] ](name) -end + local delayed = { } --- metafun.delayed + local function indexer(parent,k) + local f = function(...) + local a = { ... } + return function() + return metafun[k](unpack(a)) + end + end + parent[k] = f + return f + end -local delayed = { } metafun.delayed = delayed -local function indexer(parent,k) - local f = function(...) + local function caller(parent,...) local a = { ... } return function() - return metafun[k](unpack(a)) + return metafun(unpack(a)) end end - parent[k] = f - return f -end + setmetatableindex(delayed,indexer) + setmetatablecall (delayed,caller) -local function caller(parent,...) - local a = { ... } - return function() - return metafun(unpack(a)) - end -end + context.metafun = metafun + metafun.delayed = delayed -setmetatable(delayed, { __index = indexer, __call = caller } ) +end -- helpers: -function context.concat(...) - context(concat(...)) -end +do + + function context.concat(...) + context(concat(...)) + end + + local p_texescape = patterns.texescape + + function context.escaped(s) + return context(lpegmatch(p_texescape,s) or s) + end -local p_texescape = patterns.texescape + function context.escape(s) + return lpegmatch(p_texescape,s) or s or "" + end -function context.escaped(s) - return context(lpegmatch(p_texescape,s) or s) end -- templates -local single = lpegP("%") -local double = lpegP("%%") -local lquoted = lpegP("%[") -local rquoted = lpegP("]%") +do -local start = [[ -local texescape = lpeg.patterns.texescape -local lpegmatch = lpeg.match -return function(variables) return -]] + local single = lpegP("%") + local double = lpegP("%%") + local lquoted = lpegP("%[") + local rquoted = lpegP("]%") + local space = lpegP(" ") -local stop = [[ -end -]] - -local replacer = lpegP { "parser", - parser = lpegCs(lpegCc(start) * lpegV("step") * (lpegCc("..") * lpegV("step"))^0 * lpegCc(stop)), - unquoted = (lquoted/'') * ((lpegC((1-rquoted)^1)) / "lpegmatch(texescape,variables['%0'] or '')" ) * (rquoted/''), - escape = double/'%%', - key = (single/'') * ((lpegC((1-single)^1)) / "(variables['%0'] or '')" ) * (single/''), - step = lpegV("unquoted") - + lpegV("escape") - + lpegV("key") - + lpegCc("\n[===[") * (1 - lpegV("unquoted") - lpegV("escape") - lpegV("key"))^1 * lpegCc("]===]\n"), -} + local start = [[ + local texescape = lpeg.patterns.texescape + local lpegmatch = lpeg.match + return function(variables) return + ]] -local templates = { } + local stop = [[ + end + ]] + + local replacer = lpegP { "parser", + parser = lpegCs(lpegCc(start) * lpegV("step") * (lpegCc("..") * lpegV("step"))^0 * lpegCc(stop)), + unquoted = (lquoted*space/'') + * ((lpegC((1-space*rquoted)^1)) / "lpegmatch(texescape,variables%0 or '')" ) + * (space*rquoted/'') + + (lquoted/'') + * ((lpegC((1-rquoted)^1)) / "lpegmatch(texescape,variables['%0'] or '')" ) + * (rquoted/''), + key = (single*space/'') + * ((lpegC((1-space*single)^1)) / "(variables%0 or '')" ) + * (space*single/'') + + (single/'') + * ((lpegC((1-single)^1)) / "(variables['%0'] or '')" ) + * (single/''), + escape = double/'%%', + step = lpegV("unquoted") + + lpegV("escape") + + lpegV("key") + + lpegCc("\n[===[") * (1 - lpegV("unquoted") - lpegV("escape") - lpegV("key"))^1 * lpegCc("]===]\n"), + } + + local templates = { } -local function indexer(parent,k) - local v = lpegmatch(replacer,k) - if not v then - v = "error: no valid template (1)" - else - v = loadstring(v) - if type(v) ~= "function" then - v = "error: no valid template (2)" + local function indexer(parent,k) + local v = lpegmatch(replacer,k) + if not v then + -- report_template("invalid template:\n%s",k) + v = "error: no valid template (1)" else - v = v() - if not v then - v = "error: no valid template (3)" - end - end - end - if type(v) == "function" then - local f = function(first,second) - if second then - pushcatcodes(first) - flushlines(v(second)) - popcatcodes() + local f = loadstring(v) + if type(f) ~= "function" then + -- report_template("invalid template:\n%s\n=>\n%s",k,v) + v = "error: no valid template (2)" else - flushlines(v(first)) + f = f() + if not f then + -- report_template("invalid template:\n%s\n=>\n%s",k,v) + v = "error: no valid template (3)" + else + v = f + end end end - parent[k] = f - return f - else - return function() - flush(v) + if type(v) == "function" then + local f = function(first,second) + if second then + pushcatcodes(first) + flushlines(v(second)) + popcatcodes() + else + flushlines(v(first)) + end + end + parent[k] = f + return f + else + return function() + flush(v) + end end + end -end + local function caller(parent,k,...) + return parent[k](...) + end -local function caller(parent,k,...) - return parent[k](...) -end + setmetatableindex(templates,indexer) + setmetatablecall (templates,caller) -setmetatable(templates, { __index = indexer, __call = caller } ) + context.templates = templates -function context.template(template,...) - context(templates[template](...)) end -context.templates = templates - -- The above is a bit over the top as we could also stick to a simple context.replace -- which is fast enough anyway, but the above fits in nicer, also with the catcodes. -- diff --git a/tex/context/base/mkiv/cldf-stp.lua b/tex/context/base/mkiv/cldf-stp.lua index bd5b084ca..eeed47594 100644 --- a/tex/context/base/mkiv/cldf-stp.lua +++ b/tex/context/base/mkiv/cldf-stp.lua @@ -37,7 +37,7 @@ local stepper = nil local stack = { } -- will never be deep so no gc needed local depth = 0 -local nextstep = function() +local function nextstep() if status(stepper) == "dead" then stepper = stack[depth] depth = depth - 1 @@ -51,7 +51,7 @@ interfaces.implement { actions = nextstep, } -local ctx_resume = context.protectedcs.clf_step +local ctx_resume = context.protected.cs.clf_step function context.step(first,...) if first ~= nil then diff --git a/tex/context/base/mkiv/cldf-ver.lua b/tex/context/base/mkiv/cldf-ver.lua index 66432eb1c..3710b2415 100644 --- a/tex/context/base/mkiv/cldf-ver.lua +++ b/tex/context/base/mkiv/cldf-ver.lua @@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['cldf-ver'] = { -- better when used mixed with other code (synchronization issue). local concat, tohandle = table.concat, table.tohandle -local find, splitlines = string.find, string.splitlines +local splitlines, strip = string.splitlines, string.strip local tostring, type = tostring, type local context = context @@ -28,11 +28,15 @@ local function t_tocontext(...) context.popcatcodes() end -local function s_tocontext(...) -- we need to catch {\} +local function s_tocontext(first,...) -- we need to catch {\} context.type() context("{") context.pushcatcodes("verbatim") - context(concat({...}," ")) + if first then + context(first) -- no need to waste a { } + else + context(concat({first,...}," ")) + end context.popcatcodes() context("}") end @@ -44,34 +48,41 @@ end table .tocontext = t_tocontext string .tocontext = s_tocontext boolean.tocontext = b_tocontext +number .tocontext = s_tocontext + +local tocontext = { + ["string"] = s_tocontext, + ["table"] = t_tocontext, + ["boolean"] = b_tocontext, + ["number"] = s_tocontext, + ["function"] = function() s_tocontext("<function>") end, + ["nil"] = function() s_tocontext("<nil>") end, + -- ------------ = -------- can be extended elsewhere +} -function context.tocontext(first,...) - local t = type(first) - if t == "string" then - s_tocontext(first,...) - elseif t == "table" then - t_tocontext(first,...) - elseif t == "boolean" then - b_tocontext(first,...) +table.setmetatableindex(tocontext,function(t,k) + local v = function(s) + s_tocontext("<"..tostring(s)..">") end -end + t[k] = v + return v +end) + +table.setmetatablecall(tocontext,function(t,k,...) + tocontext[type(k)](k) +end) --- function context.tobuffer(name,str) --- context.startbuffer { name } --- context.pushcatcodes("verbatim") --- local lines = (type(str) == "string" and find(str,"[\n\r]") and splitlines(str)) or str --- for i=1,#lines do --- context(lines[i] .. " ") --- end --- context.stopbuffer() --- context.popcatcodes() --- end +context.tocontext = tocontext context.tobuffer = buffers.assign -- (name,str,catcodes) -function context.tolines(str) +function context.tolines(str,strip) local lines = type(str) == "string" and splitlines(str) or str for i=1,#lines do - context(lines[i] .. " ") + if strip then + context(strip(lines[i]) .. " ") + else + context(lines[i] .. " ") + end end end diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index fb4707e9e..2141b8616 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2016.07.23 13:35} +\newcontextversion{2016.07.25 17:40} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 1f773ada8..b3e58ad75 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -39,7 +39,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2016.07.23 13:35} +\edef\contextversion{2016.07.25 17:40} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/core-env.lua b/tex/context/base/mkiv/core-env.lua index 34220fedf..cd5439919 100644 --- a/tex/context/base/mkiv/core-env.lua +++ b/tex/context/base/mkiv/core-env.lua @@ -11,35 +11,38 @@ if not modules then modules = { } end modules ['core-env'] = { -- -- if tex.modes['xxxx'] then .... else .... end -local P, C, S, Cc, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.match, lpeg.patterns +local rawset = rawset -local context = context +local P, C, S, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.match, lpeg.patterns -local texgetcount = tex.getcount +local context = context +local ctxcore = context.core -local allocate = utilities.storage.allocate -local setmetatableindex = table.setmetatableindex -local setmetatablecall = table.setmetatablecall +local texgetcount = tex.getcount -local createtoken = token.create +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local setmetatablecall = table.setmetatablecall -tex.modes = allocate { } -tex.systemmodes = allocate { } -tex.constants = allocate { } -tex.conditionals = allocate { } -tex.ifs = allocate { } -tex.isdefined = allocate { } +local createtoken = token.create -local modes = { } -local systemmodes = { } +texmodes = allocate { } tex.modes = texmodes +texsystemmodes = allocate { } tex.systemmodes = texsystemmodes +texconstants = allocate { } tex.constants = texconstants +texconditionals = allocate { } tex.conditionals = texconditionals +texifs = allocate { } tex.ifs = texifs +texisdefined = allocate { } tex.isdefined = texisdefined + +local modes = { } +local systemmodes = { } -- we could use the built-in tex.is[count|dimen|skip|toks] here but caching -- at the lua en dis not that bad (and we need more anyway) -- undefined: mode == 0 or cmdname = "undefined_cs" - -local cache = table.setmetatableindex(function(t,k) +local cache = setmetatableindex(function(t,k) local v = createtoken(k) t[k] = v return v @@ -50,7 +53,7 @@ end) local iftrue = cache["iftrue"].mode local undefined = cache["*undefined*crap*"].mode -- is this ok? -setmetatableindex(tex.modes, function(t,k) +setmetatableindex(texmodes, function(t,k) local m = modes[k] if m then return m() @@ -59,13 +62,16 @@ setmetatableindex(tex.modes, function(t,k) if cache[n].mode == 0 then return false else - modes[k] = function() return texgetcount(n) == 1 end + rawset(modes,k, function() return texgetcount(n) == 1 end) return texgetcount(n) == 1 -- 2 is prevented end end end) +setmetatablenewindex(texmodes, function(t,k) + report_mode("you cannot set the %s named %a this way","mode",k) +end) -setmetatableindex(tex.systemmodes, function(t,k) +setmetatableindex(texsystemmodes, function(t,k) local m = systemmodes[k] if m then return m() @@ -74,37 +80,45 @@ setmetatableindex(tex.systemmodes, function(t,k) if cache[n].mode == 0 then return false else - systemmodes[k] = function() return texgetcount(n) == 1 end + rawset(systemmodes,k,function() return texgetcount(n) == 1 end) return texgetcount(n) == 1 -- 2 is prevented end end end) +setmetatablenewindex(texsystemmodes, function(t,k) + report_mode("you cannot set the %s named %a this way","systemmode",k) +end) -setmetatableindex(tex.constants, function(t,k) +setmetatableindex(texconstants, function(t,k) return cache[k].mode ~= 0 and texgetcount(k) or 0 end) +setmetatablenewindex(texconstants, function(t,k) + report_mode("you cannot set the %s named %a this way","constant",k) +end) -setmetatableindex(tex.conditionals, function(t,k) -- 0 == true +setmetatableindex(texconditionals, function(t,k) -- 0 == true return cache[k].mode ~= 0 and texgetcount(k) == 0 end) +setmetatablenewindex(texconditionals, function(t,k) + report_mode("you cannot set the %s named %a this way","conditional",k) +end) -table.setmetatableindex(tex.ifs, function(t,k) - -- local mode = cache[k].mode - -- if mode == 0 then - -- return nil - -- else - -- return mode == iftrue - -- end +table.setmetatableindex(texifs, function(t,k) return cache[k].mode == iftrue end) +setmetatablenewindex(texifs, function(t,k) + -- just ignore +end) -setmetatableindex(tex.isdefined, function(t,k) +setmetatableindex(texisdefined, function(t,k) return k and cache[k].mode ~= 0 end) - -setmetatablecall(tex.isdefined, function(t,k) +setmetatablecall(texisdefined, function(t,k) return k and cache[k].mode ~= 0 end) +setmetatablenewindex(texisdefined, function(t,k) + -- just ignore +end) local dimencode = cache["scratchdimen"] .command local countcode = cache["scratchcounter"] .command @@ -151,107 +165,35 @@ function tex.type(name) return types[cache[name].command] or "macro" end --- -- old token code --- --- local csname_id = token.csname_id --- local create = token.create --- --- local undefined = csname_id("*undefined*crap*") --- local iftrue = create("iftrue")[2] -- inefficient hack --- --- 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 --- modes[k] = function() return texgetcount(n) == 1 end --- return texgetcount(n) == 1 -- 2 is prevented --- end --- end --- end) --- --- 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 --- systemmodes[k] = function() return texgetcount(n) == 1 end --- return texgetcount(n) == 1 -- 2 is prevented --- end --- end --- end) --- --- setmetatableindex(tex.constants, function(t,k) --- return csname_id(k) ~= undefined and texgetcount(k) or 0 --- end) --- --- setmetatableindex(tex.conditionals, function(t,k) -- 0 == true --- return csname_id(k) ~= undefined and texgetcount(k) == 0 --- end) --- --- setmetatableindex(tex.ifs, function(t,k) --- -- k = "if" .. k -- better not --- return csname_id(k) ~= undefined and create(k)[2] == iftrue -- inefficient, this create, we need a helper --- end) --- --- setmetatableindex(tex.isdefined, function(t,k) --- return k and csname_id(k) ~= undefined --- end) --- setmetatablecall(tex.isdefined, function(t,k) --- return k and csname_id(k) ~= undefined --- end) --- --- local lookuptoken = token.lookup --- --- local dimencode = lookuptoken("scratchdimen" )[1] --- local countcode = lookuptoken("scratchcounter")[1] --- local tokencode = lookuptoken("scratchtoken" )[1] --- local skipcode = lookuptoken("scratchskip" )[1] --- --- local types = { --- [dimencode] = "dimen", --- [countcode] = "count", --- [tokencode] = "token", --- [skipcode ] = "skip", --- } --- --- function tex.isdimen(name) --- return lookuptoken(name)[1] == dimencode --- end --- --- function tex.iscount(name) --- return lookuptoken(name)[1] == countcode --- end --- --- function tex.istoken(name) --- return lookuptoken(name)[1] == tokencode --- end --- --- function tex.isskip(name) --- return lookuptoken(name)[1] == skipcode --- end --- --- function tex.type(name) --- return types[lookuptoken(name)[1]] or "macro" --- end - function context.setconditional(name,value) if value then - context.settruevalue(name) + ctxcore.settruevalue(name) + else + ctxcore.setfalsevalue(name) + end +end + +function context.setmode(name,value) + if value then + ctxcore.setmode(name) else - context.setfalsevalue(name) + ctxcore.resetmode(name) end end ----- arg = P("{") * C(patterns.nested) * P("}") + Cc("") +function context.setsystemmode(name,value) + if value then + ctxcore.setsystemmode(name) + else + ctxcore.resetsystemmode(name) + end +end + +context.modes = texmodes +context.systemmodes = texsystemmodes +context.conditionals = texconditionals +-------.constants = texconstants +-------.ifs = texifs local sep = S("), ") local str = C((1-sep)^1) @@ -259,9 +201,9 @@ local tag = P("(") * C((1-S(")" ))^1) * P(")") local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")") local pattern = ( - P("lua") * tag / context.luasetup - + P("xml") * arg / context.setupwithargument -- or xmlw as xmlsetup has swapped arguments - + (P("tex") * tag + str) / context.texsetup + P("lua") * tag / ctxcore.luasetup + + P("xml") * arg / ctxcore.setupwithargument -- or xmlw as xmlsetup has swapped arguments + + (P("tex") * tag + str) / ctxcore.texsetup + sep^1 )^1 @@ -270,4 +212,3 @@ interfaces.implement { actions = function(str) lpegmatch(pattern,str) end, arguments = "string" } - diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua index c11199178..de7592c87 100644 --- a/tex/context/base/mkiv/math-ini.lua +++ b/tex/context/base/mkiv/math-ini.lua @@ -25,7 +25,6 @@ local commands = commands local implement = interfaces.implement local ctx_sprint = context.sprint ------ ctx_fprint = context.fprint -- a bit inefficient local ctx_doifelsesomething = commands.doifelsesomething local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) diff --git a/tex/context/base/mkiv/node-ppt.lua b/tex/context/base/mkiv/node-ppt.lua index 0f7df2b6e..82acf2ff4 100644 --- a/tex/context/base/mkiv/node-ppt.lua +++ b/tex/context/base/mkiv/node-ppt.lua @@ -85,14 +85,13 @@ local function register(where,data,...) end local writenode = node.write -local flushnode = context.flushnode +local flushnode = context.nodes.flush function commands.deferredproperty(...) -- context(register(...)) flushnode(register(...)) end - function commands.immediateproperty(...) writenode(register(...)) end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex d13f9afa1..72504da84 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 9bcec69dd..111a82393 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-bkm.lua b/tex/context/base/mkiv/strc-bkm.lua index 9ec6734e8..e30a91820 100644 --- a/tex/context/base/mkiv/strc-bkm.lua +++ b/tex/context/base/mkiv/strc-bkm.lua @@ -112,11 +112,13 @@ end function bookmarks.place() if next(names) then - local levels = { } - local noflevels = 0 - local lastlevel = 1 - local nofblocks = #lists.sectionblocks -- always >= 1 + local levels = { } + local noflevels = 0 + local lastlevel = 1 + local nofblocks = #lists.sectionblocks -- always >= 1 local showblocktitle = toboolean(numberspec.showblocktitle,true) +-- local allsections = sections.collected + local allblocks = sections.sectionblockdata for i=1,nofblocks do local block = lists.sectionblocks[i] local blockdone = nofblocks == 1 @@ -155,9 +157,9 @@ function bookmarks.place() if not blockdone then if showblocktitle then -- add block entry - local blockdata = sections.sectionblockdata[block] - noflevels = noflevels + 1 + local blockdata = allblocks[block] local references = li.references + noflevels = noflevels + 1 levels[noflevels] = { level = 1, -- toplevel title = stripped(blockdata.bookmark ~= "" and blockdata.bookmark or block), @@ -184,19 +186,29 @@ function bookmarks.place() title = titledata.title or "?" -- end end - if numbered[name] then - local sectiondata = sections.collected[li.references.section] - local numberdata = li.numberdata - if sectiondata and numberdata then - if not numberdata.hidenumber then - -- we could typeset the number and convert it - local number = sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata) - if number and #number > 0 then - title = concat(number) .. " " .. title - end - end - end - end +-- if numbered[name] then +-- local sectiondata = allsections[li.references.section] +-- if sectiondata then +-- local numberdata = li.numberdata +-- if numberdata and not numberdata.hidenumber then +-- -- we could typeset the number and convert it +-- local number = sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata) +-- if number and #number > 0 then +-- title = concat(number) .. " " .. title +-- end +-- end +-- end +-- end +if numbered[name] then + local numberdata = li.numberdata + if numberdata and not numberdata.hidenumber then + -- we could typeset the number and convert it + local number = sections.typesetnumber(numberdata,"direct",numberspec,numberdata) + if number and #number > 0 then + title = concat(number) .. " " .. title + end + end +end noflevels = noflevels + 1 local references = li.references levels[noflevels] = { diff --git a/tex/context/base/mkiv/syst-lua.lua b/tex/context/base/mkiv/syst-lua.lua index d35a5111a..ee3b8c327 100644 --- a/tex/context/base/mkiv/syst-lua.lua +++ b/tex/context/base/mkiv/syst-lua.lua @@ -15,11 +15,11 @@ local commands = commands local context = context local implement = interfaces.implement -local protectedcs = context.protectedcs -- efficient -local ctx_firstoftwoarguments = protectedcs.firstoftwoarguments -local ctx_secondoftwoarguments = protectedcs.secondoftwoarguments -local ctx_firstofoneargument = protectedcs.firstofoneargument -local ctx_gobbleoneargument = protectedcs.gobbleoneargument +local ctx_protected_cs = context.protected.cs -- more efficient +local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments +local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments +local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument +local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument local two_strings = interfaces.strings[2] diff --git a/tex/context/base/mkiv/tabl-xtb.lua b/tex/context/base/mkiv/tabl-xtb.lua index f549d1cd6..674a0bf5a 100644 --- a/tex/context/base/mkiv/tabl-xtb.lua +++ b/tex/context/base/mkiv/tabl-xtb.lua @@ -30,7 +30,7 @@ local tonumber, next, rawget = tonumber, next, rawget local commands = commands local context = context -local ctxnode = context.flushnode +local ctxnode = context.nodes.flush local implement = interfaces.implement diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua index 93e6af7c2..bffb1807c 100644 --- a/tex/context/base/mkiv/trac-vis.lua +++ b/tex/context/base/mkiv/trac-vis.lua @@ -565,21 +565,21 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous,trace_o setattr(info,a_layer,layer) if vertical then if shift == 0 then - info = linked_nodes(current,info) + info = linked_nodes(current,dp ~= 0 and new_kern(-dp) or nil,info) elseif trace_origin then local size = 2*size local origin = o_cache[size] origin = copy_list(origin) if getid(parent) == vlist_code then setfield(origin,"shift",-shift) - info = linked_nodes(current,new_kern(-size),origin,new_kern(-size),info) + info = linked_nodes(current,new_kern(-size),origin,new_kern(-size-dp),info) else -- todo .. i need an example - info = linked_nodes(current,info) + info = linked_nodes(current,dp ~= 0 and new_kern(-dp) or nil,info) end setfield(current,"shift",0) else - info = linked_nodes(current,info) + info = linked_nodes(current,new_dp ~= 0 and new_kern(-dp) or nil,info) setfield(current,"shift",0) end info = new_vlist(info,wd,ht,dp,shift) diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex d62c1fc3f..4ff51c931 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex 8d9ab851e..9f71d5ece 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/context/modules/mkiv/s-characters-properties.lua b/tex/context/modules/mkiv/s-characters-properties.lua new file mode 100644 index 000000000..dc9fb8f93 --- /dev/null +++ b/tex/context/modules/mkiv/s-characters-properties.lua @@ -0,0 +1,83 @@ +if not modules then modules = { } end modules ['s-characters-properties'] = { + version = 1.001, + comment = "companion to s-characters-properties.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +moduledata.characters = moduledata.characters or { } +moduledata.characters.properties = moduledata.characters.properties or { } + +local catcodenames = { [0] = + "escape", "begingroup", "endgroup", "mathshift", + "alignment", "endofline", "parameter", "superscript", + "subscript", "ignore", "space", "letter", + "other", "active", "comment", "invalid", +} + +table.swapped(catcodes,catcodes) + +local catcodes = context.catcodes +local getcatcode = tex.getcatcode +local c_context = catcodes.context +local c_tex = catcodes.tex +local c_protect = catcodes.protect +local c_text = catcodes.text +local c_verbatim = catcodes.verbatim + +local context = context +local ctx_NC = context.NC +local ctx_NR = context.NR +local ctx_MR = context.MR +local ctx_ML = context.ML +local ctx_bold = context.bold +local ctx_verbatim = context.verbatim + +function moduledata.characters.properties.showcatcodes(specification) + + local function range(f,l,quit) + if quit then + ctx_MR() + end + for i=f,l do + ctx_NC() + if quit then + ctx_verbatim("%c .. %c",f,l) + else + ctx_verbatim("%c",i) + end + ctx_NC() context(catcodenames[getcatcode(c_tex,i)]) + ctx_NC() context(catcodenames[getcatcode(c_context,i)]) + ctx_NC() context(catcodenames[getcatcode(c_protect,i)]) + ctx_NC() context(catcodenames[getcatcode(c_text,i)]) + ctx_NC() context(catcodenames[getcatcode(c_verbatim,i)]) + ctx_NC() ctx_NR() + if quit then + ctx_MR() + break + end + end + end + + context.starttabulate { "|c|c|c|c|c|c|" } + ctx_ML() + ctx_NC() ctx_bold("ascii") + ctx_NC() ctx_bold("context") + ctx_NC() ctx_bold("tex") + ctx_NC() ctx_bold("protect") + ctx_NC() ctx_bold("text") + ctx_NC() ctx_bold("verbatim") + ctx_NC() ctx_NR() + ctx_ML() + range(32,47) + range(48,57,true) + range(58,64) + range(65,90,true) + range(91,96) + range(97,122,true) + range(123,126) + ctx_ML() + context.stoptabulate() + +end diff --git a/tex/context/modules/mkiv/s-characters-properties.mkiv b/tex/context/modules/mkiv/s-characters-properties.mkiv new file mode 100644 index 000000000..0beea4868 --- /dev/null +++ b/tex/context/modules/mkiv/s-characters-properties.mkiv @@ -0,0 +1,30 @@ +%D \module +%D [ file=s-characters-propertis, +%D version=2016.07.24, % moved here +%D title=\CONTEXT\ Style File, +%D subtitle=Character properties, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\startmodule[characters-properties] + +\registerctxluafile{s-characters-properties}{} + +\installmodulecommandluasingle \showcharactercatcodes {moduledata.characters.properties.showcatcodes} + +\stopmodule + +\continueifinputfile{s-characters-properties.mkiv} + +\usemodule[art-01] + +\starttext + + \showcharactercatcodes + +\stoptext diff --git a/tex/context/sample/common/khatt-en.tex b/tex/context/sample/common/khatt-en.tex index f994513e7..52891af25 100644 --- a/tex/context/sample/common/khatt-en.tex +++ b/tex/context/sample/common/khatt-en.tex @@ -1,4 +1,4 @@ -ʿAlī ibn Abī Ṭālib said to his scribe ʿUbaydullāh ibn Abī Rāfiʿ: -your inkwell before you, sharpen the edge of your pen, make sure +ʿAlī ibn Abī Ṭālib said to his scribe ʿUbaydullāh ibn Abī Rāfiʿ: Set +down your inkwell before you, sharpen the edge of your pen, make sure there is open space between the lines, and set your letter|-|spacing closely. Now {\em that} is the way to make the script shine! diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index b6c46e2db..fd525fc18 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 07/23/16 13:35:55 +-- merge date : 07/25/16 17:40:20 do -- begin closure to overcome local limits and interference |