diff options
Diffstat (limited to 'scripts/context/lua/mtxrun.lua')
-rw-r--r-- | scripts/context/lua/mtxrun.lua | 311 |
1 files changed, 264 insertions, 47 deletions
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index ac4b0556e..68ee3d2c1 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -347,7 +347,8 @@ patterns.hexadecimal = P("0x") * R("09","AF","af")^1 patterns.lowercase = R("az") patterns.uppercase = R("AZ") patterns.letter = patterns.lowercase + patterns.uppercase -patterns.space = S(" ") +patterns.space = P(" ") +patterns.tab = P("\t") patterns.eol = S("\n\r") patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto) patterns.newline = crlf + cr + lf @@ -358,6 +359,9 @@ patterns.nonwhitespace = 1 - patterns.whitespace patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191') patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false) +patterns.comma = P(",") +patterns.commaspacer = P(",") * patterns.spacer^0 +patterns.period = P(".") patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/"" patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/"" @@ -462,15 +466,36 @@ local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 6 patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4 + + local cache = { } function lpeg.stripper(str) - local s = cache[str] - if not s then - s = Cs(((S(str)^1)/"" + 1)^0) - cache[str] = s + if type(str) == "string" then + local s = cache[str] + if not s then + s = Cs(((S(str)^1)/"" + 1)^0) + cache[str] = s + end + return s + else + return Cs(((str^1)/"" + 1)^0) + end +end + +local cache = { } + +function lpeg.keeper(str) + if type(str) == "string" then + local s = cache[str] + if not s then + s = Cs((((1-S(str))^1)/"" + 1)^0) + cache[str] = s + end + return s + else + return Cs((((1-str)^1)/"" + 1)^0) end - return s end function lpeg.replacer(t) @@ -642,7 +667,7 @@ end table.sortedkeys = sortedkeys table.sortedhashkeys = sortedhashkeys -function table.sortedhash(t) +local function sortedhash(t) local s = sortedhashkeys(t) -- maybe just sortedkeys local n = 0 local function kv(s) @@ -653,7 +678,8 @@ function table.sortedhash(t) return kv, s end -table.sortedpairs = table.sortedhash +table.sortedhash = sortedhash +table.sortedpairs = sortedhash function table.append(t, list) for _,v in next, list do @@ -1315,12 +1341,17 @@ function table.count(t) return n end -function table.swapped(t) - local s = { } +function table.swapped(t,s) + local n = { } + if s then + for k, v in next, s do + n[k] = v + end + end for k, v in next, t do - s[v] = k + n[v] = k end - return s + return n end @@ -1340,7 +1371,7 @@ function table.hexed(t,seperator) return concat(tt,seperator or " ") end -function table.reverse_hash(h) +function table.reverse_hash(h) -- needs another name local r = { } for k,v in next, h do r[v] = lower(gsub(k," ","")) @@ -1388,10 +1419,18 @@ function table.insert_after_value(t,value,extra) insert(t,#t+1,extra) end -function table.sequenced(t,sep) +function table.sequenced(t,sep,simple) -- hash only local s = { } - for k, v in next, t do -- indexed? - s[#s+1] = k .. "=" .. tostring(v) + for k, v in sortedhash(t) do + if simple then + if v == true then + s[#s+1] = k + elseif v and v~= "" then + s[#s+1] = k .. "=" .. tostring(v) + end + else + s[#s+1] = k .. "=" .. tostring(v) + end end return concat(s, sep or " | ") end @@ -1593,6 +1632,39 @@ function io.ask(question,default,options) end end +function io.readnumber(f,n,m) + if m then + f:seek("set",n) + n = m + end + if n == 1 then + return byte(f:read(1)) + elseif n == 2 then + local a, b = byte(f:read(2),1,2) + return 256*a + b + elseif n == 4 then + local a, b, c, d = byte(f:read(4),1,4) + return 256^3 * a + 256^2 * b + 256*c + d + elseif n == 8 then + local a, b = readnumber(f,4), readnumber(f,4) + return 256 * b + c + elseif n == 12 then + local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4) + return 256^2 * a + 256 * b + c + else + return 0 + end +end + +function io.readstring(f,n,m) + if m then + f:seek("set",n) + n = m + end + local str = gsub(f:read(n),"%z","") + return str +end + end -- of closure @@ -1658,6 +1730,23 @@ function number.bits(n,zero) end +function number.bit(p) + return 2 ^ (p - 1) -- 1-based indexing +end + +function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ... + return x % (p + p) >= p +end + +function number.setbit(x, p) + return hasbit(x, p) and x or x + p +end + +function number.clearbit(x, p) + return hasbit(x, p) and x - p or x +end + + end -- of closure do -- create closure to overcome 200 locals limit @@ -3023,7 +3112,7 @@ end utf = utf or unicode.utf8 local concat, utfchar, utfgsub = table.concat, utf.char, utf.gsub -local char, byte, find, bytepairs = string.char, string.byte, string.find, string.bytepairs +local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format -- 0 EF BB BF UTF-8 -- 1 FF FE UTF-16-little-endian @@ -3189,6 +3278,15 @@ function unicode.utf8_to_utf16(str,littleendian) end end +function unicode.utfcodes(str) + local t = { } + for k,v in string.utfvalues(str) do + t[#t+1] = format("0x%04X",k) + end + return concat(t,separator or " ") +end + + end -- of closure @@ -3568,14 +3666,24 @@ function aux.array_to_string(a,separator) end end -function aux.settings_to_set(str,t) +function aux.settings_to_set(str,t) -- tohash? t = t or { } - for s in gmatch(str,"%s*([^,]+)") do + for s in gmatch(str,"%s*([^, ]+)") do -- space added t[s] = true end return t end +function aux.simple_hash_to_string(h, separator) + local t = { } + for k, v in table.sortedhash(h) do + if v then + t[#t+1] = k + end + end + return concat(t,separator or ",") +end + local value = lbrace * lpeg.C((nobrace + nested)^0) * rbrace local pattern = lpeg.Ct((space + value)^0) @@ -3637,6 +3745,60 @@ end -- as we use this a lot ... +function aux.formatcolumns(result,between) + if result and #result > 0 then + between = between or " " + local widths, numbers = { }, { } + local first = result[1] + local n = #first + for i=1,n do + widths[i] = 0 + end + for i=1,#result do + local r = result[i] + for j=1,n do + local rj = r[j] + local tj = type(rj) + if tj == "number" then + numbers[j] = true + end + if tj ~= "string" then + rj = tostring(rj) + r[j] = rj + end + local w = #rj + if w > widths[j] then + widths[j] = w + end + end + end + for i=1,n do + local w = widths[i] + if numbers[i] then + if w > 80 then + widths[i] = "%s" .. between + else + widths[i] = "%0" .. w .. "i" .. between + end + else + if w > 80 then + widths[i] = "%s" .. between + elseif w > 0 then + widths[i] = "%-" .. w .. "s" .. between + else + widths[i] = "%s" + end + end + end + local template = string.strip(concat(widths)) + for i=1,#result do + local str = format(template,unpack(result[i])) + result[i] = string.strip(str) + end + end + return result +end + end -- of closure @@ -3843,7 +4005,7 @@ if not modules then modules = { } end modules ['trac-set'] = { local type, next, tostring = type, next, tostring local concat = table.concat -local format, find, lower, gsub = string.format, string.find, string.lower, string.gsub +local format, find, lower, gsub, simpleesc = string.format, string.find, string.lower, string.gsub, string.simpleesc local is_boolean = string.is_boolean setters = { } @@ -3915,7 +4077,7 @@ local function set(t,what,newvalue) for name, functions in next, data do if done[name] then -- prevent recursion due to wildcards - elseif find(name,w) then + elseif find(name,simpleesc(w)) then done[name] = true for i=1,#functions do functions[i](value) @@ -3979,14 +4141,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(tostring(what))) + enable(t,what) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(tostring(what))) + disable(t,what) t.disable, t.done = e, { } end @@ -4050,36 +4212,50 @@ trackers = setters.new("trackers") directives = setters.new("directives") experiments = setters.new("experiments") +-- experiment + +if trackers and environment and environment.engineflags.trackers then + trackers.enable(environment.engineflags.trackers) +end +if directives and environment and environment.engineflags.directives then + directives.enable(environment.engineflags.directives) +end + -- nice trick: we overload two of the directives related functions with variants that -- do tracing (itself using a tracker) .. proof of concept +local function report(...) -- messy .. chicken or egg + local p = (commands and commands.writestatus) or (logs and logs.report) + if p then p(...) end +end + local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end) -local e = directives.enable -local d = directives.disable +local enable = directives.enable +local disable = directives.disable function directives.enable(...) - (commands.writestatus or logs.report)("directives","enabling: %s",concat({...}," ")) - e(...) + report("directives","enabling: %s",concat({...}," ")) + enable(...) end function directives.disable(...) - (commands.writestatus or logs.report)("directives","disabling: %s",concat({...}," ")) - d(...) + report("directives","disabling: %s",concat({...}," ")) + disable(...) end -local e = experiments.enable -local d = experiments.disable +local enable = experiments.enable +local disable = experiments.disable function experiments.enable(...) - (commands.writestatus or logs.report)("experiments","enabling: %s",concat({...}," ")) - e(...) + report("experiments","enabling: %s",concat({...}," ")) + enable(...) end function experiments.disable(...) - (commands.writestatus or logs.report)("experiments","disabling: %s",concat({...}," ")) - d(...) + report("experiments","disabling: %s",concat({...}," ")) + disable(...) end -- a useful example @@ -4088,6 +4264,15 @@ directives.register("system.nostatistics", function(v) statistics.enable = not v end) +-- experiment + +if trackers and environment and environment.engineflags.trackers then + trackers.enable(environment.engineflags.trackers) +end +if directives and environment and environment.engineflags.directives then + directives.enable(environment.engineflags.directives) +end + end -- of closure @@ -6357,17 +6542,19 @@ apply_axis['child'] = function(list) for l=1,#list do local ll = list[l] local dt = ll.dt - local en = 0 - for k=1,#dt do - local dk = dt[k] - if dk.tg then - collected[#collected+1] = dk - dk.ni = k -- refresh - en = en + 1 - dk.ei = en + if dt then -- weird that this is needed + local en = 0 + for k=1,#dt do + local dk = dt[k] + if dk.tg then + collected[#collected+1] = dk + dk.ni = k -- refresh + en = en + 1 + dk.ei = en + end end + ll.en = en end - ll.en = en end return collected end @@ -8079,6 +8266,7 @@ local finalizers = xml.finalizers.xml local xmlfilter = xml.filter -- we could inline this one for speed local xmltostring = xml.tostring local xmlserialize = xml.serialize +local xmlcollected = xml.collected local function first(collected) -- wrong ? return collected and collected[1] @@ -8356,6 +8544,19 @@ xml.all = xml.filter xml.index = xml.position xml.found = xml.filter +-- a nice one: + +local function totable(x) + local t = { } + for e in xmlcollected(x[1] or x,"/*") do + t[e.tg] = xmltostring(e.dt) or "" + end + return next(t) and t or nil +end + +xml.table = totable +finalizers.table = totable + end -- of closure @@ -8943,6 +9144,7 @@ formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', ' formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } formats['fea'] = 'FONTFEATURES' suffixes['fea'] = { 'fea' } formats['cid'] = 'FONTCIDMAPS' suffixes['cid'] = { 'cid', 'cidmap' } +formats['icc'] = 'ICCPROFILES' suffixes['icc'] = { 'icc' } formats['texmfscripts'] = 'TEXMFSCRIPTS' suffixes['texmfscripts'] = { 'rb', 'pl', 'py' } formats['lua'] = 'LUAINPUTS' suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } formats['lib'] = 'CLUAINPUTS' suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' } @@ -8958,6 +9160,7 @@ alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' +alternatives['icc profiles'] = 'icc' --[[ldx-- <p>If you wondered about some of the previous mappings, how about @@ -12160,6 +12363,21 @@ if not modules then modules = { } end modules ['luat-fmt'] = { -- helper for mtxrun +local quote = string.quote + +local function primaryflags() + local trackers = environment.argument("trackers") + local directives = environment.argument("directives") + local flags = "" + if trackers and trackers ~= "" then + flags = flags .. "--trackers=" .. quote(trackers) + end + if directives and directives ~= "" then + flags = flags .. "--directives=" .. quote(directives) + end + return flags +end + function environment.make_format(name) -- change to format path (early as we need expanded paths) local olddir = lfs.currentdir() @@ -12220,8 +12438,7 @@ function environment.make_format(name) return end -- generate format - local q = string.quote - local command = string.format("luatex --ini --lua=%s %s %sdump",q(usedluastub),q(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\") + local command = string.format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\") logs.simple("running command: %s\n",command) os.spawn(command) -- remove related mem files @@ -12260,7 +12477,7 @@ function environment.run_format(name,data,more) logs.simple("no luc/lua with name: %s",barename) else local q = string.quote - local command = string.format("luatex --fmt=%s --lua=%s %s %s",q(barename),q(luaname),q(data),more ~= "" and q(more) or "") + local command = string.format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "") logs.simple("running command: %s",command) os.spawn(command) end |