texlive[51642] Master/texmf-dist: lualibs (14jul19)

commits+karl at tug.org commits+karl at tug.org
Sun Jul 14 22:48:50 CEST 2019


Revision: 51642
          http://tug.org/svn/texlive?view=revision&revision=51642
Author:   karl
Date:     2019-07-14 22:48:50 +0200 (Sun, 14 Jul 2019)
Log Message:
-----------
lualibs (14jul19)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS
    trunk/Master/texmf-dist/doc/luatex/lualibs/README
    trunk/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf
    trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua
    trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua

Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS	2019-07-14 20:48:50 UTC (rev 51642)
@@ -1,4 +1,8 @@
                         History of the lualibs package
+2019/07/04 v2.66/
+    * sync with Context current as of 2019/07/04
+    * changed kpse initialization to avoid conflicts with latex-dev format    
+                        
 2019/05/18 v2.65/
     * sync with Context current as of 2019/05/18    
                             

Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/README
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lualibs/README	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/doc/luatex/lualibs/README	2019-07-14 20:48:50 UTC (rev 51642)
@@ -11,8 +11,8 @@
 This package has been developed by the LuaLaTeX development team on
 <http://github.com/lualatex/lualibs>. 
 
-The current verson 2.65 has been build by Ulrike Fischer on
-<https://github.com/u-fischer/lualibs> from context 2019-05-18. 
+The current verson 2.6601 has been build by Ulrike Fischer on
+<https://github.com/u-fischer/lualibs> from context 2019-06-20. 
 
 See the 'NEWS' file for version history.
 

Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx	2019-07-14 20:48:50 UTC (rev 51642)
@@ -1,6 +1,6 @@
 % \iffalse meta-comment
 %
-% Copyright (C) 2009--2018 by
+% Copyright (C) 2009--2019 by
 %
 %       PRAGMA ADE / ConTeXt Development Team
 %       The LuaLaTeX Dev Team
@@ -37,7 +37,7 @@
 \input docstrip.tex
 \Msg{************************************************************************}
 \Msg{* Installation}
-\Msg{* Package: lualibs 2019-05-18 v2.65 Lua additional functions.}
+\Msg{* Package: lualibs 2019-07-04 v2.66 Lua additional functions.}
 \Msg{************************************************************************}
 
 \keepsilent
@@ -107,7 +107,7 @@
 %<*driver>
 \NeedsTeXFormat{LaTeX2e}
 \ProvidesFile{lualibs.drv}
-  [2019/05/18 v2.65 Lua Libraries.]
+  [2019/07/04 v2.66 Lua Libraries.]
 \documentclass{ltxdoc}
 \usepackage{fancyvrb,xspace}
 \usepackage[x11names]{xcolor}
@@ -208,7 +208,7 @@
 % \GetFileInfo{lualibs.drv}
 %
 % \title{The \identifier{lualibs} package}
