From cf30fd606d6a7ed38a7ffc1cbee0ecce4761cacd Mon Sep 17 00:00:00 2001 From: Ulrike Fischer Date: Tue, 29 Oct 2019 16:50:00 +0100 Subject: [PATCH] imported context --- CTANREADME.md | 4 +- NEWS | 3 + README.md | 6 +- build.lua | 4 +- lualibs-basic-merged.lua | 205 +++++++++++++++++++++++------------- lualibs-extended-merged.lua | 68 +++++++++--- lualibs-gzip.lua | 135 +++++++++++++++++------- lualibs-lpeg.lua | 2 +- lualibs-lua.lua | 6 ++ lualibs-table.lua | 31 ++++++ lualibs-unicode.lua | 84 ++++++++------- lualibs-util-lua.lua | 10 +- lualibs-util-str.lua | 35 ++++-- lualibs-util-tab.lua | 20 +++- lualibs-util-tpl.lua | 66 +++++++----- lualibs.dtx | 18 ++-- 16 files changed, 480 insertions(+), 217 deletions(-) diff --git a/CTANREADME.md b/CTANREADME.md index b89ca40..e6455b1 100644 --- a/CTANREADME.md +++ b/CTANREADME.md @@ -1,8 +1,8 @@ # The Lualibs Package -VERSION: 2.67 +VERSION: 2.68 -DATE: 2019-08-11 +DATE: 2019-10-29 Lualibs is a collection of Lua modules useful for general programming. diff --git a/NEWS b/NEWS index 66ee05e..73e5961 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,7 @@ History of the lualibs package +2019/10/29 v2.68/ + * sync with Context current as of 2019/10/29 + 2019/08/11 v2.67/ * sync with Context current as of 2019/08/11 diff --git a/README.md b/README.md index 0e6b111..9aff4b0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # The Lualibs Package -![Version: 2.67](https://img.shields.io/badge/current_version-2.67-blue.svg?style=flat-square) -![Date: 2019-08-11](https://img.shields.io/badge/date-2019--08--11-blue.svg?style=flat-square) +![Version: 2.68](https://img.shields.io/badge/current_version-2.68-blue.svg?style=flat-square) +![Date: 2019-10-29](https://img.shields.io/badge/date-2019--10--29-blue.svg?style=flat-square) [![License: GNU GPLv2](https://img.shields.io/badge/license-GNU_GPLv2-blue.svg?style=flat-square)](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) @@ -15,7 +15,7 @@ This package has been developed by the LuaLaTeX development team on . The current version has been build by Ulrike Fischer on - from context 2019-08-11. + from context 2019-10-29. Please see the documentation lualibs.pdf for more information. diff --git a/build.lua b/build.lua index afcb6fe..068b81d 100644 --- a/build.lua +++ b/build.lua @@ -1,6 +1,6 @@ -- Build script for lualibs -packageversion= "2.67" -packagedate= "2019-08-11" +packageversion= "2.68" +packagedate= "2019-10-29" module = "lualibs" ctanpkg = "lualibs" diff --git a/lualibs-basic-merged.lua b/lualibs-basic-merged.lua index 0cb07ce..bee6c7d 100644 --- a/lualibs-basic-merged.lua +++ b/lualibs-basic-merged.lua @@ -1,6 +1,6 @@ -- merged file : lualibs-basic-merged.lua -- parent file : lualibs-basic.lua --- merge date : Tue Aug 13 20:13:08 2019 +-- merge date : Tue Oct 29 16:47:31 2019 do -- begin closure to overcome local limits and interference @@ -20,6 +20,9 @@ if LUAVERSION<5.2 and jit then MINORVERSION=2 LUAVERSION=5.2 end +if lua and lua.openfile then + io.open=lua.openfile +end if not lpeg then lpeg=require("lpeg") end @@ -613,7 +616,7 @@ patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+unders patterns.somecontent=(anything-newline-space)^1 patterns.beginline=#(1-newline) patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0)) -function anywhere(pattern) +local function anywhere(pattern) return (1-P(pattern))^0*P(pattern) end lpeg.anywhere=anywhere @@ -3954,43 +3957,98 @@ if not modules then modules={} end modules ['l-gzip']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } -if not gzip then - return -end -local suffix,suffixes=file.suffix,file.suffixes -function gzip.load(filename) - local f=io.open(filename,"rb") - if not f then - elseif suffix(filename)=="gz" then - f:close() - local g=gzip.open(filename,"rb") - if g then - local str=g:read("*all") - g:close() +if gzip then + local suffix,suffixes=file.suffix,file.suffixes + function gzip.load(filename) + local f=io.open(filename,"rb") + if not f then + elseif suffix(filename)=="gz" then + f:close() + local g=gzip.open(filename,"rb") + if g then + local str=g:read("*all") + g:close() + return str + end + else + local str=f:read("*all") + f:close() return str end - else - local str=f:read("*all") - f:close() - return str end -end -function gzip.save(filename,data) - if suffix(filename)~="gz" then - filename=filename..".gz" + function gzip.save(filename,data) + if suffix(filename)~="gz" then + filename=filename..".gz" + end + local f=io.open(filename,"wb") + if f then + local s=zlib.compress(data or "",9,nil,15+16) + f:write(s) + f:close() + return #s + end end - local f=io.open(filename,"wb") - if f then - local s=zlib.compress(data or "",9,nil,15+16) - f:write(s) - f:close() - return #s + function gzip.suffix(filename) + local suffix,extra=suffixes(filename) + local gzipped=extra=="gz" + return suffix,gzipped end +else end -function gzip.suffix(filename) - local suffix,extra=suffixes(filename) - local gzipped=extra=="gz" - return suffix,gzipped +if flate then + local type=type + local find=string.find + local compress=flate.gz_compress + local decompress=flate.gz_decompress + local absmax=128*1024*1024 + local initial=64*1024 + local identifier="^\x1F\x8B\x08" + function gzip.compressed(s) + return s and find(s,identifier) + end + function gzip.compress(s,level) + if s and not find(s,identifier) then + if not level then + level=3 + elseif level<=0 then + return s + elseif level>9 then + level=9 + end + return compress(s,level) or s + end + end + function gzip.decompress(s,size,iterate) + if s and find(s,identifier) then + if type(size)~="number" then + size=initial + end + if size>absmax then + size=absmax + end + if type(iterate)=="number" then + max=size*iterate + elseif iterate==nil or iterate==true then + iterate=true + max=absmax + end + if max>absmax then + max=absmax + end + while true do + local d=decompress(s,size) + if d then + return d + end + size=2*size + if not iterate or size>max then + return false + end + end + else + return s + end + end end end -- closure @@ -5097,49 +5155,52 @@ end function utf.utf32_to_utf8_t(t,endian) return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t end -local function little(b) - if b<0x10000 then - return char(b%256,rshift(b,8)) - else - b=b-0x10000 - local b1=rshift(b,10)+0xD800 - local b2=b%1024+0xDC00 - return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8)) +if bit32 then + local rshift=bit32.rshift + local function little(b) + if b<0x10000 then + return char(b%256,rshift(b,8)) + else + b=b-0x10000 + local b1=rshift(b,10)+0xD800 + local b2=b%1024+0xDC00 + return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8)) + end end -end -local function big(b) - if b<0x10000 then - return char(rshift(b,8),b%256) - else - b=b-0x10000 - local b1=rshift(b,10)+0xD800 - local b2=b%1024+0xDC00 - return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256) + local function big(b) + if b<0x10000 then + return char(rshift(b,8),b%256) + else + b=b-0x10000 + local b1=rshift(b,10)+0xD800 + local b2=b%1024+0xDC00 + return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256) + end end -end -local l_remap=Cs((p_utf8byte/little+P(1)/"")^0) -local b_remap=Cs((p_utf8byte/big+P(1)/"")^0) -local function utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255)..lpegmatch(b_remap,str) + local l_remap=Cs((p_utf8byte/little+P(1)/"")^0) + local b_remap=Cs((p_utf8byte/big+P(1)/"")^0) + local function utf8_to_utf16_be(str,nobom) + if nobom then + return lpegmatch(b_remap,str) + else + return char(254,255)..lpegmatch(b_remap,str) + end end -end -local function utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254)..lpegmatch(l_remap,str) + local function utf8_to_utf16_le(str,nobom) + if nobom then + return lpegmatch(l_remap,str) + else + return char(255,254)..lpegmatch(l_remap,str) + end end -end -utf.utf8_to_utf16_be=utf8_to_utf16_be -utf.utf8_to_utf16_le=utf8_to_utf16_le -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) + utf.utf8_to_utf16_be=utf8_to_utf16_be + utf.utf8_to_utf16_le=utf8_to_utf16_le + function utf.utf8_to_utf16(str,littleendian,nobom) + if littleendian then + return utf8_to_utf16_le(str,nobom) + else + return utf8_to_utf16_be(str,nobom) + end end end local pattern=Cs ( diff --git a/lualibs-extended-merged.lua b/lualibs-extended-merged.lua index b3fecf2..c250240 100644 --- a/lualibs-extended-merged.lua +++ b/lualibs-extended-merged.lua @@ -1,6 +1,6 @@ -- merged file : lualibs-extended-merged.lua -- parent file : lualibs-extended.lua --- merge date : Tue Aug 13 20:12:59 2019 +-- merge date : Tue Oct 29 16:47:22 2019 do -- begin closure to overcome local limits and interference @@ -366,7 +366,7 @@ local environment={ stripzero=patterns.stripzero, stripzeros=patterns.stripzeros, escapedquotes=string.escapedquotes, - FORMAT=string.f9, + FORMAT=string.f6, } local arguments={ "a1" } setmetatable(arguments,{ __index=function(t,k) @@ -574,12 +574,25 @@ local format_n=function() n=n+1 return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n) end -local format_N=function(f) - n=n+1 - if not f or f=="" then - f=".9" - end - return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) +local format_N if environment.FORMAT then + format_N=function(f) + n=n+1 + if not f or f=="" then + return format("FORMAT(a%s,'%%.9f')",n) + elseif f==".6" then + return format("FORMAT(a%s)",n) + else + return format("FORMAT(a%s,'%%%sf')",n,f) + end + end +else + format_N=function(f) + n=n+1 + if not f or f=="" then + f=".9" + end + return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) + end end local format_a=function(f) n=n+1 @@ -1416,7 +1429,21 @@ function table.fastserialize(t,prefix) m=m+1 r[m]="{" if n>0 then - for i=0,n do + local v=t[0] + if v then + local tv=type(v) + if tv=="string" then + m=m+1 r[m]=f_indexed_string(0,v) + elseif tv=="number" then + m=m+1 r[m]=f_indexed_number(0,v) + elseif tv=="table" then + m=m+1 r[m]=f_indexed_table(0) + fastserialize(v) + elseif tv=="boolean" then + m=m+1 r[m]=f_indexed_boolean(0,v) + end + end + for i=1,n do local v=t[i] local tv=type(v) if tv=="string" then @@ -3377,6 +3404,11 @@ luautilities.nofstrippedchunks=0 luautilities.nofstrippedbytes=0 local strippedchunks={} luautilities.strippedchunks=strippedchunks +if not LUATEXENGINE then + LUATEXENGINE=status.luatex_engine and string.lower(status.luatex_engine) + JITSUPPORTED=LUATEXENGINE=="luajittex" or jit + CONTEXTLMTXMODE=CONTEXTLMTXMODE or (LUATEXENGINE=="luametatex" and 1) or 0 +end luautilities.suffixes={ tma="tma", tmc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tmd") or (jit and "tmb") or "tmc", @@ -3386,7 +3418,7 @@ luautilities.suffixes={ luv="luv", luj="luj", tua="tua", - tuc="tuc", + tuc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tud") or (jit and "tub") or "tuc", } local function register(name) if tracestripping then @@ -3833,6 +3865,7 @@ local report_template=logs.reporter("template") local tostring,next=tostring,next local format,sub,byte=string.format,string.sub,string.byte local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns +local formatters=string.formatters local replacer local function replacekey(k,t,how,recursive) local v=t[k] @@ -3901,6 +3934,10 @@ local function replaceoptional(l,m,r,t,how,recurse) local v=t[l] return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or "" end +local function replaceformatted(l,m,r,t,how,recurse) + local v=t[r] + return v and formatters[l](v) +end local single=P("%") local double=P("%%") local lquoted=P("%[") @@ -3914,16 +3951,19 @@ local nolquoted=lquoted/'' local norquoted=rquoted/'' local nolquotedq=lquotedq/'' local norquotedq=rquotedq/'' +local nolformatted=P(":")/"%%" +local norformatted=P(":")/"" local noloptional=P("%?")/'' local noroptional=P("?%")/'' local nomoptional=P(":")/'' local args=Carg(1)*Carg(2)*Carg(3) -local key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle -local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq -local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted +local key=nosingle*((C((1-nosingle)^1)*args)/replacekey)*nosingle +local quoted=nolquotedq*((C((1-norquotedq)^1)*args)/replacekeyquoted)*norquotedq +local unquoted=nolquoted*((C((1-norquoted)^1)*args)/replacekeyunquoted)*norquoted local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional +local formatted=nosingle*((Cs(nolformatted*(1-norformatted )^1)*norformatted*C((1-nosingle)^1)*args)/replaceformatted)*nosingle local any=P(1) - replacer=Cs((unquoted+quoted+escape+optional+key+any)^0) + replacer=Cs((unquoted+quoted+formatted+escape+optional+key+any)^0) local function replace(str,mapping,how,recurse) if mapping and str then return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str diff --git a/lualibs-gzip.lua b/lualibs-gzip.lua index 5100e47..31466bd 100644 --- a/lualibs-gzip.lua +++ b/lualibs-gzip.lua @@ -5,50 +5,113 @@ if not modules then modules = { } end modules ['l-gzip'] = { license = "see context related readme files" } -if not gzip then +if gzip then - -- no fallback yet + local suffix, suffixes = file.suffix, file.suffixes - return - -end - -local suffix, suffixes = file.suffix, file.suffixes - -function gzip.load(filename) - local f = io.open(filename,"rb") - if not f then - -- invalid file - elseif suffix(filename) == "gz" then - f:close() - local g = gzip.open(filename,"rb") - if g then - local str = g:read("*all") - g:close() + function gzip.load(filename) + local f = io.open(filename,"rb") + if not f then + -- invalid file + elseif suffix(filename) == "gz" then + f:close() + local g = gzip.open(filename,"rb") + if g then + local str = g:read("*all") + g:close() + return str + end + else + local str = f:read("*all") + f:close() return str end - else - local str = f:read("*all") - f:close() - return str end -end -function gzip.save(filename,data) - if suffix(filename) ~= "gz" then - filename = filename .. ".gz" + function gzip.save(filename,data) + if suffix(filename) ~= "gz" then + filename = filename .. ".gz" + end + local f = io.open(filename,"wb") + if f then + local s = zlib.compress(data or "",9,nil,15+16) + f:write(s) + f:close() + return #s + end end - local f = io.open(filename,"wb") - if f then - local s = zlib.compress(data or "",9,nil,15+16) - f:write(s) - f:close() - return #s + + function gzip.suffix(filename) + local suffix, extra = suffixes(filename) + local gzipped = extra == "gz" + return suffix, gzipped end + +else + + -- todo: fallback on flate + end -function gzip.suffix(filename) - local suffix, extra = suffixes(filename) - local gzipped = extra == "gz" - return suffix, gzipped +if flate then + + local type = type + local find = string.find + + local compress = flate.gz_compress + local decompress = flate.gz_decompress + + local absmax = 128*1024*1024 + local initial = 64*1024 + local identifier = "^\x1F\x8B\x08" + + function gzip.compressed(s) + return s and find(s,identifier) + end + + function gzip.compress(s,level) + if s and not find(s,identifier) then -- the find check might go away + if not level then + level = 3 + elseif level <= 0 then + return s + elseif level > 9 then + level = 9 + end + return compress(s,level) or s + end + end + + function gzip.decompress(s,size,iterate) + if s and find(s,identifier) then + if type(size) ~= "number" then + size = initial + end + if size > absmax then + size = absmax + end + if type(iterate) == "number" then + max = size * iterate + elseif iterate == nil or iterate == true then + iterate = true + max = absmax + end + if max > absmax then + max = absmax + end + while true do + local d = decompress(s,size) + if d then + return d + end + size = 2 * size + if not iterate or size > max then + return false + end + end + else + return s + end + end + end diff --git a/lualibs-lpeg.lua b/lualibs-lpeg.lua index 51bc1d3..7979a40 100644 --- a/lualibs-lpeg.lua +++ b/lualibs-lpeg.lua @@ -295,7 +295,7 @@ patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^ -- return P { P(pattern) + 1 * V(1) } -- end -function anywhere(pattern) -- faster +local function anywhere(pattern) -- faster return (1-P(pattern))^0 * P(pattern) end diff --git a/lualibs-lua.lua b/lualibs-lua.lua index 6e9606e..5139921 100644 --- a/lualibs-lua.lua +++ b/lualibs-lua.lua @@ -35,6 +35,12 @@ if LUAVERSION < 5.2 and jit then LUAVERSION = 5.2 end +-- this is lmtx only: + +if lua and lua.openfile then + io.open = lua.openfile +end + -- lpeg if not lpeg then diff --git a/lualibs-table.lua b/lualibs-table.lua index cffdcc2..e828203 100644 --- a/lualibs-table.lua +++ b/lualibs-table.lua @@ -287,6 +287,37 @@ local function sortedhash(t,cmp) return nothing end +-- local function iterate(t,i) +-- local i = i + 1 +-- if i <= t.n then +-- local k = t[i] +-- return i, k, t.t[k] +-- end +-- end +-- +-- local function indexedhash(t,cmp) +-- if t then +-- local s +-- if cmp then +-- -- it would be nice if the sort function would accept a third argument (or nicer, an optional first) +-- s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) +-- else +-- s = sortedkeys(t) -- the robust one +-- end +-- local m = #s +-- if m == 1 then +-- return next, t +-- elseif m > 0 then +-- s.n = m +-- s.t = t +-- return iterate, s, 0 +-- end +-- end +-- return nothing +-- end +-- +-- -- for i, k, v in indexedhash(t) do print(k,v,s) end + table.sortedhash = sortedhash table.sortedpairs = sortedhash -- obsolete diff --git a/lualibs-unicode.lua b/lualibs-unicode.lua index 73d1eb7..2708d14 100644 --- a/lualibs-unicode.lua +++ b/lualibs-unicode.lua @@ -1081,56 +1081,62 @@ function utf.utf32_to_utf8_t(t,endian) return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t end -local function little(b) - if b < 0x10000 then - return char(b%256,rshift(b,8)) - else - b = b - 0x10000 - local b1 = rshift(b,10) + 0xD800 - local b2 = b%1024 + 0xDC00 - return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8)) +if bit32 then + + local rshift = bit32.rshift + + local function little(b) + if b < 0x10000 then + return char(b%256,rshift(b,8)) + else + b = b - 0x10000 + local b1 = rshift(b,10) + 0xD800 + local b2 = b%1024 + 0xDC00 + return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8)) + end end -end -local function big(b) - if b < 0x10000 then - return char(rshift(b,8),b%256) - else - b = b - 0x10000 - local b1 = rshift(b,10) + 0xD800 - local b2 = b%1024 + 0xDC00 - return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256) + local function big(b) + if b < 0x10000 then + return char(rshift(b,8),b%256) + else + b = b - 0x10000 + local b1 = rshift(b,10) + 0xD800 + local b2 = b%1024 + 0xDC00 + return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256) + end end -end -local l_remap = Cs((p_utf8byte/little+P(1)/"")^0) -local b_remap = Cs((p_utf8byte/big +P(1)/"")^0) + local l_remap = Cs((p_utf8byte/little+P(1)/"")^0) + local b_remap = Cs((p_utf8byte/big +P(1)/"")^0) -local function utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255) .. lpegmatch(b_remap,str) + local function utf8_to_utf16_be(str,nobom) + if nobom then + return lpegmatch(b_remap,str) + else + return char(254,255) .. lpegmatch(b_remap,str) + end end -end -local function utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254) .. lpegmatch(l_remap,str) + local function utf8_to_utf16_le(str,nobom) + if nobom then + return lpegmatch(l_remap,str) + else + return char(255,254) .. lpegmatch(l_remap,str) + end end -end -utf.utf8_to_utf16_be = utf8_to_utf16_be -utf.utf8_to_utf16_le = utf8_to_utf16_le + utf.utf8_to_utf16_be = utf8_to_utf16_be + utf.utf8_to_utf16_le = utf8_to_utf16_le -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) + function utf.utf8_to_utf16(str,littleendian,nobom) + if littleendian then + return utf8_to_utf16_le(str,nobom) + else + return utf8_to_utf16_be(str,nobom) + end end + end local pattern = Cs ( diff --git a/lualibs-util-lua.lua b/lualibs-util-lua.lua index f7e6e4f..fb4088e 100644 --- a/lualibs-util-lua.lua +++ b/lualibs-util-lua.lua @@ -28,6 +28,13 @@ luautilities.nofstrippedbytes = 0 local strippedchunks = { } -- allocate() luautilities.strippedchunks = strippedchunks +if not LUATEXENGINE then + --- probably mtxrun ... + LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) + JITSUPPORTED = LUATEXENGINE == "luajittex" or jit + CONTEXTLMTXMODE = CONTEXTLMTXMODE or (LUATEXENGINE == "luametatex" and 1) or 0 +end + luautilities.suffixes = { tma = "tma", tmc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tmd") or (jit and "tmb") or "tmc", @@ -37,7 +44,8 @@ luautilities.suffixes = { luv = "luv", luj = "luj", tua = "tua", - tuc = "tuc", + -- tuc = "tuc", + tuc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tud") or (jit and "tub") or "tuc", } -- environment.loadpreprocessedfile can be set to a preprocessor diff --git a/lualibs-util-str.lua b/lualibs-util-str.lua index ad22302..432b39e 100644 --- a/lualibs-util-str.lua +++ b/lualibs-util-str.lua @@ -633,7 +633,7 @@ local environment = { stripzeros = patterns.stripzeros, escapedquotes = string.escapedquotes, - FORMAT = string.f9, + FORMAT = string.f6, } -- -- -- @@ -908,7 +908,7 @@ local format_L = function() return format("(a%s and 'TRUE' or 'FALSE')",n) end -local format_n = function() -- strips leading and trailing zeros and removes .0 +local format_n = function() -- strips leading and trailing zeros and removes .0, beware: can produce e notation n = n + 1 return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n) end @@ -938,13 +938,30 @@ end -- end -- end -local format_N = function(f) -- strips leading and trailing zeros - n = n + 1 - -- stripzero (singular) as we only have a number - if not f or f == "" then - f = ".9" - end -- always a leading number ! - return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) +local format_N if environment.FORMAT then + + format_N = function(f) + n = n + 1 + if not f or f == "" then + return format("FORMAT(a%s,'%%.9f')",n) + elseif f == ".6" then + return format("FORMAT(a%s)",n) + else + return format("FORMAT(a%s,'%%%sf')",n,f) + end + end + +else + + format_N = function(f) -- strips leading and trailing zeros + n = n + 1 + -- stripzero (singular) as we only have a number + if not f or f == "" then + f = ".9" + end -- always a leading number ! + return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) + end + end local format_a = function(f) diff --git a/lualibs-util-tab.lua b/lualibs-util-tab.lua index f970d8a..410292c 100644 --- a/lualibs-util-tab.lua +++ b/lualibs-util-tab.lua @@ -341,7 +341,21 @@ function table.fastserialize(t,prefix) -- todo, move local function out m = m + 1 r[m] = "{" if n > 0 then - for i=0,n do + local v = t[0] + if v then + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_indexed_string(0,v) + elseif tv == "number" then + m = m + 1 r[m] = f_indexed_number(0,v) + elseif tv == "table" then + m = m + 1 r[m] = f_indexed_table(0) + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_indexed_boolean(0,v) + end + end + for i=1,n do local v = t[i] local tv = type(v) if tv == "string" then @@ -355,6 +369,8 @@ function table.fastserialize(t,prefix) -- todo, move local function out end end end + -- hm, can't we avoid this ... lua should have a way to check if there + -- is a hash part for k, v in next, t do local tk = type(k) if tk == "number" then @@ -411,7 +427,7 @@ function table.deserialize(str) return code end --- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } }) +-- inspect(table.fastserialize { a = 1, b = { [0]=4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } }) function table.load(filename,loader) if filename then diff --git a/lualibs-util-tpl.lua b/lualibs-util-tpl.lua index 57d7df3..318f2ef 100644 --- a/lualibs-util-tpl.lua +++ b/lualibs-util-tpl.lua @@ -20,6 +20,8 @@ local tostring, next = tostring, next local format, sub, byte = string.format, string.sub, string.byte local P, C, R, Cs, Cc, Carg, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match, lpeg.patterns +local formatters = string.formatters + -- todo: make installable template.new local replacer @@ -133,34 +135,42 @@ local function replaceoptional(l,m,r,t,how,recurse) return v and v ~= "" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or "" end -local single = P("%") -- test %test% test : resolves test -local double = P("%%") -- test 10%% test : %% becomes % -local lquoted = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s -local rquoted = P("]%") -- -local lquotedq = P("%(") -- test %(test)% test : resolves to 'test' with escaped "'s -local rquotedq = P(")%") -- - -local escape = double / '%%' -local nosingle = single / '' -local nodouble = double / '' -local nolquoted = lquoted / '' -local norquoted = rquoted / '' -local nolquotedq = lquotedq / '' -local norquotedq = rquotedq / '' - -local noloptional = P("%?") / '' -local noroptional = P("?%") / '' -local nomoptional = P(":") / '' - - -local args = Carg(1) * Carg(2) * Carg(3) -local key = nosingle * ((C((1-nosingle )^1) * args) / replacekey ) * nosingle -local quoted = nolquotedq * ((C((1-norquotedq )^1) * args) / replacekeyquoted ) * norquotedq -local unquoted = nolquoted * ((C((1-norquoted )^1) * args) / replacekeyunquoted) * norquoted -local optional = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) * noroptional -local any = P(1) +local function replaceformatted(l,m,r,t,how,recurse) + local v = t[r] + return v and formatters[l](v) +end - replacer = Cs((unquoted + quoted + escape + optional + key + any)^0) +local single = P("%") -- test %test% test : resolves test +local double = P("%%") -- test 10%% test : %% becomes % +local lquoted = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s +local rquoted = P("]%") -- +local lquotedq = P("%(") -- test %(test)% test : resolves to 'test' with escaped "'s +local rquotedq = P(")%") -- + +local escape = double / '%%' +local nosingle = single / '' +local nodouble = double / '' +local nolquoted = lquoted / '' +local norquoted = rquoted / '' +local nolquotedq = lquotedq / '' +local norquotedq = rquotedq / '' + +local nolformatted = P(":") / "%%" +local norformatted = P(":") / "" + +local noloptional = P("%?") / '' +local noroptional = P("?%") / '' +local nomoptional = P(":") / '' + +local args = Carg(1) * Carg(2) * Carg(3) +local key = nosingle * ((C((1-nosingle)^1) * args) / replacekey) * nosingle +local quoted = nolquotedq * ((C((1-norquotedq)^1) * args) / replacekeyquoted) * norquotedq +local unquoted = nolquoted * ((C((1-norquoted)^1) * args) / replacekeyunquoted) * norquoted +local optional = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) * noroptional +local formatted = nosingle * ((Cs(nolformatted * (1-norformatted )^1) * norformatted * C((1-nosingle)^1) * args) / replaceformatted) * nosingle +local any = P(1) + + replacer = Cs((unquoted + quoted + formatted + escape + optional + key + any)^0) local function replace(str,mapping,how,recurse) if mapping and str then @@ -179,6 +189,8 @@ end -- print(replace([[test %[x]% test]],{ x = [[a "x"  a]]})) -- print(replace([[test %(x)% test]],{ x = [[a "x"  a]]})) -- print(replace([[convert %?x: -x "%x%" ?% %?y: -y "%y%" ?%]],{ x = "yes" })) +-- print(replace("test %:0.3N:x% test",{ x = 123.45 })) +-- print(replace("test %:0.3N:x% test",{ x = 12345 })) templates.replace = replace diff --git a/lualibs.dtx b/lualibs.dtx index 8c30240..7dc0e4b 100644 --- a/lualibs.dtx +++ b/lualibs.dtx @@ -37,7 +37,7 @@ \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} -\Msg{* Package: lualibs 2019-08-11 v2.67 Lua additional functions.} +\Msg{* Package: lualibs 2019-10-29 v2.68 Lua additional functions.} \Msg{************************************************************************} \keepsilent @@ -107,7 +107,7 @@ and lualibs-extended.lua. %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{lualibs.drv} - [2019/08/11 v2.67 Lua Libraries.] + [2019/10/29 v2.68 Lua Libraries.] \documentclass{ltxdoc} \usepackage{fancyvrb,xspace} \usepackage[x11names]{xcolor} @@ -208,7 +208,7 @@ and lualibs-extended.lua. % \GetFileInfo{lualibs.drv} % % \title{The \identifier{lualibs} package} -% \date{2019/08/11 v2.67} +% \date{2019/10/29 v2.68} % \author{Élie Roux · \email{elie.roux@telecom-bretagne.eu}\\ % Philipp Gesang · \email{phg@phi-gamma.net}\\ % Ulrike Fischer · \email{fischer@troubleshooting-tex.de}\\ @@ -429,8 +429,8 @@ lualibs = lualibs or { } lualibs.module_info = { name = "lualibs", - version = "2.67", --TAGVERSION - date = "2019-08-11", --TAGDATE + version = "2.68", --TAGVERSION + date = "2019-10-29", --TAGDATE description = "ConTeXt Lua standard libraries.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", @@ -583,8 +583,8 @@ local loadmodule = lualibs.loadmodule local lualibs_basic_module = { name = "lualibs-basic", - version = "2.67", --TAGVERSION - date = "2019-08-11", --TAGDATE + version = "2.68", --TAGVERSION + date = "2019-10-29", --TAGDATE description = "ConTeXt Lua libraries -- basic collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", @@ -665,8 +665,8 @@ lualibs = lualibs or { } local lualibs_extended_module = { name = "lualibs-extended", - version = "2.67", --TAGVERSION - date = "2019-08-11", --TAGDATE + version = "2.68", --TAGVERSION + date = "2019-10-29", --TAGDATE description = "ConTeXt Lua libraries -- extended collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team",