diff options
Diffstat (limited to 'tex/context/base/util-tpl.lua')
-rw-r--r-- | tex/context/base/util-tpl.lua | 92 |
1 files changed, 72 insertions, 20 deletions
diff --git a/tex/context/base/util-tpl.lua b/tex/context/base/util-tpl.lua index 31b2ae1f1..304c9c739 100644 --- a/tex/context/base/util-tpl.lua +++ b/tex/context/base/util-tpl.lua @@ -17,14 +17,14 @@ local trace_template = false trackers.register("templates.trace",function(v) t local report_template = logs.reporter("template") local tostring = tostring -local format = string.format +local format, sub = string.format, string.sub local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match -- todo: make installable template.new local replacer -local function replacekey(k,t,recursive) +local function replacekey(k,t,how,recursive) local v = t[k] if not v then if trace_template then @@ -37,7 +37,7 @@ local function replacekey(k,t,recursive) report_template("setting key %q to value %q",k,v) end if recursive then - return lpegmatch(replacer,v,1,t) + return lpegmatch(replacer,v,1,t,how,recursive) else return v end @@ -52,38 +52,87 @@ local sqlescape = lpeg.replacer { -- { "\t", "\\t" }, } +local sqlquotedescape = lpeg.Cs(lpeg.Cc("'") * sqlescape * lpeg.Cc("'")) + +-- escapeset : \0\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\"\\\127 +-- test string: [[1\0\31test23"\\]] .. string.char(19) .. "23" +-- +-- slow: +-- +-- local luaescape = lpeg.replacer { +-- { '"', [[\"]] }, +-- { '\\', [[\\]] }, +-- { R("\0\9") * #R("09"), function(s) return "\\00" .. byte(s) end }, +-- { R("\10\31") * #R("09"), function(s) return "\\0" .. byte(s) end }, +-- { R("\0\31") , function(s) return "\\" .. byte(s) end }, +-- } +-- +-- slightly faster: +-- +-- local luaescape = Cs (( +-- P('"' ) / [[\"]] + +-- P('\\') / [[\\]] + +-- Cc("\\00") * (R("\0\9") / byte) * #R("09") + +-- Cc("\\0") * (R("\10\31") / byte) * #R("09") + +-- Cc("\\") * (R("\0\31") / byte) + +-- P(1) +-- )^0) + local escapers = { lua = function(s) - return format("%q",s) + return sub(format("%q",s),2,-2) end, sql = function(s) return lpegmatch(sqlescape,s) end, } +local quotedescapers = { + lua = function(s) + return format("%q",s) + end, + sql = function(s) + return lpegmatch(sqlquotedescape,s) + end, +} + lpeg.patterns.sqlescape = sqlescape +lpeg.patterns.sqlescape = sqlquotedescape + +local luaescaper = escapers.lua +local quotedluaescaper = quotedescapers.lua local function replacekeyunquoted(s,t,how,recurse) -- ".. \" " - local escaper = how and escapers[how] or escapers.lua - return escaper(replacekey(s,t,recurse)) + local escaper = how and escapers[how] or luaescaper + return escaper(replacekey(s,t,how,recurse)) end -local single = P("%") -- test %test% test : resolves test -local double = P("%%") -- test 10%% test : %% becomes % -local lquoted = P("%[") -- test %[test]" test : resolves test with escaped "'s -local rquoted = P("]%") -- - -local escape = double / '%%' -local nosingle = single / '' -local nodouble = double / '' -local nolquoted = lquoted / '' -local norquoted = rquoted / '' +local function replacekeyquoted(s,t,how,recurse) -- ".. \" " + local escaper = how and quotedescapers[how] or quotedluaescaper + return escaper(replacekey(s,t,how,recurse)) +end -local key = nosingle * (C((1-nosingle)^1 * Carg(1) * Carg(2) * Carg(3))/replacekey) * nosingle -local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2) * Carg(3))/replacekeyunquoted) * norquoted +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 key = nosingle * ((C((1-nosingle )^1) * Carg(1) * Carg(2) * Carg(3)) / replacekey ) * nosingle +local quoted = nolquotedq * ((C((1-norquotedq)^1) * Carg(1) * Carg(2) * Carg(3)) / replacekeyquoted ) * norquotedq +local unquoted = nolquoted * ((C((1-norquoted )^1) * Carg(1) * Carg(2) * Carg(3)) / replacekeyunquoted) * norquoted local any = P(1) - replacer = Cs((unquoted + escape + key + any)^0) + replacer = Cs((unquoted + quoted + escape + key + any)^0) local function replace(str,mapping,how,recurse) if mapping and str then @@ -95,7 +144,10 @@ end -- print(replace("test '%[x]%' test",{ x = [[a 'x' a]] })) -- print(replace("test '%[x]%' test",{ x = true })) --- print(replace("test '%[x]%' test",{ x = [[a 'x' a]] },'sql')) +-- print(replace("test '%[x]%' test",{ x = [[a 'x' a]], y = "oeps" },'sql')) +-- print(replace("test '%[x]%' test",{ x = [[a '%y%' a]], y = "oeps" },'sql',true)) +-- print(replace([[test %[x]% test]],{ x = [[a "x" a]]})) +-- print(replace([[test %(x)% test]],{ x = [[a "x" a]]})) templates.replace = replace |