-% \date{2019/05/18 v2.65}
+% \date{2019/07/04 v2.66}
 % \author{Élie Roux      · \email{elie.roux at telecom-bretagne.eu}\\
 %         Philipp Gesang · \email{phg at phi-gamma.net}\\
 %         Ulrike Fischer · \email{fischer at troubleshooting-tex.de}\\
@@ -429,8 +429,8 @@
 
 lualibs.module_info = {
   name          = "lualibs",
-  version       = 2.65,
-  date          = "2019-05-18",
+  version       = 2.66,
+  date          = "2019-07-04",
   description   = "ConTeXt Lua standard libraries.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",
@@ -505,13 +505,13 @@
   lualibs.error, lualibs.warn, lualibs.info = error, warn, info
 end
 
-if luatexbase and luatexbase.find_file then
-  find_file = luatexbase.find_file
-else
-  kpse.set_program_name"luatex"
-  find_file = kpsefind_file
+local info = status.list()
+if info.kpse_used == 0 then
+ kpse.set_program_name("luatex")
 end
 
+find_file = kpsefind_file
+
 %    \end{macrocode}
 %     The lualibs load a merged package by default.
 %     In order to create one of these, the meta file that includes the
@@ -584,8 +584,8 @@
 
 local lualibs_basic_module = {
   name          = "lualibs-basic",
-  version       = 2.65,
-  date          = "2019-05-18",
+  version       = 2.66,
+  date          = "2019-07-04",
   description   = "ConTeXt Lua libraries -- basic collection.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",
@@ -666,8 +666,8 @@
 
 local lualibs_extended_module = {
   name          = "lualibs-extended",
-  version       = 2.65,
-  date          = "2019-05-18",
+  version       = 2.66,
+  date          = "2019-07-04",
   description   = "ConTeXt Lua libraries -- extended collection.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -1,6 +1,6 @@
 -- merged file : lualibs-basic-merged.lua
 -- parent file : lualibs-basic.lua
--- merge date  : Sat May 18 17:39:21 2019
+-- merge date  : Sun Jul 14 15:31:33 2019
 
 do -- begin closure to overcome local limits and interference
 
@@ -1294,9 +1294,11 @@
  end
 end
 local anything=patterns.anything
-local allescapes=Cc("%")*S(".-+%?()[]*") 
-local someescapes=Cc("%")*S(".-+%()[]")   
-local matchescapes=Cc(".")*S("*?")   
+local moreescapes=Cc("%")*S(".-+%?()[]*$^{}")
+local allescapes=Cc("%")*S(".-+%?()[]*")   
+local someescapes=Cc("%")*S(".-+%()[]")  
+local matchescapes=Cc(".")*S("*?")     
+local pattern_m=Cs ((moreescapes+anything )^0 )
 local pattern_a=Cs ((allescapes+anything )^0 )
 local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
 local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
@@ -1306,6 +1308,8 @@
 function string.topattern(str,lowercase,strict)
  if str=="" or type(str)~="string" then
   return ".*"
+ elseif strict=="all" then
+  str=lpegmatch(pattern_m,str)
  elseif strict then
   str=lpegmatch(pattern_c,str)
  else

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -29,8 +29,8 @@
 
 local lualibs_basic_module = {
   name          = "lualibs-basic",
-  version       = 2.65,
-  date          = "2019-05-18",
+  version       = 2.66,
+  date          = "2019-07-04",
   description   = "ConTeXt Lua libraries -- basic collection.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -1,6 +1,6 @@
 -- merged file : lualibs-extended-merged.lua
 -- parent file : lualibs-extended.lua
--- merge date  : Sat May 18 17:39:12 2019
+-- merge date  : Sun Jul 14 15:31:26 2019
 
 do -- begin closure to overcome local limits and interference
 
@@ -2762,121 +2762,325 @@
 local P,V,R,S,C,Cc,Cs,Ct,Cf,Cg=lpeg.P,lpeg.V,lpeg.R,lpeg.S,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cf,lpeg.Cg
 local lpegmatch=lpeg.match
 local format,gsub=string.format,string.gsub
+local formatters=string.formatters
 local utfchar=utf.char
-local concat=table.concat
+local concat,sortedkeys=table.concat,table.sortedkeys
 local tonumber,tostring,rawset,type,next=tonumber,tostring,rawset,type,next
 local json=utilities.json or {}
 utilities.json=json
-local lbrace=P("{")
-local rbrace=P("}")
-local lparent=P("[")
-local rparent=P("]")
-local comma=P(",")
-local colon=P(":")
-local dquote=P('"')
-local whitespace=lpeg.patterns.whitespace
-local optionalws=whitespace^0
-local escapes={
- ["b"]="\010",
- ["f"]="\014",
- ["n"]="\n",
- ["r"]="\r",
- ["t"]="\t",
-}
-local escape_un=P("\\u")/""*(C(R("09","AF","af")^-4)/function(s)
- return utfchar(tonumber(s,16))
-end)
-local escape_bs=P([[\]])/""*(P(1)/escapes) 
-local jstring=dquote*Cs((escape_un+escape_bs+(1-dquote))^0)*dquote
-local jtrue=P("true")*Cc(true)
-local jfalse=P("false")*Cc(false)
-local jnull=P("null")*Cc(nil)
-local jnumber=(1-whitespace-rparent-rbrace-comma)^1/tonumber
-local key=jstring
-local jsonconverter={ "value",
- hash=lbrace*Cf(Ct("")*(V("pair")*(comma*V("pair"))^0+optionalws),rawset)*rbrace,
- pair=Cg(optionalws*key*optionalws*colon*V("value")),
- array=Ct(lparent*(V("value")*(comma*V("value"))^0+optionalws)*rparent),
- value=optionalws*(jstring+V("hash")+V("array")+jtrue+jfalse+jnull+jnumber)*optionalws,
-}
-function json.tolua(str)
- return lpegmatch(jsonconverter,str)
+do
+ local lbrace=P("{")
+ local rbrace=P("}")
+ local lparent=P("[")
+ local rparent=P("]")
+ local comma=P(",")
+ local colon=P(":")
+ local dquote=P('"')
+ local whitespace=lpeg.patterns.whitespace
+ local optionalws=whitespace^0
+ local escapes={
+  ["b"]="\010",
+  ["f"]="\014",
+  ["n"]="\n",
+  ["r"]="\r",
+  ["t"]="\t",
+ }
+ local escape_un=P("\\u")/""*(C(R("09","AF","af")^-4)/function(s)
+  return utfchar(tonumber(s,16))
+ end)
+ local escape_bs=P([[\]])/""*(P(1)/escapes) 
+ local jstring=dquote*Cs((escape_un+escape_bs+(1-dquote))^0)*dquote
+ local jtrue=P("true")*Cc(true)
+ local jfalse=P("false")*Cc(false)
+ local jnull=P("null")*Cc(nil)
+ local jnumber=(1-whitespace-rparent-rbrace-comma)^1/tonumber
+ local key=jstring
+ local jsonconverter={ "value",
+  hash=lbrace*Cf(Ct("")*(V("pair")*(comma*V("pair"))^0+optionalws),rawset)*rbrace,
+  pair=Cg(optionalws*key*optionalws*colon*V("value")),
+  array=Ct(lparent*(V("value")*(comma*V("value"))^0+optionalws)*rparent),
+  value=optionalws*(jstring+V("hash")+V("array")+jtrue+jfalse+jnull+jnumber)*optionalws,
+ }
+ function json.tolua(str)
+  return lpegmatch(jsonconverter,str)
+ end
+ function json.load(filename)
+  local data=io.loaddata(filename)
+  if data then
+   return lpegmatch(jsonconverter,data)
+  end
+ end
 end
-local escaper
-local function tojson(value,t,n) 
- local kind=type(value)
- if kind=="table" then
-  local done=false
-  local size=#value
-  if size==0 then
-   for k,v in next,value do
-    if done then
-     n=n+1;t[n]=","
+do
+ local escaper
+ local f_start_hash=formatters[   '%w{' ]
+ local f_start_array=formatters[   '%w[' ]
+ local f_start_hash_new=formatters[ "\n"..'%w{' ]
+ local f_start_array_new=formatters[ "\n"..'%w[' ]
+ local f_start_hash_key=formatters[ "\n"..'%w"%s" : {' ]
+ local f_start_array_key=formatters[ "\n"..'%w"%s" : [' ]
+ local f_stop_hash=formatters[ "\n"..'%w}' ]
+ local f_stop_array=formatters[ "\n"..'%w]' ]
+ local f_key_val_seq=formatters[ "\n"..'%w"%s" : %s' ]
+ local f_key_val_str=formatters[ "\n"..'%w"%s" : "%s"'  ]
+ local f_key_val_num=f_key_val_seq
+ local f_key_val_yes=formatters[ "\n"..'%w"%s" : true'  ]
+ local f_key_val_nop=formatters[ "\n"..'%w"%s" : false' ]
+ local f_val_num=formatters[ "\n"..'%w%s' ]
+ local f_val_str=formatters[ "\n"..'%w"%s"'  ]
+ local f_val_yes=formatters[ "\n"..'%wtrue'  ]
+ local f_val_nop=formatters[ "\n"..'%wfalse' ]
+ local f_val_seq=f_val_num
+ local t={}
+ local n=0
+ local function is_simple_table(tt) 
+  local l=#tt
+  if l>0 then
+   for i=1,l do
+    if type(tt[i])=="table" then
+     return false
+    end
+   end
+   local nn=n
+   n=n+1 t[n]="[ "
+   for i=1,l do
+    if i>1 then
+     n=n+1 t[n]=", "
+    end
+    local v=tt[i]
+    local tv=type(v)
+    if tv=="number" then
+     n=n+1 t[n]=v
+    elseif tv=="string" then
+     n=n+1 t[n]='"'
+     n=n+1 t[n]=lpegmatch(escaper,v) or v
+     n=n+1 t[n]='"'
+    elseif tv=="boolean" then
+     n=n+1 t[n]=v and "true" or "false"
     else
-     n=n+1;t[n]="{"
-     done=true
+     n=n+1 t[n]=tostring(v)
     end
-    n=n+1;t[n]=format("%q:",k)
-    t,n=tojson(v,t,n)
    end
-   if done then
-    n=n+1;t[n]="}"
+   n=n+1 t[n]=" ]"
+   local s=concat(t,"",nn+1,n)
+   n=nn
+   return s
+  end
+  return false
+ end
+ local function tojsonpp(root,name,depth,level,size)
+  if root then
+   local indexed=size>0
+   n=n+1
+   if level==0 then
+    if indexed then
+     t[n]=f_start_array(depth)
+    else
+     t[n]=f_start_hash(depth)
+    end
+   elseif name then
+    if tn=="string" then
+     name=lpegmatch(escaper,name) or name
+    elseif tn~="number" then
+     name=tostring(name)
+    end
+    if indexed then
+     t[n]=f_start_array_key(depth,name)
+    else
+     t[n]=f_start_hash_key(depth,name)
+    end
    else
-    n=n+1;t[n]="{}"
+    if indexed then
+     t[n]=f_start_array_new(depth)
+    else
+     t[n]=f_start_hash_new(depth)
+    end
    end
-  elseif size==1 then
-   n=n+1;t[n]="["
-   t,n=tojson(value[1],t,n)
-   n=n+1;t[n]="]"
-  else
-   for i=1,size do
+   depth=depth+1
+   if indexed then 
+    for i=1,size do
+     if i>1 then
+      n=n+1 t[n]=","
+     end
+     local v=root[i]
+     local tv=type(v)
+     if tv=="number" then
+      n=n+1 t[n]=f_val_num(depth,v)
+     elseif tv=="string" then
+      v=lpegmatch(escaper,v) or v
+      n=n+1 t[n]=f_val_str(depth,v)
+     elseif tv=="table" then
+      if next(v) then
+       local st=is_simple_table(v)
+       if st then
+        n=n+1 t[n]=f_val_seq(depth,st)
+       else
+        tojsonpp(v,k,depth,level+1,0)
+       end
+      end
+     elseif tv=="boolean" then
+      n=n+1
+      if v then
+       t[n]=f_val_yes(depth,v)
+      else
+       t[n]=f_val_nop(depth,v)
+      end
+     end
+    end
+   elseif next(root) then
+    local sk=sortedkeys(root)
+    for i=1,#sk do
+     if i>1 then
+      n=n+1 t[n]=","
+     end
+     local k=sk[i]
+     local v=root[k]
+     local tv=type(v)
+     local tk=type(k)
+     if tv=="number" then
+      if tk=="number" then
+       n=n+1 t[n]=f_key_val_num(depth,k,v)
+      elseif tk=="string" then
+       k=lpegmatch(escaper,k) or k
+       n=n+1 t[n]=f_key_val_str(depth,k,v)
+      end
+     elseif tv=="string" then
+      if tk=="number" then
+       v=lpegmatch(escaper,v) or v
+       n=n+1 t[n]=f_key_val_num(depth,k,v)
+      elseif tk=="string" then
+       k=lpegmatch(escaper,k) or k
+       v=lpegmatch(escaper,v) or v
+       n=n+1 t[n]=f_key_val_str(depth,k,v)
+      end
+     elseif tv=="table" then
+      local l=#v
+      if l>0 then
+       local st=is_simple_table(v)
+       if not st then
+        tojsonpp(v,k,depth,level+1,l)
+       elseif tk=="number" then
+        n=n+1 t[n]=f_key_val_seq(depth,k,st)
+       elseif tk=="string" then
+        k=lpegmatch(escaper,k) or k
+        n=n+1 t[n]=f_key_val_seq(depth,k,st)
+       end
+      elseif next(v) then
+       tojsonpp(v,k,depth,level+1,0)
+      end
+     elseif tv=="boolean" then
+      if tk=="number" then
+       n=n+1
+       if v then
+        t[n]=f_key_val_yes(depth,k)
+       else
+        t[n]=f_key_val_nop(depth,k)
+       end
+      elseif tk=="string" then
+       k=lpegmatch(escaper,k) or k
+       n=n+1
+       if v then
+        t[n]=f_key_val_yes(depth,k)
+       else
+        t[n]=f_key_val_nop(depth,k)
+       end
+      end
+     end
+    end
+   end
+   n=n+1
+   if indexed then
+    t[n]=f_stop_array(depth-1)
+   else
+    t[n]=f_stop_hash(depth-1)
+   end
+  end
+ end
+ local function tojson(value,n)
+  local kind=type(value)
+  if kind=="table" then
+   local done=false
+   local size=#value
+   if size==0 then
+    for k,v in next,value do
+     if done then
+      n=n+1;t[n]=',"'
+     else
+      n=n+1;t[n]='{"'
+      done=true
+     end
+     n=n+1;t[n]=lpegmatch(escaper,k) or k
+     n=n+1;t[n]='":'
+     t,n=tojson(v,n)
+    end
     if done then
-     n=n+1;t[n]=","
+     n=n+1;t[n]="}"
     else
-     n=n+1;t[n]="["
-     done=true
+     n=n+1;t[n]="{}"
     end
-    t,n=tojson(value[i],t,n)
+   elseif size==1 then
+    n=n+1;t[n]="["
+    t,n=tojson(value[1],n)
+    n=n+1;t[n]="]"
+   else
+    for i=1,size do
+     if done then
+      n=n+1;t[n]=","
+     else
+      n=n+1;t[n]="["
+      done=true
+     end
+     t,n=tojson(value[i],n)
+    end
+    n=n+1;t[n]="]"
    end
-   n=n+1;t[n]="]"
+  elseif kind=="string"  then
+   n=n+1;t[n]='"'
+   n=n+1;t[n]=lpegmatch(escaper,value) or value
+   n=n+1;t[n]='"'
+  elseif kind=="number" then
+   n=n+1;t[n]=value
+  elseif kind=="boolean" then
+   n=n+1;t[n]=tostring(value)
   end
- elseif kind=="string"  then
-  n=n+1;t[n]='"'
-  n=n+1;t[n]=lpegmatch(escaper,value) or value
-  n=n+1;t[n]='"'
- elseif kind=="number" then
-  n=n+1;t[n]=value
- elseif kind=="boolean" then
-  n=n+1;t[n]=tostring(value)
+  return t,n
  end
- return t,n
-end
-function json.tostring(value)
- local kind=type(value)
- if kind=="table" then
-  if not escaper then
-   local escapes={
-    ["\\"]="\\u005C",
-    ["\""]="\\u0022",
-   }
-   for i=0,0x20 do
-    escapes[utfchar(i)]=format("\\u%04X",i)
+ local function jsontostring(value,pretty)
+  local kind=type(value)
+  if kind=="table" then
+   if not escaper then
+    local escapes={
+     ["\\"]="\\u005C",
+     ["\""]="\\u0022",
+    }
+    for i=0,0x1F do
+     escapes[utfchar(i)]=format("\\u%04X",i)
+    end
+    escaper=Cs((
+     (R('\0\x20')+S('\"\\'))/escapes+P(1)
+    )^1 )
    end
-   escaper=Cs((
-    (R('\0\x20')+S('\"\\'))/escapes+P(1)
-   )^1 )
+   t={}
+   n=0
+   if pretty then
+    tojsonpp(value,name,0,0,#value)
+    value=concat(t,"",1,n)
+   else
+    tojson(value,0)
+    value=concat(t,"",1,n)
+   end
+   t=nil
+   n=0
+   return value
+  elseif kind=="string" or kind=="number" then
+   return lpegmatch(escaper,value) or value
+  else
+   return tostring(value)
   end
-  return concat((tojson(value,{},0)))
- elseif kind=="string" or kind=="number" then
-  return lpegmatch(escaper,value) or value
- else
-  return tostring(value)
  end
-end
-function json.load(filename)
- local data=io.loaddata(filename)
- if data then
-  return lpegmatch(jsonconverter,data)
+ json.tostring=jsontostring
+ function json.tojson(value)
+  return jsontostring(value,true)
  end
 end
 return json

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -30,8 +30,8 @@
 
 local lualibs_extended_module = {
   name          = "lualibs-extended",
-  version       = 2.65,
-  date          = "2019-05-18",
+  version       = 2.66,
+  date          = "2019-07-04",
   description   = "ConTeXt Lua libraries -- extended collection.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -155,11 +155,13 @@
 --- needs checking
 
 local anything     = patterns.anything
-local allescapes   = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ?
-local someescapes  = Cc("%") * S(".-+%()[]")   -- also {} and ^$ ?
-local matchescapes = Cc(".") * S("*?")         -- wildcard and single match
+local moreescapes  = Cc("%") * S(".-+%?()[]*$^{}")
+local allescapes   = Cc("%") * S(".-+%?()[]*")   -- also {} and ^$ ?
+local someescapes  = Cc("%") * S(".-+%()[]")     -- also {} and ^$ ?
+local matchescapes = Cc(".") * S("*?")           -- wildcard and single match
 
-local pattern_a = Cs ( ( allescapes + anything )^0 )
+local pattern_m = Cs ( ( moreescapes + anything )^0 )
+local pattern_a = Cs ( ( allescapes  + anything )^0 )
 local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 )
 local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") )
 
@@ -170,6 +172,8 @@
 function string.topattern(str,lowercase,strict)
     if str == "" or type(str) ~= "string" then
         return ".*"
+    elseif strict == "all" then
+        str = lpegmatch(pattern_m,str)
     elseif strict then
         str = lpegmatch(pattern_c,str)
     else

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -20,8 +20,9 @@
 local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg
 local lpegmatch = lpeg.match
 local format, gsub = string.format, string.gsub
+local formatters = string.formatters
 local utfchar = utf.char
-local concat = table.concat
+local concat, sortedkeys = table.concat, table.sortedkeys
 
 local tonumber, tostring, rawset, type, next = tonumber, tostring, rawset, type, next
 
@@ -28,147 +29,382 @@
 local json      = utilities.json or { }
 utilities.json  = json
 
--- \\ \/ \b \f \n \r \t \uHHHH
+do
 
-local lbrace     = P("{")
-local rbrace     = P("}")
-local lparent    = P("[")
-local rparent    = P("]")
-local comma      = P(",")
-local colon      = P(":")
-local dquote     = P('"')
+    -- \\ \/ \b \f \n \r \t \uHHHH
 
-local whitespace = lpeg.patterns.whitespace
-local optionalws = whitespace^0
+    local lbrace     = P("{")
+    local rbrace     = P("}")
+    local lparent    = P("[")
+    local rparent    = P("]")
+    local comma      = P(",")
+    local colon      = P(":")
+    local dquote     = P('"')
 
-local escapes    = {
-    ["b"] = "\010",
-    ["f"] = "\014",
-    ["n"] = "\n",
-    ["r"] = "\r",
-    ["t"] = "\t",
-}
+    local whitespace = lpeg.patterns.whitespace
+    local optionalws = whitespace^0
 
--- todo: also handle larger utf16
+    local escapes    = {
+        ["b"] = "\010",
+        ["f"] = "\014",
+        ["n"] = "\n",
+        ["r"] = "\r",
+        ["t"] = "\t",
+    }
 
-local escape_un  = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s)
-    return utfchar(tonumber(s,16))
-end)
+    -- todo: also handle larger utf16
 
-local escape_bs  = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char
+    local escape_un  = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s)
+        return utfchar(tonumber(s,16))
+    end)
 
-local jstring    = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote
-local jtrue      = P("true")  * Cc(true)
-local jfalse     = P("false") * Cc(false)
-local jnull      = P("null")  * Cc(nil)
-local jnumber    = (1-whitespace-rparent-rbrace-comma)^1 / tonumber
+    local escape_bs  = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char
 
-local key        = jstring
+    local jstring    = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote
+    local jtrue      = P("true")  * Cc(true)
+    local jfalse     = P("false") * Cc(false)
+    local jnull      = P("null")  * Cc(nil)
+    local jnumber    = (1-whitespace-rparent-rbrace-comma)^1 / tonumber
 
-local jsonconverter = { "value",
-    hash  = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace,
-    pair  = Cg(optionalws * key * optionalws * colon * V("value")),
-    array = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent),
---  value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws,
-    value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws,
-}
+    local key        = jstring
 
--- local jsonconverter = { "value",
---     hash   = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace,
---     pair   = Cg(optionalws * V("string") * optionalws * colon * V("value")),
---     array  = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent),
---     string = jstring,
---     value  = optionalws * (V("string") + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws,
--- }
+    local jsonconverter = { "value",
+        hash  = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace,
+        pair  = Cg(optionalws * key * optionalws * colon * V("value")),
+        array = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent),
+    --  value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws,
+        value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws,
+    }
 
