diff options
33 files changed, 2394 insertions, 1372 deletions
diff --git a/context/data/scite/lexers/scite-context-lexer-lua.lua b/context/data/scite/lexers/scite-context-lexer-lua.lua index a2d909e5a..572379416 100644 --- a/context/data/scite/lexers/scite-context-lexer-lua.lua +++ b/context/data/scite/lexers/scite-context-lexer-lua.lua @@ -45,7 +45,17 @@ local functions = { } local constants = { - '_G', '_VERSION', '_M', "...", '_ENV' + '_G', '_VERSION', '_M', '...', '_ENV', + -- here too + '__add', '__call', '__concat', '__div', '__eq', '__gc', '__index', + '__le', '__lt', '__metatable', '__mode', '__mul', '__newindex', + '__pow', '__sub', '__tostring', '__unm', +} + +local internals = { -- __ + 'add', 'call', 'concat', 'div', 'eq', 'gc', 'index', + 'le', 'lt', 'metatable', 'mode', 'mul', 'newindex', + 'pow', 'sub', 'tostring', 'unm', } local depricated = { @@ -165,18 +175,25 @@ local gotolabel = token("keyword", P("::")) local p_keywords = exact_match(keywords ) local p_functions = exact_match(functions) local p_constants = exact_match(constants) +local p_internals = P("__") + * exact_match(internals) local p_csnames = exact_match(csnames ) local keyword = token("keyword", p_keywords) local builtin = token("plain", p_functions) local constant = token("data", p_constants) +local internal = token("data", p_internals) local csname = token("user", p_csnames) * ( optionalspace * hasargument + ( optionalspace * token("special", S(".:")) * optionalspace * token("user", validword) )^1 ) local identifier = token("default", validword) - * ( optionalspace * token("special", S(".:")) * optionalspace * (token("warning", p_keywords) + token("default", validword)) )^0 + * ( optionalspace * token("special", S(".:")) * optionalspace * ( + token("warning", p_keywords) + + token("data", p_internals) + + token("default", validword ) + ) )^0 lualexer._rules = { { 'whitespace', spacing }, diff --git a/context/data/scite/scite-context-data-metafun.properties b/context/data/scite/scite-context-data-metafun.properties index 80cb13417..c5aa4cbed 100644 --- a/context/data/scite/scite-context-data-metafun.properties +++ b/context/data/scite/scite-context-data-metafun.properties @@ -1,3 +1,10 @@ +keywordclass.metafun.internals=\ +nocolormodel greycolormodel graycolormodel rgbcolormodel \ +cmykcolormodel shadefactor textextoffset normaltransparent multiplytransparent \ +screentransparent overlaytransparent softlighttransparent hardlighttransparent colordodgetransparent \ +colorburntransparent darkentransparent lightentransparent differencetransparent exclusiontransparent \ +huetransparent saturationtransparent colortransparent luminositytransparent metapostversion + keywordclass.metafun.commands=\ sqr log ln exp \ inv pow pi radian tand \ @@ -45,10 +52,3 @@ drawpoints drawcontrolpoints drawcontrollines drawpointlabels drawlineoptions \ drawpointoptions drawcontroloptions drawlabeloptions draworiginoptions drawboundoptions \ drawpathoptions resetdrawoptions decorated redecorated undecorated -keywordclass.metafun.internals=\ -nocolormodel greycolormodel graycolormodel rgbcolormodel \ -cmykcolormodel shadefactor textextoffset normaltransparent multiplytransparent \ -screentransparent overlaytransparent softlighttransparent hardlighttransparent colordodgetransparent \ -colorburntransparent darkentransparent lightentransparent differencetransparent exclusiontransparent \ -huetransparent saturationtransparent colortransparent luminositytransparent metapostversion - diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua index 37e5e77d4..61aebe9b5 100644 --- a/scripts/context/lua/mtx-context.lua +++ b/scripts/context/lua/mtx-context.lua @@ -697,6 +697,7 @@ function scripts.context.run(ctxdata,filename) -- c_flags.final = false c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2 + c_flags.maxnofruns = maxnofruns c_flags.currentrun = currentrun c_flags.noarrange = a_noarrange or a_arrange or nil -- diff --git a/scripts/context/lua/mtxlibs.lua b/scripts/context/lua/mtxlibs.lua index 59cfa3dc2..732c9a0af 100644 --- a/scripts/context/lua/mtxlibs.lua +++ b/scripts/context/lua/mtxlibs.lua @@ -83,9 +83,9 @@ local ownlibs = { "l-unicode.lua", -- nowadays independent of slunicode "l-math.lua", + "util-str.lua", "util-tab.lua", "util-sto.lua", - "util-str.lua", "util-mrg.lua", -- "util-lua.lua", -- no need for compiling "util-prs.lua", diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index d1a0887f2..ee01afe35 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lua"] = package.loaded["l-lua"] or true --- original size: 7937, stripped down to: 5418 +-- original size: 7986, stripped down to: 5461 if not modules then modules={} end modules ['l-lua']={ version=1.001, @@ -68,6 +68,7 @@ if not modules then modules={} end modules ['l-lua']={ local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") _MAJORVERSION=tonumber(major) or 5 _MINORVERSION=tonumber(minor) or 1 +_LUAVERSION=_MAJORVERSION+_MINORVERSION/10 if not lpeg then lpeg=require("lpeg") end @@ -274,7 +275,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 25591, stripped down to: 14143 +-- original size: 26334, stripped down to: 14439 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -836,6 +837,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 -- of closure @@ -964,7 +974,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 29337, stripped down to: 19618 +-- original size: 44480, stripped down to: 19618 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -4268,9 +4278,407 @@ end -- of closure do -- create closure to overcome 200 locals limit +package.loaded["util-str"] = package.loaded["util-str"] or true + +-- original size: 17245, stripped down to: 10055 + +if not modules then modules={} end modules ['util-str']={ + version=1.001, + comment="companion to luat-lib.mkiv", + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files" +} +utilities=utilities or {} +utilities.strings=utilities.strings or {} +local strings=utilities.strings +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,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 loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) +end +local stripper=patterns.stripzeros +local function points(n) + return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) +end +local function basepoints(n) + return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) +end +number.points=points +number.basepoints=basepoints +local rubish=patterns.spaceortab^0*patterns.newline +local anyrubish=patterns.spaceortab+patterns.newline +local anything=patterns.anything +local stripped=(patterns.spaceortab^1/"")*patterns.newline +local leading=rubish^0/"" +local trailing=(anyrubish^1*patterns.endofstring)/"" +local redundant=rubish^3/"\n" +local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) +function strings.collapsecrlf(str) + return lpegmatch(pattern,str) +end +local repeaters={} +function strings.newrepeater(str,offset) + offset=offset or 0 + local s=repeaters[str] + if not s then + s={} + repeaters[str]=s + end + local t=s[offset] + if t then + return t + end + t={} + setmetatable(t,{ __index=function(t,k) + if not k then + return "" + end + local n=k+offset + local s=n>0 and rep(str,n) or "" + t[k]=s + return s + end }) + s[offset]=t + return t +end +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 + end*Cs(( + Cp()*patterns.tab/function(position) + local current=(position-start+1)+extra + local spaces=tab-(current-1)%tab + if spaces>0 then + extra=extra+spaces-1 + return nspaces[spaces] + else + return "" + end + end+patterns.newline*Cp()/function(position) + extra,start=0,position + end+patterns.anything + )^1) +function strings.tabtospace(str,tab) + return lpegmatch(pattern,str,1,tab or 7) +end +function strings.striplong(str) + str=gsub(str,"^%s*","") + str=gsub(str,"[\n\r]+ *","\n") + return str +end +function strings.nice(str) + str=gsub(str,"[:%-+_]+"," ") + return str +end +local n=0 +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) +local format_s=function(f) + n=n+1 + if f and f~="" then + return format("format('%%%ss',a%s)",f,n) + else + return format("a%s",n) + end +end +local format_S=function(f) + n=n+1 + if f and f~="" then + return format("format('%%%ss',tostring(a%s))",f,n) + else + return format("tostring(a%s)",n) + end +end +local format_q=function() + n=n+1 + return format("format('%%q',a%s)",n) +end +local format_Q=function() + 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',a%s)",f,n) + else + return format("a%s",n) + end +end +local format_d=format_i +function number.signed(i) + if i>0 then + return "+",i + else + return "-",-i + end +end +local format_I=function(f) + n=n+1 + if f and f~="" then + return format("format('%%s%%%si',signed(a%s))",f,n) + else + return format("format('%%s%%i',signed(a%s))",n) + end +end +local format_f=function(f) + n=n+1 + return format("format('%%%sf',a%s)",f,n) +end +local format_g=function(f) + n=n+1 + return format("format('%%%sg',a%s)",f,n) +end +local format_G=function(f) + n=n+1 + return format("format('%%%sG',a%s)",f,n) +end +local format_e=function(f) + n=n+1 + return format("format('%%%se',a%s)",f,n) +end +local format_E=function(f) + n=n+1 + return format("format('%%%sE',a%s)",f,n) +end +local format_x=function(f) + n=n+1 + return format("format('%%%sx',a%s)",f,n) +end +local format_X=function(f) + n=n+1 + return format("format('%%%sX',a%s)",f,n) +end +local format_o=function(f) + n=n+1 + return format("format('%%%so',a%s)",f,n) +end +local format_c=function() + n=n+1 + return format("utfchar(a%s)",n) +end +local format_r=function(f) + n=n+1 + return format("format('%%%s.0f',a%s)",f,n) +end +local format_h=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('0x%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_H=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('0x%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_u=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('u+%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_U=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + else + 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(a%s)",n) +end +local format_b=function() + n=n+1 + return format("basepoints(a%s)",n) +end +local format_t=function(f) + n=n+1 + if f and f~="" then + return format("concat(a%s,%q)",n,f) + else + return format("concat(a%s)",n) + end +end +local format_l=function() + n=n+1 + 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() + 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 format_w=function(f) + 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) + 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 + 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("!") ++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") ++V("Q") ++V("N") ++V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("l")+V("L")+V("I")+V("h") ++V("w") ++V("W") ++V("a") + )+V("a") + ) +*(P(-1)+Carg(1)) + )^0, + ["s"]=(prefix_any*P("s"))/format_s, + ["q"]=(prefix_any*P("q"))/format_q, + ["i"]=(prefix_any*P("i"))/format_i, + ["d"]=(prefix_any*P("d"))/format_d, + ["f"]=(prefix_any*P("f"))/format_f, + ["g"]=(prefix_any*P("g"))/format_g, + ["G"]=(prefix_any*P("G"))/format_G, + ["e"]=(prefix_any*P("e"))/format_e, + ["E"]=(prefix_any*P("E"))/format_E, + ["x"]=(prefix_any*P("x"))/format_x, + ["X"]=(prefix_any*P("X"))/format_X, + ["o"]=(prefix_any*P("o"))/format_o, + ["S"]=(prefix_any*P("S"))/format_S, + ["Q"]=(prefix_any*P("Q"))/format_S, + ["N"]=(prefix_any*P("N"))/format_N, + ["c"]=(prefix_any*P("c"))/format_c, + ["r"]=(prefix_any*P("r"))/format_r, + ["h"]=(prefix_any*P("h"))/format_h, + ["H"]=(prefix_any*P("H"))/format_H, + ["u"]=(prefix_any*P("u"))/format_u, + ["U"]=(prefix_any*P("U"))/format_U, + ["p"]=(prefix_any*P("p"))/format_p, + ["b"]=(prefix_any*P("b"))/format_b, + ["t"]=(prefix_tab*P("t"))/format_t, + ["l"]=(prefix_tab*P("l"))/format_l, + ["L"]=(prefix_tab*P("L"))/format_L, + ["I"]=(prefix_any*P("I"))/format_I, + ["w"]=(prefix_any*P("w"))/format_w, + ["W"]=(prefix_any*P("W"))/format_W, + ["a"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_a, + ["!"]=P("!")*C((1-P("!"))^1)*P("!")/format_extension, +} +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" } +setmetatable(arguments,{ __index=function(t,k) + local v=t[k-1]..",a"..k + t[k]=v + return v + end +}) +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,"..") + 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 function use(t,fmt,...) + return t[fmt](...) +end +local formatters=string.formatters or {} +string.formatters=formatters +setmetatable(formatters,{ __index=make,__call=use }) +function string.makeformatter(str) + return formatters[str] +end +function string.formatter(str,...) + return formatters[str](...) +end +string.addformatter=addextension + + +end -- of closure + +do -- create closure to overcome 200 locals limit + package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 10865, stripped down to: 7097 +-- original size: 14459, stripped down to: 8507 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -4282,12 +4690,13 @@ if not modules then modules={} end modules ['util-tab']={ 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(".") function tables.definetable(target,nofirst,nolast) local composed,shortcut,t=nil,nil,{} @@ -4384,34 +4793,80 @@ function tables.insertaftervalue(t,value,extra) end insert(t,#t+1,extra) end +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 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] + 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]=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>"](s,k) + toxml(v,d+step,result,step) + result[#result+1]=formatters["%s</%s>"](s,k) end - elseif type(k)=="number" then - result[#result+1]=format("%s<entry n='%s'>%s</entry>",d,k,v,k) + 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]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k) + end + 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,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 @@ -4453,27 +4908,27 @@ local function fastserialize(t,r,outer) 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 @@ -4729,307 +5184,6 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-str"] = package.loaded["util-str"] or true - --- original size: 12069, stripped down to: 7814 - -if not modules then modules={} end modules ['util-str']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -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 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 patterns,lpegmatch=lpeg.patterns,lpeg.match -local utfchar,utfbyte=utf.char,utf.byte -local setmetatableindex=table.setmetatableindex -local stripper=patterns.stripzeros -local function points(n) - return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end -local function basepoints(n) - return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) -end -number.points=points -number.basepoints=basepoints -local rubish=patterns.spaceortab^0*patterns.newline -local anyrubish=patterns.spaceortab+patterns.newline -local anything=patterns.anything -local stripped=(patterns.spaceortab^1/"")*patterns.newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*patterns.endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatableindex(t,function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+patterns.newline*Cp()/function(position) - extra,start=0,position - end+patterns.anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -function strings.striplong(str) - str=gsub(str,"^%s*","") - str=gsub(str,"[\n\r]+ *","\n") - return str -end -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local prefix_any=C((S("+- .")+R("09"))^0) -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) - else - return format("(select(%s,...))",n) - end -end -local format_q=function() - n=n+1 - return format("format('%%q',(select(%s,...)))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',(select(%s,...)))",f,n) - else - return format("(select(%s,...))",n) - end -end -local format_d=format_i -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local format_I=function(f) - n=n+1 - if f and f~="" then - return format("format('%%s%%%si',signed((select(%s,...))))",f,n) - else - return format("format('%%s%%i',signed((select(%s,...))))",n) - end -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',(select(%s,...)))",f,n) -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',(select(%s,...)))",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',(select(%s,...)))",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',(select(%s,...)))",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',(select(%s,...)))",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',(select(%s,...)))",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',(select(%s,...)))",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',(select(%s,...)))",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar((select(%s,...)))",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',(select(%s,...)))",f,n) -end -local format_v=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) - else - return format("format('0x%%%sx',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -local format_V=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) - else - return format("format('0x%%%sX',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -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) - else - return format("format('u+%%%sx',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -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) - else - return format("format('U+%%%sX',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -local format_p=function() - n=n+1 - return format("points((select(%s,...)))",n) -end -local format_b=function() - n=n+1 - return format("basepoints((select(%s,...)))",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat((select(%s,...)),%q)",n,f) - else - return format("concat((select(%s,...)))",n) - end -end -local format_l=function() - n=n+1 - return format("(select(%s,...) and 'true' or 'false')",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") - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["c"]=(prefix_any*P("c"))/format_c, - ["r"]=(prefix_any*P("r"))/format_r, - ["v"]=(prefix_any*P("v"))/format_v, - ["V"]=(prefix_any*P("V"))/format_V, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["b"]=(prefix_any*P("b"))/format_b, - ["t"]=(prefix_tab*P("t"))/format_t, - ["l"]=(prefix_tab*P("l"))/format_l, - ["I"]=(prefix_any*P("I"))/format_I, - ["a"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_a, -} -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 function make(t,str) - n=0 - local p=lpegmatch(builder,str) - local c=format(template,concat(p,"..")) - formatter=load(c)() - t[str]=formatter - return formatter -end -local formatters=string.formatters or {} -string.formatters=formatters -setmetatableindex(formatters,make) -function string.makeformatter(str) - return formatters[str] -end -function string.formatter(str,...) - return formatters[str](...) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - package.loaded["util-mrg"] = package.loaded["util-mrg"] or true -- original size: 7447, stripped down to: 6001 @@ -5202,7 +5356,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lua"] = package.loaded["util-lua"] or true --- original size: 12411, stripped down to: 8581 +-- original size: 12650, stripped down to: 8744 if not modules then modules={} end modules ['util-lua']={ version=1.001, @@ -5314,6 +5468,12 @@ if jit or status.luatex_version>=74 then end return done end + function luautilities.loadstripped(...) + local l=load(...) + if l then + return load(dump(l,true)) + end + end else local function register(name,before,after) local delta=before-after @@ -5478,6 +5638,7 @@ else end return done end + luautilities.loadstripped=loadstring end @@ -5879,7 +6040,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fmt"] = package.loaded["util-fmt"] or true --- original size: 3006, stripped down to: 2072 +-- original size: 2274, stripped down to: 1781 if not modules then modules={} end modules ['util-fmt']={ version=1.001, @@ -5894,17 +6055,8 @@ local formatters=utilities.formatters 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 -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 +local stripper=lpeg.patterns.stripzeros function formatters.stripzeros(str) return lpegmatch(stripper,str) end @@ -8663,7 +8815,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true --- original size: 48888, stripped down to: 30550 +-- original size: 48955, stripped down to: 30585 if not modules then modules={} end modules ['lxml-lpt']={ version=1.001, @@ -8677,6 +8829,7 @@ local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,to local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns local setmetatableindex=table.setmetatableindex +local formatters=string.formatters local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end @@ -15098,10 +15251,10 @@ end end -- of closure --- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-tab.lua util-sto.lua util-str.lua util-mrg.lua util-lua.lua util-prs.lua util-fmt.lua util-deb.lua trac-inf.lua trac-set.lua trac-log.lua trac-pro.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-mrg.lua util-lua.lua util-prs.lua util-fmt.lua util-deb.lua trac-inf.lua trac-set.lua trac-log.lua trac-pro.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 604381 --- stripped bytes : 205386 +-- original bytes : 628660 +-- stripped bytes : 225768 -- end library merge @@ -15141,9 +15294,9 @@ local ownlibs = { -- order can be made better 'l-unicode.lua', 'l-math.lua', + 'util-str.lua', -- code might move to l-string 'util-tab.lua', 'util-sto.lua', - 'util-str.lua', -- code might move to l-string 'util-mrg.lua', 'util-lua.lua', 'util-prs.lua', diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index d1a0887f2..ee01afe35 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lua"] = package.loaded["l-lua"] or true --- original size: 7937, stripped down to: 5418 +-- original size: 7986, stripped down to: 5461 if not modules then modules={} end modules ['l-lua']={ version=1.001, @@ -68,6 +68,7 @@ if not modules then modules={} end modules ['l-lua']={ local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") _MAJORVERSION=tonumber(major) or 5 _MINORVERSION=tonumber(minor) or 1 +_LUAVERSION=_MAJORVERSION+_MINORVERSION/10 if not lpeg then lpeg=require("lpeg") end @@ -274,7 +275,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 25591, stripped down to: 14143 +-- original size: 26334, stripped down to: 14439 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -836,6 +837,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 -- of closure @@ -964,7 +974,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 29337, stripped down to: 19618 +-- original size: 44480, stripped down to: 19618 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -4268,9 +4278,407 @@ end -- of closure do -- create closure to overcome 200 locals limit +package.loaded["util-str"] = package.loaded["util-str"] or true + +-- original size: 17245, stripped down to: 10055 + +if not modules then modules={} end modules ['util-str']={ + version=1.001, + comment="companion to luat-lib.mkiv", + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files" +} +utilities=utilities or {} +utilities.strings=utilities.strings or {} +local strings=utilities.strings +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,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 loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) +end +local stripper=patterns.stripzeros +local function points(n) + return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) +end +local function basepoints(n) + return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) +end +number.points=points +number.basepoints=basepoints +local rubish=patterns.spaceortab^0*patterns.newline +local anyrubish=patterns.spaceortab+patterns.newline +local anything=patterns.anything +local stripped=(patterns.spaceortab^1/"")*patterns.newline +local leading=rubish^0/"" +local trailing=(anyrubish^1*patterns.endofstring)/"" +local redundant=rubish^3/"\n" +local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) +function strings.collapsecrlf(str) + return lpegmatch(pattern,str) +end +local repeaters={} +function strings.newrepeater(str,offset) + offset=offset or 0 + local s=repeaters[str] + if not s then + s={} + repeaters[str]=s + end + local t=s[offset] + if t then + return t + end + t={} + setmetatable(t,{ __index=function(t,k) + if not k then + return "" + end + local n=k+offset + local s=n>0 and rep(str,n) or "" + t[k]=s + return s + end }) + s[offset]=t + return t +end +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 + end*Cs(( + Cp()*patterns.tab/function(position) + local current=(position-start+1)+extra + local spaces=tab-(current-1)%tab + if spaces>0 then + extra=extra+spaces-1 + return nspaces[spaces] + else + return "" + end + end+patterns.newline*Cp()/function(position) + extra,start=0,position + end+patterns.anything + )^1) +function strings.tabtospace(str,tab) + return lpegmatch(pattern,str,1,tab or 7) +end +function strings.striplong(str) + str=gsub(str,"^%s*","") + str=gsub(str,"[\n\r]+ *","\n") + return str +end +function strings.nice(str) + str=gsub(str,"[:%-+_]+"," ") + return str +end +local n=0 +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) +local format_s=function(f) + n=n+1 + if f and f~="" then + return format("format('%%%ss',a%s)",f,n) + else + return format("a%s",n) + end +end +local format_S=function(f) + n=n+1 + if f and f~="" then + return format("format('%%%ss',tostring(a%s))",f,n) + else + return format("tostring(a%s)",n) + end +end +local format_q=function() + n=n+1 + return format("format('%%q',a%s)",n) +end +local format_Q=function() + 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',a%s)",f,n) + else + return format("a%s",n) + end +end +local format_d=format_i +function number.signed(i) + if i>0 then + return "+",i + else + return "-",-i + end +end +local format_I=function(f) + n=n+1 + if f and f~="" then + return format("format('%%s%%%si',signed(a%s))",f,n) + else + return format("format('%%s%%i',signed(a%s))",n) + end +end +local format_f=function(f) + n=n+1 + return format("format('%%%sf',a%s)",f,n) +end +local format_g=function(f) + n=n+1 + return format("format('%%%sg',a%s)",f,n) +end +local format_G=function(f) + n=n+1 + return format("format('%%%sG',a%s)",f,n) +end +local format_e=function(f) + n=n+1 + return format("format('%%%se',a%s)",f,n) +end +local format_E=function(f) + n=n+1 + return format("format('%%%sE',a%s)",f,n) +end +local format_x=function(f) + n=n+1 + return format("format('%%%sx',a%s)",f,n) +end +local format_X=function(f) + n=n+1 + return format("format('%%%sX',a%s)",f,n) +end +local format_o=function(f) + n=n+1 + return format("format('%%%so',a%s)",f,n) +end +local format_c=function() + n=n+1 + return format("utfchar(a%s)",n) +end +local format_r=function(f) + n=n+1 + return format("format('%%%s.0f',a%s)",f,n) +end +local format_h=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('0x%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_H=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('0x%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_u=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('u+%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_U=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + else + 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(a%s)",n) +end +local format_b=function() + n=n+1 + return format("basepoints(a%s)",n) +end +local format_t=function(f) + n=n+1 + if f and f~="" then + return format("concat(a%s,%q)",n,f) + else + return format("concat(a%s)",n) + end +end +local format_l=function() + n=n+1 + 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() + 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 format_w=function(f) + 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) + 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 + 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("!") ++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") ++V("Q") ++V("N") ++V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("l")+V("L")+V("I")+V("h") ++V("w") ++V("W") ++V("a") + )+V("a") + ) +*(P(-1)+Carg(1)) + )^0, + ["s"]=(prefix_any*P("s"))/format_s, + ["q"]=(prefix_any*P("q"))/format_q, + ["i"]=(prefix_any*P("i"))/format_i, + ["d"]=(prefix_any*P("d"))/format_d, + ["f"]=(prefix_any*P("f"))/format_f, + ["g"]=(prefix_any*P("g"))/format_g, + ["G"]=(prefix_any*P("G"))/format_G, + ["e"]=(prefix_any*P("e"))/format_e, + ["E"]=(prefix_any*P("E"))/format_E, + ["x"]=(prefix_any*P("x"))/format_x, + ["X"]=(prefix_any*P("X"))/format_X, + ["o"]=(prefix_any*P("o"))/format_o, + ["S"]=(prefix_any*P("S"))/format_S, + ["Q"]=(prefix_any*P("Q"))/format_S, + ["N"]=(prefix_any*P("N"))/format_N, + ["c"]=(prefix_any*P("c"))/format_c, + ["r"]=(prefix_any*P("r"))/format_r, + ["h"]=(prefix_any*P("h"))/format_h, + ["H"]=(prefix_any*P("H"))/format_H, + ["u"]=(prefix_any*P("u"))/format_u, + ["U"]=(prefix_any*P("U"))/format_U, + ["p"]=(prefix_any*P("p"))/format_p, + ["b"]=(prefix_any*P("b"))/format_b, + ["t"]=(prefix_tab*P("t"))/format_t, + ["l"]=(prefix_tab*P("l"))/format_l, + ["L"]=(prefix_tab*P("L"))/format_L, + ["I"]=(prefix_any*P("I"))/format_I, + ["w"]=(prefix_any*P("w"))/format_w, + ["W"]=(prefix_any*P("W"))/format_W, + ["a"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_a, + ["!"]=P("!")*C((1-P("!"))^1)*P("!")/format_extension, +} +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" } +setmetatable(arguments,{ __index=function(t,k) + local v=t[k-1]..",a"..k + t[k]=v + return v + end +}) +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,"..") + 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 function use(t,fmt,...) + return t[fmt](...) +end +local formatters=string.formatters or {} +string.formatters=formatters +setmetatable(formatters,{ __index=make,__call=use }) +function string.makeformatter(str) + return formatters[str] +end +function string.formatter(str,...) + return formatters[str](...) +end +string.addformatter=addextension + + +end -- of closure + +do -- create closure to overcome 200 locals limit + package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 10865, stripped down to: 7097 +-- original size: 14459, stripped down to: 8507 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -4282,12 +4690,13 @@ if not modules then modules={} end modules ['util-tab']={ 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(".") function tables.definetable(target,nofirst,nolast) local composed,shortcut,t=nil,nil,{} @@ -4384,34 +4793,80 @@ function tables.insertaftervalue(t,value,extra) end insert(t,#t+1,extra) end +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 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] + 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]=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>"](s,k) + toxml(v,d+step,result,step) + result[#result+1]=formatters["%s</%s>"](s,k) end - elseif type(k)=="number" then - result[#result+1]=format("%s<entry n='%s'>%s</entry>",d,k,v,k) + 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]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k) + end + 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,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 @@ -4453,27 +4908,27 @@ local function fastserialize(t,r,outer) 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 @@ -4729,307 +5184,6 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-str"] = package.loaded["util-str"] or true - --- original size: 12069, stripped down to: 7814 - -if not modules then modules={} end modules ['util-str']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -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 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 patterns,lpegmatch=lpeg.patterns,lpeg.match -local utfchar,utfbyte=utf.char,utf.byte -local setmetatableindex=table.setmetatableindex -local stripper=patterns.stripzeros -local function points(n) - return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end -local function basepoints(n) - return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) -end -number.points=points -number.basepoints=basepoints -local rubish=patterns.spaceortab^0*patterns.newline -local anyrubish=patterns.spaceortab+patterns.newline -local anything=patterns.anything -local stripped=(patterns.spaceortab^1/"")*patterns.newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*patterns.endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatableindex(t,function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+patterns.newline*Cp()/function(position) - extra,start=0,position - end+patterns.anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -function strings.striplong(str) - str=gsub(str,"^%s*","") - str=gsub(str,"[\n\r]+ *","\n") - return str -end -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local prefix_any=C((S("+- .")+R("09"))^0) -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) - else - return format("(select(%s,...))",n) - end -end -local format_q=function() - n=n+1 - return format("format('%%q',(select(%s,...)))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',(select(%s,...)))",f,n) - else - return format("(select(%s,...))",n) - end -end -local format_d=format_i -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local format_I=function(f) - n=n+1 - if f and f~="" then - return format("format('%%s%%%si',signed((select(%s,...))))",f,n) - else - return format("format('%%s%%i',signed((select(%s,...))))",n) - end -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',(select(%s,...)))",f,n) -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',(select(%s,...)))",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',(select(%s,...)))",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',(select(%s,...)))",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',(select(%s,...)))",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',(select(%s,...)))",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',(select(%s,...)))",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',(select(%s,...)))",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar((select(%s,...)))",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',(select(%s,...)))",f,n) -end -local format_v=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) - else - return format("format('0x%%%sx',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -local format_V=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) - else - return format("format('0x%%%sX',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -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) - else - return format("format('u+%%%sx',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -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) - else - return format("format('U+%%%sX',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -local format_p=function() - n=n+1 - return format("points((select(%s,...)))",n) -end -local format_b=function() - n=n+1 - return format("basepoints((select(%s,...)))",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat((select(%s,...)),%q)",n,f) - else - return format("concat((select(%s,...)))",n) - end -end -local format_l=function() - n=n+1 - return format("(select(%s,...) and 'true' or 'false')",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") - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["c"]=(prefix_any*P("c"))/format_c, - ["r"]=(prefix_any*P("r"))/format_r, - ["v"]=(prefix_any*P("v"))/format_v, - ["V"]=(prefix_any*P("V"))/format_V, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["b"]=(prefix_any*P("b"))/format_b, - ["t"]=(prefix_tab*P("t"))/format_t, - ["l"]=(prefix_tab*P("l"))/format_l, - ["I"]=(prefix_any*P("I"))/format_I, - ["a"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_a, -} -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 function make(t,str) - n=0 - local p=lpegmatch(builder,str) - local c=format(template,concat(p,"..")) - formatter=load(c)() - t[str]=formatter - return formatter -end -local formatters=string.formatters or {} -string.formatters=formatters -setmetatableindex(formatters,make) -function string.makeformatter(str) - return formatters[str] -end -function string.formatter(str,...) - return formatters[str](...) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - package.loaded["util-mrg"] = package.loaded["util-mrg"] or true -- original size: 7447, stripped down to: 6001 @@ -5202,7 +5356,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lua"] = package.loaded["util-lua"] or true --- original size: 12411, stripped down to: 8581 +-- original size: 12650, stripped down to: 8744 if not modules then modules={} end modules ['util-lua']={ version=1.001, @@ -5314,6 +5468,12 @@ if jit or status.luatex_version>=74 then end return done end + function luautilities.loadstripped(...) + local l=load(...) + if l then + return load(dump(l,true)) + end + end else local function register(name,before,after) local delta=before-after @@ -5478,6 +5638,7 @@ else end return done end + luautilities.loadstripped=loadstring end @@ -5879,7 +6040,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fmt"] = package.loaded["util-fmt"] or true --- original size: 3006, stripped down to: 2072 +-- original size: 2274, stripped down to: 1781 if not modules then modules={} end modules ['util-fmt']={ version=1.001, @@ -5894,17 +6055,8 @@ local formatters=utilities.formatters 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 -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 +local stripper=lpeg.patterns.stripzeros function formatters.stripzeros(str) return lpegmatch(stripper,str) end @@ -8663,7 +8815,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true --- original size: 48888, stripped down to: 30550 +-- original size: 48955, stripped down to: 30585 if not modules then modules={} end modules ['lxml-lpt']={ version=1.001, @@ -8677,6 +8829,7 @@ local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,to local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns local setmetatableindex=table.setmetatableindex +local formatters=string.formatters local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end @@ -15098,10 +15251,10 @@ end end -- of closure --- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-tab.lua util-sto.lua util-str.lua util-mrg.lua util-lua.lua util-prs.lua util-fmt.lua util-deb.lua trac-inf.lua trac-set.lua trac-log.lua trac-pro.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-mrg.lua util-lua.lua util-prs.lua util-fmt.lua util-deb.lua trac-inf.lua trac-set.lua trac-log.lua trac-pro.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 604381 --- stripped bytes : 205386 +-- original bytes : 628660 +-- stripped bytes : 225768 -- end library merge @@ -15141,9 +15294,9 @@ local ownlibs = { -- order can be made better 'l-unicode.lua', 'l-math.lua', + 'util-str.lua', -- code might move to l-string 'util-tab.lua', 'util-sto.lua', - 'util-str.lua', -- code might move to l-string 'util-mrg.lua', 'util-lua.lua', 'util-prs.lua', diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index d1a0887f2..ee01afe35 100755 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lua"] = package.loaded["l-lua"] or true --- original size: 7937, stripped down to: 5418 +-- original size: 7986, stripped down to: 5461 if not modules then modules={} end modules ['l-lua']={ version=1.001, @@ -68,6 +68,7 @@ if not modules then modules={} end modules ['l-lua']={ local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") _MAJORVERSION=tonumber(major) or 5 _MINORVERSION=tonumber(minor) or 1 +_LUAVERSION=_MAJORVERSION+_MINORVERSION/10 if not lpeg then lpeg=require("lpeg") end @@ -274,7 +275,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 25591, stripped down to: 14143 +-- original size: 26334, stripped down to: 14439 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -836,6 +837,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 -- of closure @@ -964,7 +974,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 29337, stripped down to: 19618 +-- original size: 44480, stripped down to: 19618 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -4268,9 +4278,407 @@ end -- of closure do -- create closure to overcome 200 locals limit +package.loaded["util-str"] = package.loaded["util-str"] or true + +-- original size: 17245, stripped down to: 10055 + +if not modules then modules={} end modules ['util-str']={ + version=1.001, + comment="companion to luat-lib.mkiv", + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files" +} +utilities=utilities or {} +utilities.strings=utilities.strings or {} +local strings=utilities.strings +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,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 loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) +end +local stripper=patterns.stripzeros +local function points(n) + return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) +end +local function basepoints(n) + return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) +end +number.points=points +number.basepoints=basepoints +local rubish=patterns.spaceortab^0*patterns.newline +local anyrubish=patterns.spaceortab+patterns.newline +local anything=patterns.anything +local stripped=(patterns.spaceortab^1/"")*patterns.newline +local leading=rubish^0/"" +local trailing=(anyrubish^1*patterns.endofstring)/"" +local redundant=rubish^3/"\n" +local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) +function strings.collapsecrlf(str) + return lpegmatch(pattern,str) +end +local repeaters={} +function strings.newrepeater(str,offset) + offset=offset or 0 + local s=repeaters[str] + if not s then + s={} + repeaters[str]=s + end + local t=s[offset] + if t then + return t + end + t={} + setmetatable(t,{ __index=function(t,k) + if not k then + return "" + end + local n=k+offset + local s=n>0 and rep(str,n) or "" + t[k]=s + return s + end }) + s[offset]=t + return t +end +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 + end*Cs(( + Cp()*patterns.tab/function(position) + local current=(position-start+1)+extra + local spaces=tab-(current-1)%tab + if spaces>0 then + extra=extra+spaces-1 + return nspaces[spaces] + else + return "" + end + end+patterns.newline*Cp()/function(position) + extra,start=0,position + end+patterns.anything + )^1) +function strings.tabtospace(str,tab) + return lpegmatch(pattern,str,1,tab or 7) +end +function strings.striplong(str) + str=gsub(str,"^%s*","") + str=gsub(str,"[\n\r]+ *","\n") + return str +end +function strings.nice(str) + str=gsub(str,"[:%-+_]+"," ") + return str +end +local n=0 +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) +local format_s=function(f) + n=n+1 + if f and f~="" then + return format("format('%%%ss',a%s)",f,n) + else + return format("a%s",n) + end +end +local format_S=function(f) + n=n+1 + if f and f~="" then + return format("format('%%%ss',tostring(a%s))",f,n) + else + return format("tostring(a%s)",n) + end +end +local format_q=function() + n=n+1 + return format("format('%%q',a%s)",n) +end +local format_Q=function() + 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',a%s)",f,n) + else + return format("a%s",n) + end +end +local format_d=format_i +function number.signed(i) + if i>0 then + return "+",i + else + return "-",-i + end +end +local format_I=function(f) + n=n+1 + if f and f~="" then + return format("format('%%s%%%si',signed(a%s))",f,n) + else + return format("format('%%s%%i',signed(a%s))",n) + end +end +local format_f=function(f) + n=n+1 + return format("format('%%%sf',a%s)",f,n) +end +local format_g=function(f) + n=n+1 + return format("format('%%%sg',a%s)",f,n) +end +local format_G=function(f) + n=n+1 + return format("format('%%%sG',a%s)",f,n) +end +local format_e=function(f) + n=n+1 + return format("format('%%%se',a%s)",f,n) +end +local format_E=function(f) + n=n+1 + return format("format('%%%sE',a%s)",f,n) +end +local format_x=function(f) + n=n+1 + return format("format('%%%sx',a%s)",f,n) +end +local format_X=function(f) + n=n+1 + return format("format('%%%sX',a%s)",f,n) +end +local format_o=function(f) + n=n+1 + return format("format('%%%so',a%s)",f,n) +end +local format_c=function() + n=n+1 + return format("utfchar(a%s)",n) +end +local format_r=function(f) + n=n+1 + return format("format('%%%s.0f',a%s)",f,n) +end +local format_h=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('0x%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_H=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('0x%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_u=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + else + return format("format('u+%%%sx',utfbyte(a%s))",f=="" and "05" or f,n) + end +end +local format_U=function(f) + n=n+1 + if f=="-" then + f=sub(f,2) + return format("format('%%%sX',utfbyte(a%s))",f=="" and "05" or f,n) + else + 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(a%s)",n) +end +local format_b=function() + n=n+1 + return format("basepoints(a%s)",n) +end +local format_t=function(f) + n=n+1 + if f and f~="" then + return format("concat(a%s,%q)",n,f) + else + return format("concat(a%s)",n) + end +end +local format_l=function() + n=n+1 + 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() + 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 format_w=function(f) + 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) + 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 + 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("!") ++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") ++V("Q") ++V("N") ++V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("l")+V("L")+V("I")+V("h") ++V("w") ++V("W") ++V("a") + )+V("a") + ) +*(P(-1)+Carg(1)) + )^0, + ["s"]=(prefix_any*P("s"))/format_s, + ["q"]=(prefix_any*P("q"))/format_q, + ["i"]=(prefix_any*P("i"))/format_i, + ["d"]=(prefix_any*P("d"))/format_d, + ["f"]=(prefix_any*P("f"))/format_f, + ["g"]=(prefix_any*P("g"))/format_g, + ["G"]=(prefix_any*P("G"))/format_G, + ["e"]=(prefix_any*P("e"))/format_e, + ["E"]=(prefix_any*P("E"))/format_E, + ["x"]=(prefix_any*P("x"))/format_x, + ["X"]=(prefix_any*P("X"))/format_X, + ["o"]=(prefix_any*P("o"))/format_o, + ["S"]=(prefix_any*P("S"))/format_S, + ["Q"]=(prefix_any*P("Q"))/format_S, + ["N"]=(prefix_any*P("N"))/format_N, + ["c"]=(prefix_any*P("c"))/format_c, + ["r"]=(prefix_any*P("r"))/format_r, + ["h"]=(prefix_any*P("h"))/format_h, + ["H"]=(prefix_any*P("H"))/format_H, + ["u"]=(prefix_any*P("u"))/format_u, + ["U"]=(prefix_any*P("U"))/format_U, + ["p"]=(prefix_any*P("p"))/format_p, + ["b"]=(prefix_any*P("b"))/format_b, + ["t"]=(prefix_tab*P("t"))/format_t, + ["l"]=(prefix_tab*P("l"))/format_l, + ["L"]=(prefix_tab*P("L"))/format_L, + ["I"]=(prefix_any*P("I"))/format_I, + ["w"]=(prefix_any*P("w"))/format_w, + ["W"]=(prefix_any*P("W"))/format_W, + ["a"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_a, + ["!"]=P("!")*C((1-P("!"))^1)*P("!")/format_extension, +} +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" } +setmetatable(arguments,{ __index=function(t,k) + local v=t[k-1]..",a"..k + t[k]=v + return v + end +}) +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,"..") + 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 function use(t,fmt,...) + return t[fmt](...) +end +local formatters=string.formatters or {} +string.formatters=formatters +setmetatable(formatters,{ __index=make,__call=use }) +function string.makeformatter(str) + return formatters[str] +end +function string.formatter(str,...) + return formatters[str](...) +end +string.addformatter=addextension + + +end -- of closure + +do -- create closure to overcome 200 locals limit + package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 10865, stripped down to: 7097 +-- original size: 14459, stripped down to: 8507 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -4282,12 +4690,13 @@ if not modules then modules={} end modules ['util-tab']={ 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(".") function tables.definetable(target,nofirst,nolast) local composed,shortcut,t=nil,nil,{} @@ -4384,34 +4793,80 @@ function tables.insertaftervalue(t,value,extra) end insert(t,#t+1,extra) end +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 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] + 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]=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>"](s,k) + toxml(v,d+step,result,step) + result[#result+1]=formatters["%s</%s>"](s,k) end - elseif type(k)=="number" then - result[#result+1]=format("%s<entry n='%s'>%s</entry>",d,k,v,k) + 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]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k) + end + 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,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 @@ -4453,27 +4908,27 @@ local function fastserialize(t,r,outer) 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 @@ -4729,307 +5184,6 @@ end -- of closure do -- create closure to overcome 200 locals limit -package.loaded["util-str"] = package.loaded["util-str"] or true - --- original size: 12069, stripped down to: 7814 - -if not modules then modules={} end modules ['util-str']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -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 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 patterns,lpegmatch=lpeg.patterns,lpeg.match -local utfchar,utfbyte=utf.char,utf.byte -local setmetatableindex=table.setmetatableindex -local stripper=patterns.stripzeros -local function points(n) - return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end -local function basepoints(n) - return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) -end -number.points=points -number.basepoints=basepoints -local rubish=patterns.spaceortab^0*patterns.newline -local anyrubish=patterns.spaceortab+patterns.newline -local anything=patterns.anything -local stripped=(patterns.spaceortab^1/"")*patterns.newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*patterns.endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatableindex(t,function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+patterns.newline*Cp()/function(position) - extra,start=0,position - end+patterns.anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -function strings.striplong(str) - str=gsub(str,"^%s*","") - str=gsub(str,"[\n\r]+ *","\n") - return str -end -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local prefix_any=C((S("+- .")+R("09"))^0) -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) - else - return format("(select(%s,...))",n) - end -end -local format_q=function() - n=n+1 - return format("format('%%q',(select(%s,...)))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',(select(%s,...)))",f,n) - else - return format("(select(%s,...))",n) - end -end -local format_d=format_i -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local format_I=function(f) - n=n+1 - if f and f~="" then - return format("format('%%s%%%si',signed((select(%s,...))))",f,n) - else - return format("format('%%s%%i',signed((select(%s,...))))",n) - end -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',(select(%s,...)))",f,n) -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',(select(%s,...)))",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',(select(%s,...)))",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',(select(%s,...)))",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',(select(%s,...)))",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',(select(%s,...)))",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',(select(%s,...)))",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',(select(%s,...)))",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar((select(%s,...)))",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',(select(%s,...)))",f,n) -end -local format_v=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) - else - return format("format('0x%%%sx',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -local format_V=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) - else - return format("format('0x%%%sX',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -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) - else - return format("format('u+%%%sx',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -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) - else - return format("format('U+%%%sX',utfbyte((select(%s,...))))",f=="" and "05" or f,n) - end -end -local format_p=function() - n=n+1 - return format("points((select(%s,...)))",n) -end -local format_b=function() - n=n+1 - return format("basepoints((select(%s,...)))",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat((select(%s,...)),%q)",n,f) - else - return format("concat((select(%s,...)))",n) - end -end -local format_l=function() - n=n+1 - return format("(select(%s,...) and 'true' or 'false')",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") - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["c"]=(prefix_any*P("c"))/format_c, - ["r"]=(prefix_any*P("r"))/format_r, - ["v"]=(prefix_any*P("v"))/format_v, - ["V"]=(prefix_any*P("V"))/format_V, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["b"]=(prefix_any*P("b"))/format_b, - ["t"]=(prefix_tab*P("t"))/format_t, - ["l"]=(prefix_tab*P("l"))/format_l, - ["I"]=(prefix_any*P("I"))/format_I, - ["a"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_a, -} -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 function make(t,str) - n=0 - local p=lpegmatch(builder,str) - local c=format(template,concat(p,"..")) - formatter=load(c)() - t[str]=formatter - return formatter -end -local formatters=string.formatters or {} -string.formatters=formatters -setmetatableindex(formatters,make) -function string.makeformatter(str) - return formatters[str] -end -function string.formatter(str,...) - return formatters[str](...) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - package.loaded["util-mrg"] = package.loaded["util-mrg"] or true -- original size: 7447, stripped down to: 6001 @@ -5202,7 +5356,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-lua"] = package.loaded["util-lua"] or true --- original size: 12411, stripped down to: 8581 +-- original size: 12650, stripped down to: 8744 if not modules then modules={} end modules ['util-lua']={ version=1.001, @@ -5314,6 +5468,12 @@ if jit or status.luatex_version>=74 then end return done end + function luautilities.loadstripped(...) + local l=load(...) + if l then + return load(dump(l,true)) + end + end else local function register(name,before,after) local delta=before-after @@ -5478,6 +5638,7 @@ else end return done end + luautilities.loadstripped=loadstring end @@ -5879,7 +6040,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fmt"] = package.loaded["util-fmt"] or true --- original size: 3006, stripped down to: 2072 +-- original size: 2274, stripped down to: 1781 if not modules then modules={} end modules ['util-fmt']={ version=1.001, @@ -5894,17 +6055,8 @@ local formatters=utilities.formatters 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 -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 +local stripper=lpeg.patterns.stripzeros function formatters.stripzeros(str) return lpegmatch(stripper,str) end @@ -8663,7 +8815,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true --- original size: 48888, stripped down to: 30550 +-- original size: 48955, stripped down to: 30585 if not modules then modules={} end modules ['lxml-lpt']={ version=1.001, @@ -8677,6 +8829,7 @@ local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,to local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns local setmetatableindex=table.setmetatableindex +local formatters=string.formatters local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end @@ -15098,10 +15251,10 @@ end end -- of closure --- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-tab.lua util-sto.lua util-str.lua util-mrg.lua util-lua.lua util-prs.lua util-fmt.lua util-deb.lua trac-inf.lua trac-set.lua trac-log.lua trac-pro.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua luat-sta.lua luat-fmt.lua +-- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-mrg.lua util-lua.lua util-prs.lua util-fmt.lua util-deb.lua trac-inf.lua trac-set.lua trac-log.lua trac-pro.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 604381 --- stripped bytes : 205386 +-- original bytes : 628660 +-- stripped bytes : 225768 -- end library merge @@ -15141,9 +15294,9 @@ local ownlibs = { -- order can be made better 'l-unicode.lua', 'l-math.lua', + 'util-str.lua', -- code might move to l-string 'util-tab.lua', 'util-sto.lua', - 'util-str.lua', -- code might move to l-string 'util-mrg.lua', 'util-lua.lua', 'util-prs.lua', 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/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/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 |