summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <phg42.2a@gmail.com>2014-07-05 14:52:28 +0200
committerPhilipp Gesang <phg42.2a@gmail.com>2014-07-05 14:52:28 +0200
commitce31f05f5fb463bf71f6eb86a94720839e686ba2 (patch)
treea51db627275c3a503e54eebf329439c080234aee
parentcc8eda7f75260c2e1486248df5c56abffb449f65 (diff)
downloadlualibs-ce31f05f5fb463bf71f6eb86a94720839e686ba2.tar.gz
sync with context as of 2014-07-05
-rw-r--r--lualibs-dir.lua303
-rw-r--r--lualibs-lpeg.lua82
-rw-r--r--lualibs-table.lua80
-rw-r--r--lualibs-util-prs.lua30
-rw-r--r--lualibs-util-str.lua25
5 files changed, 370 insertions, 150 deletions
diff --git a/lualibs-dir.lua b/lualibs-dir.lua
index 2572120..660529b 100644
--- a/lualibs-dir.lua
+++ b/lualibs-dir.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['l-dir'] = {
-- dir.expandname will be merged with cleanpath and collapsepath
local type, select = type, select
-local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
+local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub
local concat, insert, remove, unpack = table.concat, table.insert, table.remove, table.unpack
local lpegmatch = lpeg.match
@@ -21,8 +21,8 @@ local lfs = lfs
local attributes = lfs.attributes
local walkdir = lfs.dir
-local isdir = lfs.isdir
-local isfile = lfs.isfile
+local isdir = lfs.isdir -- not robust, will be overloaded anyway
+local isfile = lfs.isfile -- not robust, will be overloaded anyway
local currentdir = lfs.currentdir
local chdir = lfs.chdir
local mkdir = lfs.mkdir
@@ -31,20 +31,36 @@ local onwindows = os.type == "windows" or find(os.getenv("PATH"),";",1,true)
-- in case we load outside luatex
-if not isdir then
- function isdir(name)
- local a = attributes(name)
- return a and a.mode == "directory"
+if onwindows then
+
+ -- lfs.isdir does not like trailing /
+ -- lfs.dir accepts trailing /
+
+ isdir = function(name)
+ name = gsub(name,"([/\\]+)$","/.")
+ return attributes(name,"mode") == "directory"
end
- lfs.isdir = isdir
-end
-if not isfile then
- function isfile(name)
- local a = attributes(name)
- return a and a.mode == "file"
+ isfile = function(name)
+ return attributes(name,"mode") == "file"
+ end
+
+ lfs.isdir = isdir
+ lfs.isfile = isfile
+
+else
+
+ isdir = function(name)
+ return attributes(name,"mode") == "directory"
end
+
+ isfile = function(name)
+ return attributes(name,"mode") == "file"
+ end
+
+ lfs.isdir = isdir
lfs.isfile = isfile
+
end
-- handy
@@ -53,63 +69,104 @@ function dir.current()
return (gsub(currentdir(),"\\","/"))
end
--- optimizing for no find (*) does not save time
-
---~ local function globpattern(path,patt,recurse,action) -- fails in recent luatex due to some change in lfs
---~ local ok, scanner
---~ if path == "/" then
---~ ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
---~ else
---~ ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
---~ end
---~ if ok and type(scanner) == "function" then
---~ if not find(path,"/$") then path = path .. '/' end
---~ for name in scanner do
---~ local full = path .. name
---~ local mode = attributes(full,'mode')
---~ if mode == 'file' then
---~ if find(full,patt) then
---~ action(full)
---~ end
---~ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
---~ globpattern(full,patt,recurse,action)
---~ end
---~ end
---~ end
---~ end
-
-local lfsisdir = isdir
-
-local function isdir(path)
- path = gsub(path,"[/\\]+$","")
- return lfsisdir(path)
-end
+-- somewhat optimized
-lfs.isdir = isdir
+local function glob_pattern_function(path,patt,recurse,action)
+ if isdir(path) then
+ local usedpath
+ if path == "/" then
+ usedpath = "/."
+ elseif not find(path,"/$") then
+ usedpath = path .. "/."
+ path = path .. "/"
+ else
+ usedpath = path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name ~= "." and name ~= ".." then
+ local full = path .. name
+ local mode = attributes(full,'mode')
+ if mode == 'file' then
+ if not patt or find(full,patt) then
+ action(full)
+ end
+ elseif recurse and mode == "directory" then
+ if not dirs then
+ dirs = { full }
+ else
+ dirs[#dirs+1] = full
+ end
+ end
+ end
+ end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_function(dirs[i],patt,recurse,action)
+ end
+ end
+ end
+end
-local function globpattern(path,patt,recurse,action)
- if path == "/" then
- path = path .. "."
- elseif not find(path,"/$") then
- path = path .. '/'
+local function glob_pattern_table(path,patt,recurse,result)
+ if not result then
+ result = { }
end
- if isdir(path) then -- lfs.isdir does not like trailing /
- for name in walkdir(path) do -- lfs.dir accepts trailing /
- local full = path .. name
- local mode = attributes(full,'mode')
- if mode == 'file' then
- if find(full,patt) then
- action(full)
+ if isdir(path) then
+ local usedpath
+ if path == "/" then
+ usedpath = "/."
+ elseif not find(path,"/$") then
+ usedpath = path .. "/."
+ path = path .. "/"
+ else
+ usedpath = path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name ~= "." and name ~= ".." then
+ local full = path .. name
+ local mode = attributes(full,'mode')
+ if mode == 'file' then
+ if not patt or find(full,patt) then
+ result[#result+1] = full
+ end
+ elseif recurse and mode == "directory" then
+ if not dirs then
+ dirs = { full }
+ else
+ dirs[#dirs+1] = full
+ end
end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- globpattern(full,patt,recurse,action)
end
end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_table(dirs[i],patt,recurse,result)
+ end
+ end
+ end
+ return result
+end
+
+local function globpattern(path,patt,recurse,method)
+ local kind = type(method)
+ if pattern and sub(patt,1,-3) == path then
+ patt = false
+ end
+ if kind == "function" then
+ return glob_pattern_function(path,patt,recurse,method)
+ elseif kind == "table" then
+ return glob_pattern_table(path,patt,recurse,method)
+ else
+ return glob_pattern_table(path,patt,recurse,{ })
end
end
dir.globpattern = globpattern
+-- never or seldom used so far:
+
local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
@@ -119,18 +176,26 @@ local function collectpattern(path,patt,recurse,result)
ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
- if not find(path,"/$") then path = path .. '/' end
+ if not find(path,"/$") then
+ path = path .. '/'
+ end
for name in scanner, first do
- local full = path .. name
- local attr = attributes(full)
- local mode = attr.mode
- if mode == 'file' then
- if find(full,patt) then
+ if name == "." then
+ -- skip
+ elseif name == ".." then
+ -- skip
+ else
+ local full = path .. name
+ local attr = attributes(full)
+ local mode = attr.mode
+ if mode == 'file' then
+ if find(full,patt) then
+ result[name] = attr
+ end
+ elseif recurse and mode == "directory" then
+ attr.list = collectpattern(full,patt,recurse)
result[name] = attr
end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- attr.list = collectpattern(full,patt,recurse)
- result[name] = attr
end
end
end
@@ -143,15 +208,10 @@ local separator
if onwindows then -- we could sanitize here
--- pattern = Ct {
--- [1] = (C(P(".") + S("/\\")^1) + C(R("az","AZ") * P(":") * S("/\\")^0) + Cc("./")) * V(2) * V(3),
--- [2] = C(((1-S("*?/\\"))^0 * S("/\\"))^0),
--- [3] = C(P(1)^0)
--- }
-
local slash = S("/\\") / "/"
- pattern = Ct {
+-- pattern = Ct {
+ pattern = {
[1] = (Cs(P(".") + slash^1) + Cs(R("az","AZ") * P(":") * slash^0) + Cc("./")) * V(2) * V(3),
[2] = Cs(((1-S("*?/\\"))^0 * slash)^0),
[3] = Cs(P(1)^0)
@@ -159,7 +219,8 @@ if onwindows then -- we could sanitize here
else -- assume unix
- pattern = Ct {
+-- pattern = Ct {
+ pattern = {
[1] = (C(P(".") + P("/")^1) + Cc("./")) * V(2) * V(3),
[2] = C(((1-S("*?/"))^0 * P("/"))^0),
[3] = C(P(1)^0)
@@ -186,12 +247,11 @@ local function glob(str,t)
elseif isfile(str) then
t(str)
else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local root, path, base = split[1], split[2], split[3]
+ local root, path, base = lpegmatch(pattern,str) -- we could use the file splitter
+ if root and path and base then
local recurse = find(base,"**",1,true) -- find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
globpattern(start,result,recurse,t)
end
end
@@ -210,16 +270,12 @@ local function glob(str,t)
return { str }
end
else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local t = t or { }
- local action = action or function(name) t[#t+1] = name end
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"**",1,true) -- find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,action)
- return t
+ local root, path, base = lpegmatch(pattern,str) -- we could use the file splitter
+ if root and path and base then
+ local recurse = find(base,"**",1,true) -- find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ return globpattern(start,result,recurse,t)
else
return { }
end
@@ -229,11 +285,20 @@ end
dir.glob = glob
---~ list = dir.glob("**/*.tif")
---~ list = dir.glob("/**/*.tif")
---~ list = dir.glob("./**/*.tif")
---~ list = dir.glob("oeps/**/*.tif")
---~ list = dir.glob("/oeps/**/*.tif")
+-- local c = os.clock()
+-- local t = dir.glob("e:/**")
+-- local t = dir.glob("t:/sources/**")
+-- local t = dir.glob("t:/**")
+-- print(os.clock()-c,#t)
+
+-- for i=1,3000 do print(t[i]) end
+-- for i=1,10 do print(t[i]) end
+
+-- list = dir.glob("**/*.tif")
+-- list = dir.glob("/**/*.tif")
+-- list = dir.glob("./**/*.tif")
+-- list = dir.glob("oeps/**/*.tif")
+-- list = dir.glob("/oeps/**/*.tif")
local function globfiles(path,recurse,func,files) -- func == pattern or function
if type(func) == "string" then
@@ -275,10 +340,10 @@ function dir.ls(pattern)
return concat(glob(pattern),"\n")
end
---~ mkdirs("temp")
---~ mkdirs("a/b/c")
---~ mkdirs(".","/a/b/c")
---~ mkdirs("a","b","c")
+-- mkdirs("temp")
+-- mkdirs("a/b/c")
+-- mkdirs(".","/a/b/c")
+-- mkdirs("a","b","c")
local make_indeed = true -- false
@@ -347,17 +412,17 @@ if onwindows then
return pth, (isdir(pth) == true)
end
- --~ print(dir.mkdirs("","","a","c"))
- --~ print(dir.mkdirs("a"))
- --~ print(dir.mkdirs("a:"))
- --~ print(dir.mkdirs("a:/b/c"))
- --~ print(dir.mkdirs("a:b/c"))
- --~ print(dir.mkdirs("a:/bbb/c"))
- --~ print(dir.mkdirs("/a/b/c"))
- --~ print(dir.mkdirs("/aaa/b/c"))
- --~ print(dir.mkdirs("//a/b/c"))
- --~ print(dir.mkdirs("///a/b/c"))
- --~ print(dir.mkdirs("a/bbb//ccc/"))
+ -- print(dir.mkdirs("","","a","c"))
+ -- print(dir.mkdirs("a"))
+ -- print(dir.mkdirs("a:"))
+ -- print(dir.mkdirs("a:/b/c"))
+ -- print(dir.mkdirs("a:b/c"))
+ -- print(dir.mkdirs("a:/bbb/c"))
+ -- print(dir.mkdirs("/a/b/c"))
+ -- print(dir.mkdirs("/aaa/b/c"))
+ -- print(dir.mkdirs("//a/b/c"))
+ -- print(dir.mkdirs("///a/b/c"))
+ -- print(dir.mkdirs("a/bbb//ccc/"))
else
@@ -408,13 +473,13 @@ else
return pth, (isdir(pth) == true)
end
- --~ print(dir.mkdirs("","","a","c"))
- --~ print(dir.mkdirs("a"))
- --~ print(dir.mkdirs("/a/b/c"))
- --~ print(dir.mkdirs("/aaa/b/c"))
- --~ print(dir.mkdirs("//a/b/c"))
- --~ print(dir.mkdirs("///a/b/c"))
- --~ print(dir.mkdirs("a/bbb//ccc/"))
+ -- print(dir.mkdirs("","","a","c"))
+ -- print(dir.mkdirs("a"))
+ -- print(dir.mkdirs("/a/b/c"))
+ -- print(dir.mkdirs("/aaa/b/c"))
+ -- print(dir.mkdirs("//a/b/c"))
+ -- print(dir.mkdirs("///a/b/c"))
+ -- print(dir.mkdirs("a/bbb//ccc/"))
end
@@ -424,7 +489,7 @@ dir.makedirs = dir.mkdirs
if onwindows then
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
+ function dir.expandname(str) -- will be merged with cleanpath and collapsepath\
local first, nothing, last = match(str,"^(//)(//*)(.*)$")
if first then
first = dir.current() .. "/" -- dir.current sanitizes
diff --git a/lualibs-lpeg.lua b/lualibs-lpeg.lua
index 666af21..c203d80 100644
--- a/lualibs-lpeg.lua
+++ b/lualibs-lpeg.lua
@@ -225,9 +225,12 @@ patterns.integer = sign^-1 * digit^1
patterns.unsigned = digit^0 * period * digit^1
patterns.float = sign^-1 * patterns.unsigned
patterns.cunsigned = digit^0 * comma * digit^1
+patterns.cpunsigned = digit^0 * (period + comma) * digit^1
patterns.cfloat = sign^-1 * patterns.cunsigned
+patterns.cpfloat = sign^-1 * patterns.cpunsigned
patterns.number = patterns.float + patterns.integer
patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.cpnumber = patterns.cpfloat + patterns.integer
patterns.oct = zero * octdigit^1
patterns.octal = patterns.oct
patterns.HEX = zero * P("X") * (digit+uppercase)^1
@@ -813,21 +816,76 @@ end
-- experiment:
-local function make(t)
- local p
+-- local function make(t)
+-- local p
+-- local keys = sortedkeys(t)
+-- for i=1,#keys do
+-- local k = keys[i]
+-- local v = t[k]
+-- if not p then
+-- if next(v) then
+-- p = P(k) * make(v)
+-- else
+-- p = P(k)
+-- end
+-- else
+-- if next(v) then
+-- p = p + P(k) * make(v)
+-- else
+-- p = p + P(k)
+-- end
+-- end
+-- end
+-- return p
+-- end
+
+-- local function make(t)
+-- local p = P(false)
+-- local keys = sortedkeys(t)
+-- for i=1,#keys do
+-- local k = keys[i]
+-- local v = t[k]
+-- if next(v) then
+-- p = p + P(k) * make(v)
+-- else
+-- p = p + P(k)
+-- end
+-- end
+-- return p
+-- end
+
+-- function lpeg.utfchartabletopattern(list) -- goes to util-lpg
+-- local tree = { }
+-- for i=1,#list do
+-- local t = tree
+-- for c in gmatch(list[i],".") do
+-- local tc = t[c]
+-- if not tc then
+-- tc = { }
+-- t[c] = tc
+-- end
+-- t = tc
+-- end
+-- end
+-- return make(tree)
+-- end
+
+local function make(t,hash)
+ local p = P(false)
local keys = sortedkeys(t)
for i=1,#keys do
local k = keys[i]
local v = t[k]
- if not p then
+ local h = hash[v]
+ if h then
if next(v) then
- p = P(k) * make(v)
+ p = p + P(k) * (make(v,hash) + P(true))
else
- p = P(k)
+ p = p + P(k) * P(true)
end
else
if next(v) then
- p = p + P(k) * make(v)
+ p = p + P(k) * make(v,hash)
else
p = p + P(k)
end
@@ -838,16 +896,20 @@ end
function lpeg.utfchartabletopattern(list) -- goes to util-lpg
local tree = { }
+ local hash = { }
for i=1,#list do
local t = tree
for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
+ local tc = t[c]
+ if not tc then
+ tc = { }
+ t[c] = tc
end
- t = t[c]
+ t = tc
end
+ hash[t] = list[i]
end
- return make(tree)
+ return make(tree,hash)
end
-- inspect ( lpeg.utfchartabletopattern {
diff --git a/lualibs-table.lua b/lualibs-table.lua
index d231830..ca067fb 100644
--- a/lualibs-table.lua
+++ b/lualibs-table.lua
@@ -164,14 +164,14 @@ local function sortedhash(t,cmp)
end
local n = 0
local m = #s
- local function kv(s)
+ local function kv() -- (s)
if n < m then
n = n + 1
local k = s[n]
return k, t[k]
end
end
- return kv, s
+ return kv -- , s
else
return nothing
end
@@ -400,7 +400,7 @@ local function simple_table(t)
if tv == "number" then
nt = nt + 1
if hexify then
- tt[nt] = format("0x%04X",v)
+ tt[nt] = format("0x%X",v)
else
tt[nt] = tostring(v) -- tostring not needed
end
@@ -451,7 +451,7 @@ local function do_serialize(root,name,depth,level,indexed)
local tn = type(name)
if tn == "number" then
if hexify then
- handle(format("%s[0x%04X]={",depth,name))
+ handle(format("%s[0x%X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
@@ -502,7 +502,7 @@ local function do_serialize(root,name,depth,level,indexed)
if compact and first and tk == "number" and k >= first and k <= last then
if tv == "number" then
if hexify then
- handle(format("%s 0x%04X,",depth,v))
+ handle(format("%s 0x%X,",depth,v))
else
handle(format("%s %s,",depth,v)) -- %.99g
end
@@ -543,25 +543,25 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv == "number" then
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ handle(format("%s [0x%X]=0x%X,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g
end
elseif tk == "boolean" then
if hexify then
- handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v))
+ handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g
end
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
+ handle(format("%s %s=0x%X,",depth,k,v))
else
handle(format("%s %s=%s,",depth,k,v)) -- %.99g
end
else
if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
+ handle(format("%s [%q]=0x%X,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g
end
@@ -570,7 +570,7 @@ local function do_serialize(root,name,depth,level,indexed)
if reduce and tonumber(v) then
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
+ handle(format("%s [0x%X]=%s,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
@@ -584,7 +584,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
+ handle(format("%s [0x%X]=%q,",depth,k,v))
else
handle(format("%s [%s]=%q,",depth,k,v))
end
@@ -600,7 +600,7 @@ local function do_serialize(root,name,depth,level,indexed)
if not next(v) then
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
+ handle(format("%s [0x%X]={},",depth,k))
else
handle(format("%s [%s]={},",depth,k))
end
@@ -616,7 +616,7 @@ local function do_serialize(root,name,depth,level,indexed)
if st then
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
@@ -636,7 +636,7 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv == "boolean" then
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false"))
+ handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
else
handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
end
@@ -653,7 +653,7 @@ local function do_serialize(root,name,depth,level,indexed)
-- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ handle(format("%s [0x%X]=load(%q),",depth,k,f))
else
handle(format("%s [%s]=load(%q),",depth,k,f))
end
@@ -668,7 +668,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk == "number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
@@ -727,7 +727,7 @@ local function serialize(_handle,root,name,specification) -- handle wins
end
elseif tname == "number" then
if hexify then
- handle(format("[0x%04X]={",name))
+ handle(format("[0x%X]={",name))
else
handle("[" .. name .. "]={")
end
@@ -1114,3 +1114,49 @@ function table.values(t,s) -- optional sort flag
return { }
end
end
+
+-- maybe this will move to util-tab.lua
+
+-- for k, v in table.filtered(t,pattern) do ... end
+-- for k, v in table.filtered(t,pattern,true) do ... end
+-- for k, v in table.filtered(t,pattern,true,cmp) do ... end
+
+function table.filtered(t,pattern,sort,cmp)
+ if t and type(pattern) == "string" then
+ if sort 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 n = 0
+ local m = #s
+ local function kv(s)
+ while n < m do
+ n = n + 1
+ local k = s[n]
+ if find(k,pattern) then
+ return k, t[k]
+ end
+ end
+ end
+ return kv, s
+ else
+ local n = next(t)
+ local function iterator()
+ while n do
+ local k = n
+ n = next(t,k)
+ if find(k,pattern) then
+ return k, t[k]
+ end
+ end
+ end
+ return iterator, t
+ end
+ else
+ return nothing
+ end
+end
diff --git a/lualibs-util-prs.lua b/lualibs-util-prs.lua
index 2cede91..f51f6fc 100644
--- a/lualibs-util-prs.lua
+++ b/lualibs-util-prs.lua
@@ -542,8 +542,8 @@ end
--
-local pattern_math = Cs((P("%")/"\\percent " + P("^") * Cc("{") * lpegpatterns.integer * Cc("}") + P(1))^0)
-local pattern_text = Cs((P("%")/"\\percent " + (P("^")/"\\high") * Cc("{") * lpegpatterns.integer * Cc("}") + P(1))^0)
+local pattern_math = Cs((P("%")/"\\percent " + P("^") * Cc("{") * lpegpatterns.integer * Cc("}") + anything)^0)
+local pattern_text = Cs((P("%")/"\\percent " + (P("^")/"\\high") * Cc("{") * lpegpatterns.integer * Cc("}") + anything)^0)
patterns.unittotex = pattern
@@ -551,7 +551,7 @@ function parsers.unittotex(str,textmode)
return lpegmatch(textmode and pattern_text or pattern_math,str)
end
-local pattern = Cs((P("^") / "<sup>" * lpegpatterns.integer * Cc("</sup>") + P(1))^0)
+local pattern = Cs((P("^") / "<sup>" * lpegpatterns.integer * Cc("</sup>") + anything)^0)
function parsers.unittoxml(str)
return lpegmatch(pattern,str)
@@ -648,3 +648,27 @@ function utilities.parsers.runtime(time)
local seconds = mod(time,60)
return days, hours, minutes, seconds
end
+
+--
+
+local spacing = whitespace^0
+local apply = P("->")
+local method = C((1-apply)^1)
+local token = lbrace * C((1-rbrace)^1) * rbrace + C(anything^1)
+
+local pattern = spacing * (method * spacing * apply + Carg(1)) * spacing * token
+
+function utilities.parsers.splitmethod(str,default)
+ if str then
+ return lpegmatch(pattern,str,1,default or false)
+ else
+ return default or false, ""
+ end
+end
+
+-- print(utilities.parsers.splitmethod(" foo -> {bar} "))
+-- print(utilities.parsers.splitmethod("foo->{bar}"))
+-- print(utilities.parsers.splitmethod("foo->bar"))
+-- print(utilities.parsers.splitmethod("foo"))
+-- print(utilities.parsers.splitmethod("{foo}"))
+-- print(utilities.parsers.splitmethod())
diff --git a/lualibs-util-str.lua b/lualibs-util-str.lua
index 6f95254..2739a20 100644
--- a/lualibs-util-str.lua
+++ b/lualibs-util-str.lua
@@ -216,6 +216,7 @@ local striplinepatterns = {
["retain"] = p_retain_normal,
["retain and collapse"] = p_retain_collapse,
["retain and no empty"] = p_retain_noempty,
+ ["collapse"] = patterns.collapser, -- how about: stripper fullstripper
}
strings.striplinepatterns = striplinepatterns
@@ -224,6 +225,8 @@ function strings.striplines(str,how)
return str and lpegmatch(how and striplinepatterns[how] or p_prune_collapse,str) or str
end
+-- also see: string.collapsespaces
+
strings.striplong = strings.striplines -- for old times sake
-- local str = table.concat( {
@@ -534,7 +537,7 @@ end
-- We could probably use just %s with integers but who knows what Lua 5.3 will do? So let's
-- for the moment use %i.
-local format_F = function()
+local format_F = function() -- beware, no cast to number
n = n + 1
if not f or f == "" then
return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
@@ -1091,3 +1094,23 @@ end
-- string.formatteds = formatteds
--
-- setmetatable(formatteds, { __index = make, __call = use })
+
+-- This is a somewhat silly one used in commandline reconstruction but the older
+-- method, using a combination of fine, gsub, quoted and unquoted was not that
+-- reliable.
+--
+-- '"foo"bar \"and " whatever"' => "foo\"bar \"and \" whatever"
+-- 'foo"bar \"and " whatever' => "foo\"bar \"and \" whatever"
+
+local dquote = patterns.dquote -- P('"')
+local equote = patterns.escaped + dquote / '\\"' + 1
+local space = patterns.space
+local cquote = Cc('"')
+
+local pattern =
+ Cs(dquote * (equote - P(-2))^0 * dquote) -- we keep the outer but escape unescaped ones
+ + Cs(cquote * (equote - space)^0 * space * equote^0 * cquote) -- we escape unescaped ones
+
+function string.optionalquoted(str)
+ return lpegmatch(pattern,str) or str
+end