--- lpeg.print(jsonconverter) -- size 181
+    -- local jsonconverter = { "value",
+    --     hash   = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace,
+    --     pair   = Cg(optionalws * V("string") * optionalws * colon * V("value")),
+    --     array  = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent),
+    --     string = jstring,
+    --     value  = optionalws * (V("string") + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws,
+    -- }
 
-function json.tolua(str)
-    return lpegmatch(jsonconverter,str)
+    -- lpeg.print(jsonconverter) -- size 181
+
+    function json.tolua(str)
+        return lpegmatch(jsonconverter,str)
+    end
+
+    function json.load(filename)
+        local data = io.loaddata(filename)
+        if data then
+            return lpegmatch(jsonconverter,data)
+        end
+    end
+
 end
 
-local escaper
+do
 
-local function tojson(value,t,n) -- we could optimize #t
-    local kind = type(value)
-    if kind == "table" then
-        local done = false
-        local size = #value
-        if size == 0 then
-            for k, v in next, value do
-                if done then
-                    n = n + 1 ; t[n] = ","
+    -- It's pretty bad that JSON doesn't allow the trailing comma ... it's a
+    -- typical example of a spec that then forces all generators to check for
+    -- this. It's a way to make sure programmers keep jobs.
+
+    local escaper
+
+    local f_start_hash      = formatters[         '%w{' ]
+    local f_start_array     = formatters[         '%w[' ]
+    local f_start_hash_new  = formatters[ "\n" .. '%w{' ]
+    local f_start_array_new = formatters[ "\n" .. '%w[' ]
+    local f_start_hash_key  = formatters[ "\n" .. '%w"%s" : {' ]
+    local f_start_array_key = formatters[ "\n" .. '%w"%s" : [' ]
+
+    local f_stop_hash       = formatters[ "\n" .. '%w}' ]
+    local f_stop_array      = formatters[ "\n" .. '%w]' ]
+
+    local f_key_val_seq     = formatters[ "\n" .. '%w"%s" : %s'    ]
+    local f_key_val_str     = formatters[ "\n" .. '%w"%s" : "%s"'  ]
+    local f_key_val_num     = f_key_val_seq
+    local f_key_val_yes     = formatters[ "\n" .. '%w"%s" : true'  ]
+    local f_key_val_nop     = formatters[ "\n" .. '%w"%s" : false' ]
+
+    local f_val_num         = formatters[ "\n" .. '%w%s'    ]
+    local f_val_str         = formatters[ "\n" .. '%w"%s"'  ]
+    local f_val_yes         = formatters[ "\n" .. '%wtrue'  ]
+    local f_val_nop         = formatters[ "\n" .. '%wfalse' ]
+    local f_val_seq         = f_val_num
+
+    -- no empty tables because unknown if table or hash
+
+    local t = { }
+    local n = 0
+
+    local function is_simple_table(tt) -- also used in util-tab so maybe public
+        local l = #tt
+        if l > 0 then
+            for i=1,l do
+                if type(tt[i]) == "table" then
+                    return false
+                end
+            end
+            local nn = n
+            n = n + 1 t[n] = "[ "
+            for i=1,l do
+                if i > 1 then
+                    n = n + 1 t[n] = ", "
+                end
+                local v = tt[i]
+                local tv = type(v)
+                if tv == "number" then
+                    n = n + 1 t[n] = v
+                elseif tv == "string" then
+                    n = n + 1 t[n] = '"'
+                    n = n + 1 t[n] = lpegmatch(escaper,v) or v
+                    n = n + 1 t[n] = '"'
+                elseif tv == "boolean" then
+                    n = n + 1 t[n] = v and "true" or "false"
                 else
