diff options
Diffstat (limited to 'tex')
30 files changed, 858 insertions, 313 deletions
diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua index e3b7ed82a..f4b8ece4c 100644 --- a/tex/context/base/cldf-ini.lua +++ b/tex/context/base/cldf-ini.lua @@ -32,6 +32,7 @@ local format, gsub, validstring = string.format, string.gsub, string.valid local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable local insert, remove, concat = table.insert, table.remove, table.concat local lpegmatch, lpegC, lpegS, lpegP, lpegCc, patterns = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc, lpeg.patterns +local formatters = string.formatters -- using formatteds is slower in this case local texsprint = tex.sprint local textprint = tex.tprint @@ -533,7 +534,7 @@ local function caller(parent,f,a,...) local typ = type(f) if typ == "string" then if a then - flush(contentcatcodes,format(f,a,...)) -- was currentcatcodes + flush(contentcatcodes,formatters[f](a,...)) -- was currentcatcodes elseif processlines and lpegmatch(containseol,f) then local flushlines = parent.__flushlines or flushlines flushlines(f) @@ -606,13 +607,13 @@ end function context.fprint(catcodes,fmt,first,...) if type(catcodes) == "number" then if first then - flush(catcodes,format(fmt,first,...)) + flush(catcodes,formatters[fmt](first,...)) else flush(catcodes,fmt) end else if fmt then - flush(format(catcodes,fmt,first,...)) + flush(formatters[catcodes](fmt,first,...)) else flush(catcodes) end @@ -621,29 +622,29 @@ end function tex.fprint(fmt,first,...) -- goodie if first then - flush(currentcatcodes,format(fmt,first,...)) + flush(currentcatcodes,formatters[fmt](first,...)) else flush(currentcatcodes,fmt) end end -local formatters = string.formatters +-- function context.formatted(catcodes,fmt,first,...) -- no longer to be used ... context(...) now uses formatted +-- if type(catcodes) == "number" then -- and this was just a temporary helper that will go away +-- if first then +-- flush(catcodes,formatters[fmt](first,...)) +-- else +-- flush(catcodes,fmt) +-- end +-- else +-- if fmt then +-- flush(formatters[catcodes](fmt,first,...)) +-- else +-- flush(catcodes) +-- end +-- end +-- end -function context.formatted(catcodes,fmt,first,...) - if type(catcodes) == "number" then - if first then - flush(catcodes,formatters[fmt](first,...)) - else - flush(catcodes,fmt) - end - else - if fmt then - flush(formatters[catcodes](fmt,first,...)) - else - flush(catcodes) - end - end -end +context.formatted = context.fprint -- logging @@ -697,7 +698,7 @@ local traced = function(normal,one,two,...) normal(one,two,...) local catcodes = type(one) == "number" and one local arguments = catcodes and { two, ... } or { one, two, ... } - local collapsed, c = { format("f : %s : ", catcodes or '-') }, 1 + local collapsed, c = { formatters["f : %s : "](catcodes or '-') }, 1 for i=1,#arguments do local argument = arguments[i] local argtype = type(argument) @@ -707,7 +708,7 @@ local traced = function(normal,one,two,...) elseif argtype == "number" then collapsed[c] = argument else - collapsed[c] = format("<<%s>>",tostring(argument)) + collapsed[c] = formatters["<<%S>>"](argument) end end currenttrace(concat(collapsed)) @@ -716,11 +717,11 @@ local traced = function(normal,one,two,...) normal(one) local argtype = type(one) if argtype == "string" then - currenttrace(format("f : - : %s",lpegmatch(visualizer,one))) + currenttrace(formatters["f : - : %s"](lpegmatch(visualizer,one))) elseif argtype == "number" then - currenttrace(format("f : - : %s",one)) + currenttrace(formatters["f : - : %s"](one)) else - currenttrace(format("f : - : <<%s>>",tostring(one))) + currenttrace(formatters["f : - : <<%S>>"](one)) end end end @@ -924,7 +925,7 @@ local function caller(parent,f,a,...) local typ = type(f) if typ == "string" then if a then - flush(currentcatcodes,mpdrawing,"{",format(f,a,...),"}") + flush(currentcatcodes,mpdrawing,"{",formatters[f](a,...),"}") else flush(currentcatcodes,mpdrawing,"{",f,"}") end @@ -962,7 +963,7 @@ function metafun.stop() end function metafun.color(name) - return format([[\MPcolor{%s}]],name) + return formatters[ [[\MPcolor{%s}]] ](name) end -- metafun.delayed diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua index 1a994b567..29cce70f0 100644 --- a/tex/context/base/colo-ini.lua +++ b/tex/context/base/colo-ini.lua @@ -11,6 +11,7 @@ local concat, insert, remove = table.concat, table.insert, table.remove local format, gmatch, gsub, lower, match, find = string.format, string.gmatch, string.gsub, string.lower, string.match, string.find local P, R, C, Cc = lpeg.P, lpeg.R, lpeg.C, lpeg.Cc local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local formatters = string.formatters local trace_define = false trackers.register("colors.define",function(v) trace_define = v end) @@ -470,38 +471,32 @@ local function mpcolor(model,ca,ta,default) model = forcedmodel(model) if tv then if model == 2 then - return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5]) + return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5]) elseif model == 3 then - return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5]) + return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5]) elseif model == 4 then - return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9]) + return formatters["transparent(%s,%s,cmyk(%s,%s,%s,%s))"](tv[1],tv[2],cv[6],cv[7],cv[8],cv[9]) elseif model == 5 then - return format('transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))',tv[1],tv[2],cv[10],cv[11],cv[12],cv[13]) - else - return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5]) --- this will become (see ** in meta-ini.mkiv) --- --- return format("transparent(%s,%s,(%s))",tv[1],tv[2],cv[2]) + return formatters['transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))'](tv[1],tv[2],cv[10],cv[11],cv[12],cv[13]) + else -- see ** in meta-ini.mkiv: return formatters["transparent(%s,%s,(%s))"](tv[1],tv[2],cv[2]) + return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5]) end else if model == 2 then - return format("(%s,%s,%s)",cv[3],cv[4],cv[5]) + return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5]) elseif model == 3 then - return format("(%s,%s,%s)",cv[3],cv[4],cv[5]) + return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5]) elseif model == 4 then - return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9]) + return formatters["cmyk(%s,%s,%s,%s)"](cv[6],cv[7],cv[8],cv[9]) elseif model == 5 then - return format('multitonecolor("%s",%s,"%s","%s")',cv[10],cv[11],cv[12],cv[13]) - else - return format("(%s,%s,%s)",cv[3],cv[4],cv[5]) --- this will become (see ** in meta-ini.mkiv) --- --- return format("%s",(cv[2])) + return formatters['multitonecolor("%s",%s,"%s","%s")'](cv[10],cv[11],cv[12],cv[13]) + else -- see ** in meta-ini.mkiv: return formatters["%s"]((cv[2])) + return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5]) end end else default = default or 0 -- rgb ! - return format("(%s,%s,%s)",default,default,default) + return formatters["(%s,%s,%s)"](default,default,default) end end @@ -510,7 +505,7 @@ local function mpnamedcolor(name) end local function mpoptions(model,ca,ta,default) -- will move to mlib-col - return format("withcolor %s",mpcolor(model,ca,ta,default)) + return formatters["withcolor %s"](mpcolor(model,ca,ta,default)) end colors.mpcolor = mpcolor diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index aa4e3223d..a53a074c4 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{2013.03.08 01:14} +\newcontextversion{2013.03.10 14:36} %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 debad7bae..cc4ded1f2 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{2013.03.08 01:14} +\newcontextversion{2013.03.10 14:36} %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/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex 398846f55..bbc4ff28d 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png Binary files differindex 3be5fcc66..43823ceb6 100644 --- a/tex/context/base/context-version.png +++ b/tex/context/base/context-version.png diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 20aefca87..0a5bc9680 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{2013.03.08 01:14} +\edef\contextversion{2013.03.10 14:36} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 4fcd7ae07..8cb615107 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -25,7 +25,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2013.03.08 01:14} +\edef\contextversion{2013.03.10 14:36} %D For those who want to use this: diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua index 533103ec6..b5c4b2b05 100644 --- a/tex/context/base/file-job.lua +++ b/tex/context/base/file-job.lua @@ -823,15 +823,24 @@ function commands.getcommandline() -- has to happen at the tex end in order to e inputfile = basename(inputfile) end + local kindofrun = arguments.kindofrun + local currentrun = arguments.maxnofruns + local maxnofruns = arguments.currentrun + context.setupsystem { [constants.directory] = validstring(arguments.setuppath), [constants.inputfile] = inputfile, [constants.file] = validstring(arguments.result), [constants.random] = validstring(arguments.randomseed), - [constants.n] = validstring(arguments.kindofrun), - [constants.m] = validstring(arguments.currentrun), + -- old: + [constants.n] = validstring(kindofrun), + [constants.m] = validstring(currentrun), } + environment.kindofrun = tonumber(kindofrun) or 0 + environment.maxnofruns = tonumber(maxnofruns) or 0 + environment.currentrun = tonumber(currentrun) or 0 + if validstring(arguments.arguments) then context.setupenv { arguments.arguments } end diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 3f90da91b..63564f4f9 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -15,6 +15,7 @@ local concat, sort, format = table.concat, table.sort, string.format local serialize = table.serialize local lpegmatch = lpeg.match local unpack = unpack or table.unpack +local formatters = string.formatters local allocate = utilities.storage.allocate local sparse = utilities.storage.sparse @@ -581,7 +582,7 @@ local function checkduplicate(where) -- fails on "Romantik" but that's a border for _, m in next, mapping do for k, v in next, m do local s = specifications[v] - local hash = format("%s-%s-%s-%s-%s",s.familyname,s.weight or "*",s.style or "*",s.width or "*",s.variant or "*") + local hash = formatters["%s-%s-%s-%s-%s"](s.familyname,s.weight or "*",s.style or "*",s.width or "*",s.variant or "*") local h = loaded[hash] if h then local ok = true diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv index 54d024b85..8557bbb0b 100644 --- a/tex/context/base/grph-inc.mkiv +++ b/tex/context/base/grph-inc.mkiv @@ -567,6 +567,10 @@ {\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight \stopfoundexternalfigure} +% \doifmodeelse{*\v!last} +% {\settrue \c_grph_include_flush} +% {\setfalse\c_grph_include_flush}% + \def\grph_include_finalize {\global\setbox\foundexternalfigure\vbox {\ifcase\figurestatus diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index 9bd9706bf..cfc26a5a5 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -829,3 +829,24 @@ end -- local s = "12" .. string.rep("AB",20) .. "34" .. string.rep("AB",30) .. "56" -- inspect(p) -- print(lpeg.match(p,s)) + +-- moved here (before util-str) + +local digit = R("09") +local period = P(".") +local zero = P("0") +local trailingzeros = zero^0 * -digit -- suggested by Roberto R +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") +local number = digit^1 * (case_1 + case_2) +local stripper = Cs((number + 1)^0) + +lpeg.patterns.stripzeros = stripper + +-- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" +-- collectgarbage("collect") +-- str = string.rep(sample,10000) +-- local ts = os.clock() +-- lpegmatch(stripper,str) +-- print(#str, os.clock()-ts, lpegmatch(stripper,sample)) + diff --git a/tex/context/base/l-lua.lua b/tex/context/base/l-lua.lua index 5863960b3..9ac8192b0 100644 --- a/tex/context/base/l-lua.lua +++ b/tex/context/base/l-lua.lua @@ -12,6 +12,7 @@ local major, minor = string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") _MAJORVERSION = tonumber(major) or 5 _MINORVERSION = tonumber(minor) or 1 +_LUAVERSION = _MAJORVERSION + _MINORVERSION/10 -- lpeg diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 92ef02503..c33cd195b 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -394,6 +394,8 @@ end -- todo: %g faster on numbers than %s +-- we can speed this up with repeaters and formatters (is indeed faster) + local propername = patterns.propername -- was find(name,"^%a[%w%_]*$") local function dummy() end @@ -711,6 +713,322 @@ local function serialize(_handle,root,name,specification) -- handle wins handle("}") end +-- -- This is some 20% faster than using format (because formatters are much faster) but +-- -- of course, inlining the format using .. is then again faster .. anyway, as we do +-- -- some pretty printing as well there is not that much to gain unless we make a 'fast' +-- -- ugly variant as well. But, we would have to move the formatter to l-string then. + +-- local formatters = string.formatters + +-- local function do_serialize(root,name,level,indexed) +-- if level > 0 then +-- if indexed then +-- handle(formatters["%w{"](level)) +-- else +-- local tn = type(name) +-- if tn == "number" then +-- if hexify then +-- handle(formatters["%w[%04H]={"](level,name)) +-- else +-- handle(formatters["%w[%s]={"](level,name)) +-- end +-- elseif tn == "string" then +-- if noquotes and not reserved[name] and lpegmatch(propername,name) then +-- handle(formatters["%w%s={"](level,name)) +-- else +-- handle(formatters["%w[%q]={"](level,name)) +-- end +-- elseif tn == "boolean" then +-- handle(formatters["%w[%S]={"](level,name)) +-- else +-- handle(formatters["%w{"](level)) +-- end +-- end +-- end +-- -- we could check for k (index) being number (cardinal) +-- if root and next(root) then +-- -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone) +-- -- if compact then +-- -- -- NOT: for k=1,#root do (we need to quit at nil) +-- -- for k,v in ipairs(root) do -- can we use next? +-- -- if not first then first = k end +-- -- last = last + 1 +-- -- end +-- -- end +-- local first, last = nil, 0 +-- if compact then +-- last = #root +-- for k=1,last do +-- if root[k] == nil then +-- last = k - 1 +-- break +-- end +-- end +-- if last > 0 then +-- first = 1 +-- end +-- end +-- local sk = sortedkeys(root) +-- for i=1,#sk do +-- local k = sk[i] +-- local v = root[k] +-- --~ if v == root then +-- -- circular +-- --~ else +-- local t, tk = type(v), type(k) +-- if compact and first and tk == "number" and k >= first and k <= last then +-- if t == "number" then +-- if hexify then +-- handle(formatters["%w %04H,"](level,v)) +-- else +-- handle(formatters["%w %s,"](level,v)) -- %.99g +-- end +-- elseif t == "string" then +-- if reduce and tonumber(v) then +-- handle(formatters["%w %s,"](level,v)) +-- else +-- handle(formatters["%w %q,"](level,v)) +-- end +-- elseif t == "table" then +-- if not next(v) then +-- handle(formatters["%w {},"](level)) +-- elseif inline then -- and #t > 0 +-- local st = simple_table(v) +-- if st then +-- handle(formatters["%w { %, t },"](level,st)) +-- else +-- do_serialize(v,k,level+1,true) +-- end +-- else +-- do_serialize(v,k,level+1,true) +-- end +-- elseif t == "boolean" then +-- handle(formatters["%w %S,"](level,v)) +-- elseif t == "function" then +-- if functions then +-- handle(formatters['%w load(%q),'](level,dump(v))) +-- else +-- handle(formatters['%w "function",'](level)) +-- end +-- else +-- handle(formatters["%w %Q,"](level,v)) +-- end +-- elseif k == "__p__" then -- parent +-- if false then +-- handle(formatters["%w __p__=nil,"](level)) +-- end +-- elseif t == "number" then +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]=%04H,"](level,k,v)) +-- else +-- handle(formatters["%w [%s]=%s,"](level,k,v)) -- %.99g +-- end +-- elseif tk == "boolean" then +-- if hexify then +-- handle(formatters["%w [%S]=%04H,"](level,k,v)) +-- else +-- handle(formatters["%w [%S]=%s,"](level,k,v)) -- %.99g +-- end +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- if hexify then +-- handle(formatters["%w %s=%04H,"](level,k,v)) +-- else +-- handle(formatters["%w %s=%s,"](level,k,v)) -- %.99g +-- end +-- else +-- if hexify then +-- handle(formatters["%w [%q]=%04H,"](level,k,v)) +-- else +-- handle(formatters["%w [%q]=%s,"](level,k,v)) -- %.99g +-- end +-- end +-- elseif t == "string" then +-- if reduce and tonumber(v) then +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]=%s,"](level,k,v)) +-- else +-- handle(formatters["%w [%s]=%s,"](level,k,v)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]=%s,"](level,k,v)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s=%s,"](level,k,v)) +-- else +-- handle(formatters["%w [%q]=%s,"](level,k,v)) +-- end +-- else +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]=%q,"](level,k,v)) +-- else +-- handle(formatters["%w [%s]=%q,"](level,k,v)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]=%q,"](level,k,v)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s=%q,"](level,k,v)) +-- else +-- handle(formatters["%w [%q]=%q,"](level,k,v)) +-- end +-- end +-- elseif t == "table" then +-- if not next(v) then +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]={},"](level,k)) +-- else +-- handle(formatters["%w [%s]={},"](level,k)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]={},"](level,k)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s={},"](level,k)) +-- else +-- handle(formatters["%w [%q]={},"](level,k)) +-- end +-- elseif inline then +-- local st = simple_table(v) +-- if st then +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]={ %, t },"](level,k,st)) +-- else +-- handle(formatters["%w [%s]={ %, t },"](level,k,st)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]={ %, t },"](level,k,st)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s={ %, t },"](level,k,st)) +-- else +-- handle(formatters["%w [%q]={ %, t },"](level,k,st)) +-- end +-- else +-- do_serialize(v,k,level+1) +-- end +-- else +-- do_serialize(v,k,level+1) +-- end +-- elseif t == "boolean" then +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]=%S,"](level,k,v)) +-- else +-- handle(formatters["%w [%s]=%S,"](level,k,v)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]=%S,"](level,k,v)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s=%S,"](level,k,v)) +-- else +-- handle(formatters["%w [%q]=%S,"](level,k,v)) +-- end +-- elseif t == "function" then +-- if functions then +-- local f = getinfo(v).what == "C" and dump(dummy) or dump(v) +-- -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]=load(%q),"](level,k,f)) +-- else +-- handle(formatters["%w [%s]=load(%q),"](level,k,f)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]=load(%q),"](level,k,f)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s=load(%q),"](level,k,f)) +-- else +-- handle(formatters["%w [%q]=load(%q),"](level,k,f)) +-- end +-- end +-- else +-- if tk == "number" then +-- if hexify then +-- handle(formatters["%w [%04H]=%Q,"](level,k,v)) +-- else +-- handle(formatters["%w [%s]=%Q,"](level,k,v)) +-- end +-- elseif tk == "boolean" then +-- handle(formatters["%w [%S]=%Q,"](level,k,v)) +-- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then +-- handle(formatters["%w %s=%Q,"](level,k,v)) +-- else +-- handle(formatters["%w [%q]=%Q,"](level,k,v)) +-- end +-- end +-- --~ end +-- end +-- end +-- if level > 0 then +-- handle(formatters["%w}"](level)) +-- end +-- end + +-- local function serialize(_handle,root,name,specification) -- handle wins +-- local tname = type(name) +-- if type(specification) == "table" then +-- noquotes = specification.noquotes +-- hexify = specification.hexify +-- handle = _handle or specification.handle or print +-- reduce = specification.reduce or false +-- functions = specification.functions +-- compact = specification.compact +-- inline = specification.inline and compact +-- if functions == nil then +-- functions = true +-- end +-- if compact == nil then +-- compact = true +-- end +-- if inline == nil then +-- inline = compact +-- end +-- else +-- noquotes = false +-- hexify = false +-- handle = _handle or print +-- reduce = false +-- compact = true +-- inline = true +-- functions = true +-- end +-- if tname == "string" then +-- if name == "return" then +-- handle("return {") +-- else +-- handle(name .. "={") +-- end +-- elseif tname == "number" then +-- if hexify then +-- handle(format("[0x%04X]={",name)) +-- else +-- handle("[" .. name .. "]={") +-- end +-- elseif tname == "boolean" then +-- if name then +-- handle("return {") +-- else +-- handle("{") +-- end +-- else +-- handle("t={") +-- end +-- if root then +-- -- The dummy access will initialize a table that has a delayed initialization +-- -- using a metatable. (maybe explicitly test for metatable) +-- if getmetatable(root) then -- todo: make this an option, maybe even per subtable +-- local dummy = root._w_h_a_t_e_v_e_r_ +-- root._w_h_a_t_e_v_e_r_ = nil +-- end +-- -- Let's forget about empty tables. +-- if next(root) then +-- do_serialize(root,name,0) +-- end +-- end +-- handle("}") +-- end + -- name: -- -- true : return { } @@ -730,6 +1048,13 @@ function table.serialize(root,name,specification) return concat(t,"\n") end +-- local a = { e = { 1,2,3,4,5,6}, a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc", d = { a = 1, b = 2, c = "ccc" } } } +-- local t = os.clock() +-- for i=1,10000 do +-- table.serialize(a) +-- end +-- print(os.clock()-t,table.serialize(a)) + table.tohandle = serialize -- sometimes tables are real use (zapfino extra pro is some 85M) in which diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv index 4ece2a29a..b9ccd8b11 100644 --- a/tex/context/base/luat-lib.mkiv +++ b/tex/context/base/luat-lib.mkiv @@ -13,9 +13,9 @@ \writestatus{loading}{ConTeXt Lua Macros / Libraries} +\registerctxluafile{util-str}{1.001} \registerctxluafile{util-tab}{1.001} \registerctxluafile{util-sto}{1.001} % could also be done in trac-deb.mkiv -\registerctxluafile{util-str}{1.001} % uses util-sto \registerctxluafile{util-pck}{1.001} \registerctxluafile{util-seq}{1.001} %registerctxluafile{util-mrg}{1.001} % not needed in context itself, only mtxrun diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua index d73b87287..2be648075 100644 --- a/tex/context/base/lxml-lpt.lua +++ b/tex/context/base/lxml-lpt.lua @@ -15,6 +15,7 @@ local format, upper, lower, gmatch, gsub, find, rep = string.format, string.uppe local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns local setmetatableindex = table.setmetatableindex +local formatters = string.formatters -- no need (yet) as paths are cached anyway -- beware, this is not xpath ... e.g. position is different (currently) and -- we have reverse-sibling as reversed preceding sibling @@ -608,15 +609,12 @@ local converter = Cs ( ) cleaner = Cs ( ( ---~ lp_fastpos + + -- lp_fastpos + lp_reserved + lp_number + lp_string + 1 )^1 ) - ---~ expr - local template_e = [[ local expr = xml.expressions return function(list,ll,l,order) @@ -671,6 +669,7 @@ local function errorrunner_e(str,cnv) end return false end + local function errorrunner_f(str,arg) report_lpath("error in finalizer: %s(%s)",str,arg or "") return false diff --git a/tex/context/base/meta-ini.lua b/tex/context/base/meta-ini.lua index 928048776..05433121e 100644 --- a/tex/context/base/meta-ini.lua +++ b/tex/context/base/meta-ini.lua @@ -153,8 +153,12 @@ end -- context.mathematics(f) -- end +-- formatters["\\times10^{%N}"](s) -- strips leading zeros too + local one = Cs((P("@")/"%%." * (R("09")^1) + P("@")/"%%" + 1)^0) -local two = Cs((P("e")/"" * ((S("+-")^0 * R("09")^1)/function(s) return format("\\times10^{%s}",tonumber(s) or s) end) + 1)^1) +local two = Cs((P("e")/"" * ((S("+-")^0 * R("09")^1) / function(s) return format("\\times10^{%s}",tonumber(s) or s) end) + 1)^1) + +-- local two = Cs((P("e")/"" * ((S("+-")^0 * R("09")^1) / formatters["\\times10^{%N}"]) + 1)^1) function metapost.formatnumber(fmt,n) -- just lua format context.mathematics(lpegmatch(two,format(lpegmatch(one,fmt),n))) diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua index e22e3af30..205dbd35a 100644 --- a/tex/context/base/mlib-pdf.lua +++ b/tex/context/base/mlib-pdf.lua @@ -12,6 +12,7 @@ local format, concat, gsub = string.format, table.concat, string.gsub local abs, sqrt, round = math.abs, math.sqrt, math.round local setmetatable = setmetatable local Cf, C, Cg, Ct, P, S, lpegmatch = lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.match +local formatters = string.formatters local report_metapost = logs.reporter("metapost") @@ -97,7 +98,7 @@ end function pdfflusher.comment(message) if message then - message = format("%% mps graphic %s: %s", metapost.n, message) + message = formatters["%% mps graphic %s: %s"](metapost.n,message) if experiment then context(pdfliteral(message)) else @@ -189,11 +190,11 @@ local function flushnormalpath(path, t, open) nt = nt + 1 pth = path[i] if not ith then - t[nt] = format("%f %f m",pth.x_coord,pth.y_coord) + t[nt] = formatters["%f %f m"](pth.x_coord,pth.y_coord) elseif curved(ith,pth) then - t[nt] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) + t[nt] = formatters["%f %f %f %f %f %f c"](ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) else - t[nt] = format("%f %f l",pth.x_coord,pth.y_coord) + t[nt] = formatters["%f %f l"](pth.x_coord,pth.y_coord) end ith = pth end @@ -201,15 +202,15 @@ local function flushnormalpath(path, t, open) nt = nt + 1 local one = path[1] if curved(pth,one) then - t[nt] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) + t[nt] = formatters["%f %f %f %f %f %f c"](pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) else - t[nt] = format("%f %f l",one.x_coord,one.y_coord) + t[nt] = formatters["%f %f l"](one.x_coord,one.y_coord) end elseif #path == 1 then -- special case .. draw point local one = path[1] nt = nt + 1 - t[nt] = format("%f %f l",one.x_coord,one.y_coord) + t[nt] = formatters["%f %f l"](one.x_coord,one.y_coord) end return t end @@ -223,18 +224,18 @@ local function flushconcatpath(path, t, open) nt = 0 end nt = nt + 1 - t[nt] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty) + t[nt] = formatters["%f %f %f %f %f %f cm"](sx,rx,ry,sy,tx,ty) for i=1,#path do nt = nt + 1 pth = path[i] if not ith then - t[nt] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord)) + t[nt] = formatters["%f %f m"](mpconcat(pth.x_coord,pth.y_coord)) elseif curved(ith,pth) then local a, b = mpconcat(ith.right_x,ith.right_y) local c, d = mpconcat(pth.left_x,pth.left_y) - t[nt] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(pth.x_coord,pth.y_coord)) + t[nt] = formatters["%f %f %f %f %f %f c"](a,b,c,d,mpconcat(pth.x_coord,pth.y_coord)) else - t[nt] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord)) + t[nt] = formatters["%f %f l"](mpconcat(pth.x_coord, pth.y_coord)) end ith = pth end @@ -244,15 +245,15 @@ local function flushconcatpath(path, t, open) if curved(pth,one) then local a, b = mpconcat(pth.right_x,pth.right_y) local c, d = mpconcat(one.left_x,one.left_y) - t[nt] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(one.x_coord, one.y_coord)) + t[nt] = formatters["%f %f %f %f %f %f c"](a,b,c,d,mpconcat(one.x_coord, one.y_coord)) else - t[nt] = format("%f %f l",mpconcat(one.x_coord,one.y_coord)) + t[nt] = formatters["%f %f l"](mpconcat(one.x_coord,one.y_coord)) end elseif #path == 1 then -- special case .. draw point nt = nt + 1 local one = path[1] - t[nt] = format("%f %f l",mpconcat(one.x_coord,one.y_coord)) + t[nt] = formatters["%f %f l"](mpconcat(one.x_coord,one.y_coord)) end return t end @@ -319,7 +320,7 @@ function metapost.flush(result,flusher,askedfig) elseif objecttype == "text" then t[#t+1] = "q" local ot = object.transform -- 3,4,5,6,1,2 - t[#t+1] = format("%f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: format("%f %f m %f %f %f %f 0 0 cm",unpack(ot)) + t[#t+1] = formatters["%f %f %f %f %f %f cm"](ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: formatters["%f %f m %f %f %f %f 0 0 cm"](unpack(ot)) flushfigure(t) -- flush accumulated literals t = { } textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) @@ -344,21 +345,21 @@ function metapost.flush(result,flusher,askedfig) local ml = object.miterlimit if ml and ml ~= miterlimit then miterlimit = ml - t[#t+1] = format("%f M",ml) + t[#t+1] = formatters["%f M"](ml) end local lj = object.linejoin if lj and lj ~= linejoin then linejoin = lj - t[#t+1] = format("%i j",lj) + t[#t+1] = formatters["%i j"](lj) end local lc = object.linecap if lc and lc ~= linecap then linecap = lc - t[#t+1] = format("%i J",lc) + t[#t+1] = formatters["%i J"](lc) end local dl = object.dash if dl then - local d = format("[%s] %f d",concat(dl.dashes or {}," "),dl.offset) + local d = formatters["[%s] %f d"](concat(dl.dashes or {}," "),dl.offset) if d ~= dashed then dashed = d t[#t+1] = dashed @@ -374,7 +375,7 @@ function metapost.flush(result,flusher,askedfig) if pen then if pen.type == 'elliptical' then transformed, penwidth = pen_characteristics(original) -- boolean, value - t[#t+1] = format("%f w",penwidth) -- todo: only if changed + t[#t+1] = formatters["%f w"](penwidth) -- todo: only if changed if objecttype == 'fill' then objecttype = 'both' end diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua index 78e35d8b0..3a6f0dc77 100644 --- a/tex/context/base/mlib-pps.lua +++ b/tex/context/base/mlib-pps.lua @@ -15,7 +15,6 @@ local round = math.round local insert, concat = table.insert, table.concat 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 formatters = string.formatters local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context @@ -665,7 +664,7 @@ function makempy.processgraphics(graphics) local data = io.loaddata(mpyfile) for figure in gmatch(data,"beginfig(.-)endfig") do r = r + 1 - result[r] = format("begingraphictextfig%sendgraphictextfig ;\n", figure) + result[r] = formatters["begingraphictextfig%sendgraphictextfig ;\n"](figure) end io.savedata(mpyfile,concat(result,"")) end @@ -800,91 +799,6 @@ local function cl_reset(t) t[#t+1] = metapost.colorinitializer() -- only color end --- text - --- local tx_done = { } --- --- local function tx_reset() --- tx_done = { } --- end --- --- local function tx_analyze(object,prescript) -- todo: hash content and reuse them --- local tx_stage = prescript.tx_stage --- if tx_stage then --- local tx_number = tonumber(prescript.tx_number) --- if not tx_done[tx_number] then --- tx_done[tx_number] = true --- if trace_textexts then --- report_textexts("setting %s %s (first pass)",tx_stage,tx_number) --- end --- local s = object.postscript or "" --- local c = object.color -- only simple ones, no transparency --- local a = prescript.tr_alternative --- local t = prescript.tr_transparency --- if not c then --- -- no color --- elseif #c == 1 then --- if a and t then --- s = format("\\directcolored[s=%f,a=%f,t=%f]%s",c[1],a,t,s) --- else --- s = format("\\directcolored[s=%f]%s",c[1],s) --- end --- elseif #c == 3 then --- if a and t then --- s = format("\\directcolored[r=%f,g=%f,b=%f,a=%f,t=%f]%s",c[1],c[2],c[3],a,t,s) --- else --- s = format("\\directcolored[r=%f,g=%f,b=%f]%s",c[1],c[2],c[3],s) --- end --- elseif #c == 4 then --- if a and t then --- s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s",c[1],c[2],c[3],c[4],a,t,s) --- else --- s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f]%s",c[1],c[2],c[3],c[4],s) --- end --- end --- context.MPLIBsettext(tx_number,s) -- combine colored in here, saves call --- metapost.multipass = true --- end --- end --- end --- --- local function tx_process(object,prescript,before,after) --- local tx_number = prescript.tx_number --- if tx_number then --- tx_number = tonumber(tx_number) --- local tx_stage = prescript.tx_stage --- if tx_stage == "final" then -- redundant test --- if trace_textexts then --- report_textexts("processing %s (second pass)",tx_number) --- end --- local sx,rx,ry,sy,tx,ty = cm(object) -- outside function ! --- before[#before+1] = function() --- -- flush always happens, we can have a special flush function injected before --- local box = textexts[tx_number] --- if box then --- context.MPLIBgettextscaledcm(tx_number, --- format("%f",sx), -- bah ... %s no longer checks --- format("%f",rx), -- bah ... %s no longer checks --- format("%f",ry), -- bah ... %s no longer checks --- format("%f",sy), -- bah ... %s no longer checks --- format("%f",tx), -- bah ... %s no longer checks --- format("%f",ty), -- bah ... %s no longer checks --- sxsy(box.width,box.height,box.depth)) --- else --- report_textexts("unknown %s",tx_number) --- end --- end --- if not trace_textexts then --- object.path = false -- else: keep it --- end --- object.color = false --- object.grouped = true --- end --- end --- end - --- experiment - local tx_hash = { } local tx_last = 0 @@ -915,21 +829,21 @@ local function tx_analyze(object,prescript) -- todo: hash content and reuse them -- no color elseif #c == 1 then if a and t then - s = format("\\directcolored[s=%f,a=%f,t=%f]%s",c[1],a,t,s) + s = formatters["\\directcolored[s=%f,a=%f,t=%f]%s"](c[1],a,t,s) else - s = format("\\directcolored[s=%f]%s",c[1],s) + s = formatters["\\directcolored[s=%f]%s"](c[1],s) end elseif #c == 3 then if a and t then - s = format("\\directcolored[r=%f,g=%f,b=%f,a=%f,t=%f]%s",c[1],c[2],c[3],a,t,s) + s = formatters["\\directcolored[r=%f,g=%f,b=%f,a=%f,t=%f]%s"](c[1],c[2],c[3],a,t,s) else - s = format("\\directcolored[r=%f,g=%f,b=%f]%s",c[1],c[2],c[3],s) + s = formatters["\\directcolored[r=%f,g=%f,b=%f]%s"](c[1],c[2],c[3],s) end elseif #c == 4 then if a and t then - s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s",c[1],c[2],c[3],c[4],a,t,s) + s = formatters["\\directcolored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s"](c[1],c[2],c[3],c[4],a,t,s) else - s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f]%s",c[1],c[2],c[3],c[4],s) + s = formatters["\\directcolored[c=%f,m=%f,y=%f,k=%f]%s"](c[1],c[2],c[3],c[4],s) end end context.MPLIBsettext(tx_last,s) @@ -1022,7 +936,7 @@ end local function gt_analyze(object,prescript) local gt_stage = prescript.gt_stage if gt_stage == "trial" then - graphics[#graphics+1] = format("\\MPLIBgraphictext{%s}",object.postscript or "") + graphics[#graphics+1] = formatters["\\MPLIBgraphictext{%s}"](object.postscript or "") metapost.intermediate.needed = true metapost.multipass = true end @@ -1098,7 +1012,7 @@ local function sh_process(object,prescript,before,after) else -- fatal error end - before[#before+1], after[#after+1] = "q /Pattern cs", format("W n /%s sh Q",name) + before[#before+1], after[#after+1] = "q /Pattern cs", formatters["W n /%s sh Q"](name) -- false, not nil, else mt triggered object.colored = false -- hm, not object.color ? object.type = false @@ -1179,7 +1093,7 @@ local function tr_process(object,prescript,before,after) if tr_alternative then tr_alternative = tonumber(tr_alternative) local tr_transparency = tonumber(prescript.tr_transparency) - before[#before+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true)) + before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,tr_alternative,tr_transparency,true)) after[#after+1] = "/Tr0 gs" -- outertransparency end local cs = object.color @@ -1209,7 +1123,7 @@ local function tr_process(object,prescript,before,after) local t = t_list[sp_name] -- string or attribute local v = t and attributes.transparencies.value(t) if v then - before[#before+1] = format("/Tr%s gs",registertransparency(nil,v[1],v[2],true)) + before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,v[1],v[2],true)) after[#after+1] = "/Tr0 gs" -- outertransparency end end diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua index 35cbd40f5..5adf43b46 100644 --- a/tex/context/base/mlib-run.lua +++ b/tex/context/base/mlib-run.lua @@ -444,10 +444,10 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, if trace_tracingall then mpx:execute("tracingall;") end --- table.insert(data,2,"") + -- table.insert(data,2,"") for i=1,#data do local d = data[i] --- d = string.gsub(d,"\r","") + -- d = string.gsub(d,"\r","") if d then if trace_graphics then mp_inp[mpx]:write(format("\n%% begin snippet %s\n",i)) diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf Binary files differindex 6fb7f16c3..4803e083f 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf Binary files differindex 19170f8b0..a0bbca101 100644 --- a/tex/context/base/status-lua.pdf +++ b/tex/context/base/status-lua.pdf diff --git a/tex/context/base/typo-del.mkiv b/tex/context/base/typo-del.mkiv index 8dfb2d461..b48c71e58 100644 --- a/tex/context/base/typo-del.mkiv +++ b/tex/context/base/typo-del.mkiv @@ -476,6 +476,7 @@ \fi \strut % new, needed below \delimitedtextparameter#1% unhbox\scratchbox + \penalty\plustenthousand % new per 2013-03-09 WS mailing list \hskip\d_typo_delimited_signal % +- \prewordbreak \fi \endgroup} diff --git a/tex/context/base/typo-prc.lua b/tex/context/base/typo-prc.lua index bb965ff66..ae9b541bf 100644 --- a/tex/context/base/typo-prc.lua +++ b/tex/context/base/typo-prc.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['typo-prc'] = { -- moved from strc-ini.lua -local format = string.format +local formatters = string.formatters local lpegmatch, patterns, P, C, Cs = lpeg.match, lpeg.patterns, lpeg.P, lpeg.C, lpeg.Cs -- processors: syntax: processor->data ... not ok yet @@ -108,7 +108,7 @@ end function processors.tostring(str) local p, s = lpegmatch(splitter,str) if registered[p] then - return format("\\applyprocessor{%s}{%s}",p,s) + return formatters["\\applyprocessor{%s}{%s}"](p,s) else return str end diff --git a/tex/context/base/util-fmt.lua b/tex/context/base/util-fmt.lua index e049d0b94..371a5dfce 100644 --- a/tex/context/base/util-fmt.lua +++ b/tex/context/base/util-fmt.lua @@ -14,28 +14,8 @@ local concat, format = table.concat, string.format local tostring, type = tostring, type local strip = string.strip -local P, R, Cs = lpeg.P, lpeg.R, lpeg.Cs local lpegmatch = lpeg.match - --- temporary here - -local digit = R("09") -local period = P(".") -local zero = P("0") -local trailingzeros = zero^0 * -digit -- suggested by Roberto R -local case_1 = period * trailingzeros / "" -local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") -local number = digit^1 * (case_1 + case_2) -local stripper = Cs((number + 1)^0) - ---~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" ---~ collectgarbage("collect") ---~ str = string.rep(sample,10000) ---~ local ts = os.clock() ---~ lpegmatch(stripper,str) ---~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) - -lpeg.patterns.stripzeros = stripper +local stripper = lpeg.patterns.stripzeros function formatters.stripzeros(str) return lpegmatch(stripper,str) diff --git a/tex/context/base/util-lua.lua b/tex/context/base/util-lua.lua index 36daaff55..96101f8ec 100644 --- a/tex/context/base/util-lua.lua +++ b/tex/context/base/util-lua.lua @@ -7,6 +7,8 @@ if not modules then modules = { } end modules ['util-lua'] = { license = "see context related readme files" } +-- we will remove the 5.1 code some day soon + local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format local load, loadfile, type = load, loadfile, type @@ -126,6 +128,13 @@ if jit or status.luatex_version >= 74 then return done end + function luautilities.loadstripped(...) + local l = load(...) + if l then + return load(dump(l,true)) + end + end + else -- The next function was posted by Peter Cawley on the lua list and strips line @@ -319,6 +328,8 @@ else return done end + luautilities.loadstripped = loadstring + end -- local getmetatable, type = getmetatable, type diff --git a/tex/context/base/util-seq.lua b/tex/context/base/util-seq.lua index 0bf056365..27f95f0ee 100644 --- a/tex/context/base/util-seq.lua +++ b/tex/context/base/util-seq.lua @@ -258,7 +258,7 @@ compile = function(t,compiler,n) -- already referred to in sequencers.new if compiled == "" then runner = false else - runner = compiled and load(compiled)() + runner = compiled and load(compiled)() -- we can use loadstripped here end t.runner = runner return runner diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua index a4889d252..959955867 100644 --- a/tex/context/base/util-str.lua +++ b/tex/context/base/util-str.lua @@ -10,14 +10,18 @@ utilities = utilities or {} utilities.strings = utilities.strings or { } local strings = utilities.strings -local load = load local format, gsub, rep, sub = string.format, string.gsub, string.rep, string.sub +local load, dump = load, string.dump local concat = table.concat -local P, V, C, S, R, Ct, Cs, Cp, Carg = lpeg.P, lpeg.V, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cs, lpeg.Cp, lpeg.Carg +local P, V, C, S, R, Ct, Cs, Cp, Carg, Cc = lpeg.P, lpeg.V, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cs, lpeg.Cp, lpeg.Carg, lpeg.Cc local patterns, lpegmatch = lpeg.patterns, lpeg.match local utfchar, utfbyte = utf.char, utf.byte -local setmetatableindex = table.setmetatableindex --- +----- loadstripped = utilities.lua.loadstripped +----- setmetatableindex = table.setmetatableindex + +local loadstripped = _LUAVERSION < 5.2 and load or function(str) + return load(dump(load(str),true)) -- it only makes sense in luajit and luatex where we have a stipped load +end local stripper = patterns.stripzeros @@ -65,7 +69,7 @@ function strings.newrepeater(str,offset) return t end t = { } - setmetatableindex(t, function(t,k) + setmetatable(t, { __index = function(t,k) if not k then return "" end @@ -73,7 +77,7 @@ function strings.newrepeater(str,offset) local s = n > 0 and rep(str,n) or "" t[k] = s return s - end) + end }) s[offset] = t return t end @@ -85,6 +89,8 @@ local extra, tab, start = 0, 0, 4, 0 local nspaces = strings.newrepeater(" ") +string.nspaces = nspaces + local pattern = Carg(1) / function(t) extra, tab, start = 0, t or 7, 1 @@ -144,6 +150,13 @@ end -- Work in progress. Interesting is that compared to the built-in this -- is faster in luatex than in luajittex where we have a comparable speed. +-- It only makes sense to use the formatter when a (somewhat) complex format +-- is used a lot. Each formatter is a function so there is some overhead +-- and not all formatted output is worth that overhead. Keep in mind that +-- there is an extra function call involved. In principle we end up with a +-- string concatination so one could inline such a sequence but often at the +-- cost of less readabinity. So, it's a sort of (visual) compromise. Of course +-- there is the benefit of more variants. local n = 0 @@ -155,6 +168,20 @@ local n = 0 -- print(...,...,...) -- 1,1,1,2,3 -- end +local template_shortcuts = [[ +local tostring = tostring +local format = string.format +local concat = table.concat +local signed = number.signed +local points = number.points +local basepoints = number.basepoints +local utfchar = utf.char +local utfbyte = utf.byte +local lpegmatch = lpeg.match +local xmlescape = lpeg.patterns.xmlescape +local spaces = string.nspaces +]] + local prefix_any = C((S("+- .") + R("09"))^0) local prefix_tab = C((1-R("az","AZ","09","%%"))^0) @@ -163,23 +190,37 @@ local prefix_tab = C((1-R("az","AZ","09","%%"))^0) local format_s = function(f) n = n + 1 if f and f ~= "" then - return format("format('%%%ss',(select(%s,...)))",f,n) + return format("format('%%%ss',a%s)",f,n) + else + return format("a%s",n) + end +end + +local format_S = function(f) -- can be optimized + n = n + 1 + if f and f ~= "" then + return format("format('%%%ss',tostring(a%s))",f,n) else - return format("(select(%s,...))",n) + return format("tostring(a%s)",n) end end local format_q = function() n = n + 1 - return format("format('%%q',(select(%s,...)))",n) -- maybe an own lpeg + return format("format('%%q',a%s)",n) -- maybe an own lpeg +end + +local format_Q = function() -- can be optimized + n = n + 1 + return format("format('%%q',tostring(a%s))",n) end local format_i = function(f) n = n + 1 if f and f ~= "" then - return format("format('%%%si',(select(%s,...)))",f,n) + return format("format('%%%si',a%s)",f,n) else - return format("(select(%s,...))",n) + return format("a%s",n) end end @@ -196,79 +237,79 @@ end local format_I = function(f) n = n + 1 if f and f ~= "" then - return format("format('%%s%%%si',signed((select(%s,...))))",f,n) + return format("format('%%s%%%si',signed(a%s))",f,n) else - return format("format('%%s%%i',signed((select(%s,...))))",n) + return format("format('%%s%%i',signed(a%s))",n) end end local format_f = function(f) n = n + 1 - return format("format('%%%sf',(select(%s,...)))",f,n) + return format("format('%%%sf',a%s)",f,n) end local format_g = function(f) n = n + 1 - return format("format('%%%sg',(select(%s,...)))",f,n) + return format("format('%%%sg',a%s)",f,n) end local format_G = function(f) n = n + 1 - return format("format('%%%sG',(select(%s,...)))",f,n) + return format("format('%%%sG',a%s)",f,n) end local format_e = function(f) n = n + 1 - return format("format('%%%se',(select(%s,...)))",f,n) + return format("format('%%%se',a%s)",f,n) end local format_E = function(f) n = n + 1 - return format("format('%%%sE',(select(%s,...)))",f,n) + return format("format('%%%sE',a%s)",f,n) end local format_x = function(f) n = n + 1 - return format("format('%%%sx',(select(%s,...)))",f,n) + return format("format('%%%sx',a%s)",f,n) end local format_X = function(f) n = n + 1 - return format("format('%%%sX',(select(%s,...)))",f,n) + return format("format('%%%sX',a%s)",f,n) end local format_o = function(f) n = n + 1 - return format("format('%%%so',(select(%s,...)))",f,n) + return format("format('%%%so',a%s)",f,n) end local format_c = function() n = n + 1 - return format("utfchar((select(%s,...)))",n) + return format("utfchar(a%s)",n) end local format_r = function(f) n = n + 1 - return format("format('%%%s.0f',(select(%s,...)))",f,n) + return format("format('%%%s.0f',a%s)",f,n) end -local format_v = function(f) +local format_h = function(f) n = n + 1 if f == "-" then f = sub(f,2) - return format("format('%%%sx',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('%%%sx',utfbyte(a%s))",f == "" and "05" or f,n) else - return format("format('0x%%%sx',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('0x%%%sx',utfbyte(a%s))",f == "" and "05" or f,n) end end -local format_V = function(f) +local format_H = function(f) n = n + 1 if f == "-" then f = sub(f,2) - return format("format('%%%sX',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('%%%sX',utfbyte(a%s))",f == "" and "05" or f,n) else - return format("format('0x%%%sX',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('0x%%%sX',utfbyte(a%s))",f == "" and "05" or f,n) end end @@ -276,9 +317,9 @@ local format_u = function(f) n = n + 1 if f == "-" then f = sub(f,2) - return format("format('%%%sx',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('%%%sx',utfbyte(a%s))",f == "" and "05" or f,n) else - return format("format('u+%%%sx',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('u+%%%sx',utfbyte(a%s))",f == "" and "05" or f,n) end end @@ -286,57 +327,117 @@ local format_U = function(f) n = n + 1 if f == "-" then f = sub(f,2) - return format("format('%%%sX',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('%%%sX',utfbyte(a%s))",f == "" and "05" or f,n) else - return format("format('U+%%%sX',utfbyte((select(%s,...))))",f == "" and "05" or f,n) + return format("format('U+%%%sX',utfbyte(a%s))",f == "" and "05" or f,n) end end local format_p = function() n = n + 1 - return format("points((select(%s,...)))",n) + return format("points(a%s)",n) end local format_b = function() n = n + 1 - return format("basepoints((select(%s,...)))",n) + return format("basepoints(a%s)",n) end local format_t = function(f) n = n + 1 if f and f ~= "" then - return format("concat((select(%s,...)),%q)",n,f) + return format("concat(a%s,%q)",n,f) else - return format("concat((select(%s,...)))",n) + return format("concat(a%s)",n) end end local format_l = function() n = n + 1 - return format("(select(%s,...) and 'true' or 'false')",n) + return format("(a%s and 'true' or 'false')",n) +end + +local format_L = function() + n = n + 1 + return format("(a%s and 'TRUE' or 'FALSE')",n) +end + +local format_N = function() -- strips leading zeros + n = n + 1 + return format("tostring(tonumber(a%s) or a%s)",n,n) end local format_a = function(s) return format("%q",s) end -local builder = Ct { "start", - start = (P("%") * ( - V("s") + V("q") - + V("i") + V("d") - + V("f") + V("g") + V("G") + V("e") + V("E") - + V("x") + V("X") + V("o") - -- - + V("c") - -- - + V("r") - + V("v") + V("V") + V("u") + V("U") - + V("p") + V("b") - + V("t") - + V("l") - + V("I") - ) - + V("a") +local format_w = function(f) -- handy when doing depth related indent + n = n + 1 + f = tonumber(f) + if f then + return format("spaces[%s+tonumber(a%s)]",f,n) + else + return format("spaces[tonumber(a%s)]",n) + end +end + +local format_W = function(f) -- handy when doing depth related indent + return format("spaces[%s]",tonumber(f) or 0) +end + +local extensions = { } + +local format_extension = function(name) + n = n + 1 + local extension = extensions[name] or "tostring(%s)" + return format(extension,format("a%s",n)) +end + +function addextension(name,template,shortcuts) + extensions[name] = template + if shortcuts then + template_shortcuts = shortcuts .. "\n" .. template_shortcuts -- so we can't overload + end +end + +lpeg.patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + P(1))^0) +lpeg.patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0) + +addextension("xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +addextension("tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) + +local builder = Cs { "start", + start = ( + ( + P("%") / "" + * ( + V("!") -- new + + V("s") + V("q") + + V("i") + V("d") + + V("f") + V("g") + V("G") + V("e") + V("E") + + V("x") + V("X") + V("o") + -- + + V("c") + + V("S") -- new + + V("Q") -- new + + V("N") -- new + -- + + V("r") + + V("h") + V("H") + V("u") + V("U") + + V("p") + V("b") + + V("t") + + V("l") + V("L") + + V("I") + + V("h") -- new + + V("w") -- new + + V("W") -- new + -- + + V("a") -- ignores probably messed up % + ) + + V("a") + ) +-- * (P(-1) + Cc("..")) + * (P(-1) + Carg(1)) )^0, -- ["s"] = (prefix_any * P("s")) / format_s, -- %s => regular %s (string) @@ -352,61 +453,132 @@ local builder = Ct { "start", ["X"] = (prefix_any * P("X")) / format_X, -- %X => regular %X (HEXADECIMAL) ["o"] = (prefix_any * P("o")) / format_o, -- %o => regular %o (octal) -- + ["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring) + ["Q"] = (prefix_any * P("Q")) / format_S, -- %Q => %q (tostring) + ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros) ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular) -- ["r"] = (prefix_any * P("r")) / format_r, -- %r => round - ["v"] = (prefix_any * P("v")) / format_v, -- %v => 0x0a1b2 (when - no 0x) - ["V"] = (prefix_any * P("V")) / format_V, -- %V => 0x0A1B2 (when - no 0x) + ["h"] = (prefix_any * P("h")) / format_h, -- %h => 0x0a1b2 (when - no 0x) was v + ["H"] = (prefix_any * P("H")) / format_H, -- %H => 0x0A1B2 (when - no 0x) was V ["u"] = (prefix_any * P("u")) / format_u, -- %u => u+0a1b2 (when - no u+) ["U"] = (prefix_any * P("U")) / format_U, -- %U => U+0A1B2 (when - no U+) ["p"] = (prefix_any * P("p")) / format_p, -- %p => 12.345pt / maybe: P (and more units) ["b"] = (prefix_any * P("b")) / format_b, -- %b => 12.342bp / maybe: B (and more units) ["t"] = (prefix_tab * P("t")) / format_t, -- %t => concat ["l"] = (prefix_tab * P("l")) / format_l, -- %l => boolean + ["L"] = (prefix_tab * P("L")) / format_L, -- %L => BOOLEAN ["I"] = (prefix_any * P("I")) / format_I, -- %I => signed integer -- - ["a"] = Cs(((1-P("%"))^1 + P("%%")/"%%")^1) / format_a, -- %a => text (including %%) + ["w"] = (prefix_any * P("w")) / format_w, -- %w => n spaces (optional prefix is added) + ["W"] = (prefix_any * P("W")) / format_W, -- %w => mandate prefix, no specifier + -- + ["a"] = Cs(((1-P("%"))^1 + P("%%")/"%%%%")^1) / format_a, -- rest (including %%) + -- + -- ["!"] = P("!xml!") / format_xml, -- %!xml! => hypertext escaped " < > & + ["!"] = P("!") * C((1-P("!"))^1) * P("!") / format_extension, } -- we can be clever and only alias what is needed -local template = [[ -local format = string.format -local concat = table.concat -local signed = number.signed -local points = number.points -local basepoints = number.basepoints -local utfchar = utf.char -local utfbyte = utf.byte -return function(...) - return %s -end +local direct = Cs ( + P("%")/"" + * Cc([[local format = string.format return function(str) return format("%]]) + * C(S("+- .") + R("09"))^0 * S("sqidfgGeExXo") + * Cc([[",str) end]]) + * P(-1) + ) + +local template = [[ +%s +return function(%s) return %s end ]] +local arguments = { "a1" } -- faster than previously used (select(n,...)) + +setmetatable(arguments, { __index = + function(t,k) + local v = t[k-1] .. ",a" .. k + t[k] = v + return v + end +}) + local function make(t,str) - n = 0 - local p = lpegmatch(builder,str) --- inspect(p) - local c = format(template,concat(p,"..")) --- inspect(c) - formatter = load(c)() - t[str] = formatter - return formatter + local f + local p = lpegmatch(direct,str) + if p then + f = loadstripped(p)() + else + n = 0 + p = lpegmatch(builder,str,1,"..") -- after this we know n + if n > 0 then + p = format(template,template_shortcuts,arguments[n],p) + -- print("builder>",p) + f = loadstripped(p)() + else + f = function() return str end + end + end + t[str] = f + return f +end + +local function use(t,fmt,...) + return t[fmt](...) end local formatters = string.formatters or { } string.formatters = formatters -setmetatableindex(formatters,make) +setmetatable(formatters, { __index = make, __call = use }) -function string.makeformatter(str) +-- -- yes or no: +-- +-- local function make(t,str) +-- local f +-- local p = lpegmatch(direct,str) +-- if p then +-- f = loadstripped(p)() +-- else +-- n = 0 +-- p = lpegmatch(builder,str,1,",") -- after this we know n +-- if n > 0 then +-- p = format(template,template_shortcuts,arguments[n],p) +-- f = loadstripped(p)() +-- else +-- f = function() return str end +-- end +-- end +-- t[str] = f +-- return f +-- end +-- +-- local formatteds = string.formatteds or { } +-- string.formatteds = formatteds +-- +-- setmetatable(formatteds, { __index = make, __call = use }) + +-- + +-- print(formatters["hans %N and %N done"](123,"0123")) +-- local test = formatters["1%%23%4w56%s78 %p %!xml! test and %!tex! more %s"] +-- print(#string.dump(test)) +-- print(test(2,123,99999,"abc&def","# and $","okay","!!!")) +-- local test = formatters["%s"] +-- print(#string.dump(test)) +-- print(test("okay")) + +function string.makeformatter(str) -- redundant return formatters[str] end -function string.formatter(str,...) +function string.formatter(str,...) -- redundant return formatters[str](...) end +string.addformatter = addextension + -- local p1 = "%s test %f done %p and %c and %V or %+t or %%" -- local p2 = "%s test %f done %s and %s and 0x%05X or %s or %%" -- diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index 539d70d1b..9efdae4d6 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -10,12 +10,13 @@ utilities = utilities or {} utilities.tables = utilities.tables or { } local tables = utilities.tables -local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub +local format, gmatch, gsub = string.format, string.gmatch, string.gsub local concat, insert, remove = table.concat, table.insert, table.remove local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring -local type, next, rawset, tonumber, load, select = type, next, rawset, tonumber, load, select -local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs -local serialize = table.serialize +local type, next, rawset, tonumber, tostring, load, select = type, next, rawset, tonumber, tostring, load, select +local lpegmatch, P, Cs, Cc = lpeg.match, lpeg.P, lpeg.Cs, lpeg.Cc +local serialize, sortedkeys, sortedpairs = table.serialize, table.sortedkeys, table.sortedpairs +local formatters = string.formatters local splitter = lpeg.tsplitat(".") @@ -126,35 +127,131 @@ end -- experimental +local escape = Cs(Cc('"') * ((P('"')/'""' + P(1))^0) * Cc('"')) + +function table.tocsv(t,specification) + if t and #t > 0 then + local result = { } + local r = { } + specification = specification or { } + local fields = specification.fields + if type(fields) ~= "string" then + fields = sortedkeys(t[1]) + end + local separator = specification.separator or "," + if specification.preamble == true then + for f=1,#fields do + r[f] = lpegmatch(escape,tostring(fields[f])) + end + result[1] = concat(r,separator) + end + for i=1,#t do + local ti = t[i] + for f=1,#fields do + local field = ti[fields[f]] + if type(field) == "string" then + r[f] = lpegmatch(escape,field) + else + r[f] = tostring(field) + end + end + result[#result+1] = concat(r,separator) + end + return concat(result,"\n") + else + return "" + end +end + +-- local nspaces = utilities.strings.newrepeater(" ") +-- local escape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P(1))^0) +-- +-- local function toxml(t,d,result,step) +-- for k, v in sortedpairs(t) do +-- local s = nspaces[d] +-- local tk = type(k) +-- local tv = type(v) +-- if tv == "table" then +-- if tk == "number" then +-- result[#result+1] = format("%s<entry n='%s'>",s,k) +-- toxml(v,d+step,result,step) +-- result[#result+1] = format("%s</entry>",s,k) +-- else +-- result[#result+1] = format("%s<%s>",s,k) +-- toxml(v,d+step,result,step) +-- result[#result+1] = format("%s</%s>",s,k) +-- end +-- elseif tv == "string" then +-- if tk == "number" then +-- result[#result+1] = format("%s<entry n='%s'>%s</entry>",s,k,lpegmatch(escape,v),k) +-- else +-- result[#result+1] = format("%s<%s>%s</%s>",s,k,lpegmatch(escape,v),k) +-- end +-- elseif tk == "number" then +-- result[#result+1] = format("%s<entry n='%s'>%s</entry>",s,k,tostring(v),k) +-- else +-- result[#result+1] = format("%s<%s>%s</%s>",s,k,tostring(v),k) +-- end +-- end +-- end +-- +-- much faster + +local nspaces = utilities.strings.newrepeater(" ") + local function toxml(t,d,result,step) - for k, v in table.sortedpairs(t) do - if type(v) == "table" then - if type(k) == "number" then - result[#result+1] = format("%s<entry n='%s'>",d,k) - toxml(v,d..step,result,step) - result[#result+1] = format("%s</entry>",d,k) + for k, v in sortedpairs(t) do + local s = nspaces[d] -- inlining this is somewhat faster but gives more formatters + local tk = type(k) + local tv = type(v) + if tv == "table" then + if tk == "number" then + result[#result+1] = formatters["%s<entry n='%s'>"](s,k) + toxml(v,d+step,result,step) + result[#result+1] = formatters["%s</entry>"](s,k) + else + result[#result+1] = formatters["%s<%s>"](s,k) + toxml(v,d+step,result,step) + result[#result+1] = formatters["%s</%s>"](s,k) + end + elseif tv == "string" then + if tk == "number" then + result[#result+1] = formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k) else - result[#result+1] = format("%s<%s>",d,k) - toxml(v,d..step,result,step) - result[#result+1] = format("%s</%s>",d,k) + result[#result+1] = formatters["%s<%s>%!xml!</%s>"](s,k,v,k) end - elseif type(k) == "number" then - result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k) + elseif tk == "number" then + result[#result+1] = formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k) else - result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k) + result[#result+1] = formatters["%s<%s>%S</%s>"](s,k,v,k) end end end -function table.toxml(t,name,nobanner,indent,spaces) +-- function table.toxml(t,name,nobanner,indent,spaces) +-- local noroot = name == false +-- local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" } +-- local indent = rep(" ",indent or 0) +-- local spaces = rep(" ",spaces or 1) +-- if noroot then +-- toxml( t, inndent, result, spaces) +-- else +-- toxml( { [name or "root"] = t }, indent, result, spaces) +-- end +-- return concat(result,"\n") +-- end + +function table.toxml(t,specification) + specification = specification or { } + local name = specification.name local noroot = name == false - local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" } - local indent = rep(" ",indent or 0) - local spaces = rep(" ",spaces or 1) + local result = (specification.nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" } + local indent = specification.indent or 0 + local spaces = specification.spaces or 1 if noroot then - toxml( t, inndent, result, spaces) + toxml( t, indent, result, spaces) else - toxml( { [name or "root"] = t }, indent, result, spaces) + toxml( { [name or "data"] = t }, indent, result, spaces) end return concat(result,"\n") end @@ -204,27 +301,27 @@ local function fastserialize(t,r,outer) -- no mixes local v = t[i] local tv = type(v) if tv == "string" then - r[#r+1] = format("%q,",v) + r[#r+1] = formatters["%q,"](v) elseif tv == "number" then - r[#r+1] = format("%s,",v) + r[#r+1] = formatters["%s,"](v) elseif tv == "table" then fastserialize(v,r) elseif tv == "boolean" then - r[#r+1] = format("%s,",tostring(v)) + r[#r+1] = formatters["%S,"](v) end end else for k, v in next, t do local tv = type(v) if tv == "string" then - r[#r+1] = format("[%q]=%q,",k,v) + r[#r+1] = formatters["[%q]=%q,"](k,v) elseif tv == "number" then - r[#r+1] = format("[%q]=%s,",k,v) + r[#r+1] = formatters["[%q]=%s,"](k,v) elseif tv == "table" then - r[#r+1] = format("[%q]=",k) + r[#r+1] = formatters["[%q]="](k) fastserialize(v,r) elseif tv == "boolean" then - r[#r+1] = format("[%q]=%s,",k,tostring(v)) + r[#r+1] = formatters["[%q]=%S,"](k,v) end end end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 28859a963..1013f5467 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 03/08/13 01:14:04 +-- merge date : 03/10/13 14:36:13 do -- begin closure to overcome local limits and interference @@ -564,6 +564,15 @@ end function lpeg.times(pattern,n) return P(nextstep(n,2^16,{ "start",["1"]=pattern })) end +local digit=R("09") +local period=P(".") +local zero=P("0") +local trailingzeros=zero^0*-digit +local case_1=period*trailingzeros/"" +local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"") +local number=digit^1*(case_1+case_2) +local stripper=Cs((number+1)^0) +lpeg.patterns.stripzeros=stripper end -- closure |