-                    n = n + 1 ; t[n] = "{"
-                    done = true
+                    n = n + 1 t[n] = tostring(v)
                 end
-                n = n + 1 ; t[n] = format("%q:",k)
-                t, n = tojson(v,t,n)
             end
-            if done then
-                n = n + 1 ; t[n] = "}"
+            n = n + 1 t[n] = " ]"
+            local s = concat(t,"",nn+1,n)
+            n = nn
+            return s
+        end
+        return false
+    end
+
+    local function tojsonpp(root,name,depth,level,size)
+        if root then
+            local indexed = size > 0
+            n = n + 1
+            if level == 0 then
+                if indexed then
+                    t[n] = f_start_array(depth)
+                else
+                    t[n] = f_start_hash(depth)
+                end
+            elseif name then
+                if tn == "string" then
+                    name = lpegmatch(escaper,name) or name
+                elseif tn ~= "number" then
+                    name = tostring(name)
+                end
+                if indexed then
+                    t[n] = f_start_array_key(depth,name)
+                else
+                    t[n] = f_start_hash_key(depth,name)
+                end
             else
-                n = n + 1 ; t[n] = "{}"
+                if indexed then
+                    t[n] = f_start_array_new(depth)
+                else
+                    t[n] = f_start_hash_new(depth)
+                end
             end
-        elseif size == 1 then
-            -- we can optimize for non tables
-            n = n + 1 ; t[n] = "["
-            t, n = tojson(value[1],t,n)
-            n = n + 1 ; t[n] = "]"
-        else
-            for i=1,size do
+            depth = depth + 1
+            if indexed then -- indexed
+                for i=1,size do
+                    if i > 1 then
+                        n = n + 1 t[n] = ","
+                    end
+                    local v  = root[i]
+                    local tv = type(v)
+                    if tv == "number" then
+                        n = n + 1 t[n] = f_val_num(depth,v)
+                    elseif tv == "string" then
+                        v = lpegmatch(escaper,v) or v
+                        n = n + 1 t[n] = f_val_str(depth,v)
+                    elseif tv == "table" then
+                        if next(v) then
+                            local st = is_simple_table(v)
+                            if st then
+                                n = n + 1 t[n] = f_val_seq(depth,st)
+                            else
+                                tojsonpp(v,k,depth,level+1,0)
+                            end
+                        end
+                    elseif tv == "boolean" then
+                        n = n + 1
+                        if v then
+                            t[n] = f_val_yes(depth,v)
+                        else
+                            t[n] = f_val_nop(depth,v)
+                        end
+                    end
+                end
+            elseif next(root) then
+                local sk = sortedkeys(root)
+                for i=1,#sk do
+                    if i > 1 then
+                        n = n + 1 t[n] = ","
+                    end
+                    local k  = sk[i]
+                    local v  = root[k]
+                    local tv = type(v)
+                    local tk = type(k)
+                    if tv == "number" then
+                        if tk == "number" then
+                            n = n + 1 t[n] = f_key_val_num(depth,k,v)
+                        elseif tk == "string" then
+                            k = lpegmatch(escaper,k) or k
+                            n = n + 1 t[n] = f_key_val_str(depth,k,v)
+                        end
+                    elseif tv == "string" then
+                        if tk == "number" then
+                            v = lpegmatch(escaper,v) or v
+                            n = n + 1 t[n] = f_key_val_num(depth,k,v)
+                        elseif tk == "string" then
+                            k = lpegmatch(escaper,k) or k
+                            v = lpegmatch(escaper,v) or v
+                            n = n + 1 t[n] = f_key_val_str(depth,k,v)
+                        end
+                    elseif tv == "table" then
+                        local l = #v
+                        if l > 0 then
+                            local st = is_simple_table(v)
+                            if not st then
+                                tojsonpp(v,k,depth,level+1,l)
+                            elseif tk == "number" then
+                                n = n + 1 t[n] = f_key_val_seq(depth,k,st)
+                            elseif tk == "string" then
+                                k = lpegmatch(escaper,k) or k
+                                n = n + 1 t[n] = f_key_val_seq(depth,k,st)
+                            end
+                        elseif next(v) then
+                            tojsonpp(v,k,depth,level+1,0)
+                        end
+                    elseif tv == "boolean" then
+                        if tk == "number" then
+                            n = n + 1
+                            if v then
+                                t[n] = f_key_val_yes(depth,k)
+                            else
+                                t[n] = f_key_val_nop(depth,k)
+                            end
+                        elseif tk == "string" then
+                            k = lpegmatch(escaper,k) or k
+                            n = n + 1
+                            if v then
+                                t[n] = f_key_val_yes(depth,k)
+                            else
+                                t[n] = f_key_val_nop(depth,k)
+                            end
+                        end
+                    end
+                end
+            end
+            n = n + 1
+            if indexed then
+                t[n] = f_stop_array(depth-1)
+            else
+                t[n] = f_stop_hash(depth-1)
+            end
+        end
+    end
+
+    local function tojson(value,n)
+        local kind = type(value)
+        if kind == "table" then
+            local done = false
+            local size = #value
+            if size == 0 then
+                for k, v in next, value do
+                    if done then
+                     -- n = n + 1 ; t[n] = ","
+                        n = n + 1 ; t[n] = ',"'
+                    else
+                     -- n = n + 1 ; t[n] = "{"
+                        n = n + 1 ; t[n] = '{"'
+                        done = true
+                    end
+                    n = n + 1 ; t[n] = lpegmatch(escaper,k) or k
+                    n = n + 1 ; t[n] = '":'
+                    t, n = tojson(v,n)
+                end
                 if done then
-                    n = n + 1 ; t[n] = ","
+                    n = n + 1 ; t[n] = "}"
                 else
-                    n = n + 1 ; t[n] = "["
-                    done = true
+                    n = n + 1 ; t[n] = "{}"
                 end
-                t, n = tojson(value[i],t,n)
+            elseif size == 1 then
+                -- we can optimize for non tables
+                n = n + 1 ; t[n] = "["
+                t, n = tojson(value[1],n)
+                n = n + 1 ; t[n] = "]"
+            else
+                for i=1,size do
+                    if done then
+                        n = n + 1 ; t[n] = ","
+                    else
+                        n = n + 1 ; t[n] = "["
+                        done = true
+                    end
+                    t, n = tojson(value[i],n)
+                end
+                n = n + 1 ; t[n] = "]"
             end
-            n = n + 1 ; t[n] = "]"
+        elseif kind == "string"  then
+            n = n + 1 ; t[n] = '"'
+            n = n + 1 ; t[n] = lpegmatch(escaper,value) or value
+            n = n + 1 ; t[n] = '"'
+        elseif kind == "number" then
+            n = n + 1 ; t[n] = value
+        elseif kind == "boolean" then
+            n = n + 1 ; t[n] = tostring(value)
         end
-    elseif kind == "string"  then
-        n = n + 1 ; t[n] = '"'
-        n = n + 1 ; t[n] = lpegmatch(escaper,value) or value
-        n = n + 1 ; t[n] = '"'
-    elseif kind == "number" then
-        n = n + 1 ; t[n] = value
-    elseif kind == "boolean" then
-        n = n + 1 ; t[n] = tostring(value)
+        return t, n
     end
-    return t, n
-end
 
-function json.tostring(value)
-    -- todo optimize for non table
-    local kind = type(value)
-    if kind == "table" then
-        if not escaper then
-            local escapes = {
-                ["\\"] = "\\u005C",
-                ["\""] = "\\u0022",
-            }
-            for i=0,0x20 do
-                escapes[utfchar(i)] = format("\\u%04X",i)
+    -- escaping keys can become an option
+
+    local function jsontostring(value,pretty)
+        -- todo optimize for non table
+        local kind = type(value)
+        if kind == "table" then
+            if not escaper then
+                local escapes = {
+                    ["\\"] = "\\u005C",
+                    ["\""] = "\\u0022",
+                }
+                for i=0,0x1F do
+                    escapes[utfchar(i)] = format("\\u%04X",i)
+                end
+                escaper = Cs( (
+                    (R('\0\x20') + S('\"\\')) / escapes
+                  + P(1)
+                )^1 )
+
             end
-            escaper = Cs( (
-                (R('\0\x20') + S('\"\\')) / escapes
-              + P(1)
-            )^1 )
-
+            -- local to the closure (saves wrapping and local functions)
+            t = { }
+            n = 0
+            if pretty then
+                tojsonpp(value,name,0,0,#value)
+--                 value = concat(t,"\n",1,n)
+                value = concat(t,"",1,n)
+            else
+                tojson(value,0)
+                value = concat(t,"",1,n)
+            end
+            t = nil
+            n = 0
+            return value
+        elseif kind == "string" or kind == "number" then
+            return lpegmatch(escaper,value) or value
+        else
+            return tostring(value)
         end
-        return concat((tojson(value,{},0)))
-    elseif kind == "string" or kind == "number" then
-        return lpegmatch(escaper,value) or value
-    else
-        return tostring(value)
     end
+
+    json.tostring = jsontostring
+
+    function json.tojson(value)
+        return jsontostring(value,true)
+    end
+
 end
 
--- local tmp = [[ { "t" : "foobar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
+-- local tmp = [[ { "t\nt t" : "foo bar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
 -- tmp = json.tolua(tmp)
 -- inspect(tmp)
--- tmp = json.tostring(tmp)
+-- tmp = json.tostring(tmp,true)
 -- inspect(tmp)
 -- tmp = json.tolua(tmp)
 -- inspect(tmp)
@@ -176,13 +412,6 @@
 -- inspect(tmp)
 -- inspect(json.tostring(true))
 
-function json.load(filename)
-    local data = io.loaddata(filename)
-    if data then
-        return lpegmatch(jsonconverter,data)
-    end
-end
-
 -- local s = [[\foo"bar"]]
 -- local j = json.tostring { s = s }
 -- local l = json.tolua(j)

Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua	2019-07-14 20:48:21 UTC (rev 51641)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua	2019-07-14 20:48:50 UTC (rev 51642)
@@ -25,8 +25,8 @@
 
 lualibs.module_info = {
   name          = "lualibs",
-  version       = 2.65,
-  date          = "2019-05-18",
+  version       = 2.66,
+  date          = "2019-07-04",
   description   = "ConTeXt Lua standard libraries.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",
@@ -79,14 +79,14 @@
   lualibs.error, lualibs.warn, lualibs.info = error, warn, info
 end
 
-if luatexbase and luatexbase.find_file then
-  find_file = luatexbase.find_file
-else
-  kpse.set_program_name"luatex"
-  find_file = kpsefind_file
+local info = status.list()
+if info.kpse_used == 0 then
+ kpse.set_program_name("luatex")
 end
 
+find_file = kpsefind_file
 
+
 local loadmodule = loadmodule or function (name, t)
   if not t then t = "library" end
   local filepath  = find_file(name, "lua")



More information about the tex-live-commits mailing list