diff options
Diffstat (limited to 'scripts/context/lua/mtxrun.lua')
-rw-r--r-- | scripts/context/lua/mtxrun.lua | 406 |
1 files changed, 219 insertions, 187 deletions
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index aa78a553e..f08c0f812 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -176,7 +176,7 @@ end --~ split = lpeg.Ct(c*(p*c)^0) --~ splitters[separator] = split --~ end ---~ return lpeg.match(split,self) -- split:match(self) +--~ return split:match(self) --~ else --~ return { } --~ end @@ -429,6 +429,8 @@ if not versions then versions = { } end versions['l-lpeg'] = 1.001 --~ lpeg.whitespace = lpeg.S(' \r\n\f\t')^1 --~ lpeg.nonwhitespace = lpeg.P(1-lpeg.whitespace)^1 +local hash = { } + function lpeg.anywhere(pattern) --slightly adapted from website return lpeg.P { lpeg.P(pattern) + 1 * lpeg.V(1) } end @@ -444,6 +446,20 @@ function lpeg.splitter(pattern, action) end +local crlf = lpeg.P("\r\n") +local cr = lpeg.P("\r") +local lf = lpeg.P("\n") +local space = lpeg.S(" \t\f\v") +local newline = crlf + cr + lf +local spacing = space^0 * newline +local content = lpeg.Cs((1-spacing)^1) * spacing^-1 * (spacing * lpeg.Cc(""))^0 + +local capture = lpeg.Ct(content^0) + +function string:splitlines() + return capture:match(self) +end + -- filename : l-table.lua -- comment : split off from luat-lib @@ -517,15 +533,6 @@ function table.prepend(t, list) end end ---~ function table.merge(t, ...) ---~ for _, list in ipairs({...}) do ---~ for k,v in pairs(list) do ---~ t[k] = v ---~ end ---~ end ---~ return t ---~ end - function table.merge(t, ...) -- first one is target t = t or {} local lst = {...} @@ -537,16 +544,6 @@ function table.merge(t, ...) -- first one is target return t end ---~ function table.merged(...) ---~ local tmp = { } ---~ for _, list in ipairs({...}) do ---~ for k,v in pairs(list) do ---~ tmp[k] = v ---~ end ---~ end ---~ return tmp ---~ end - function table.merged(...) local tmp, lst = { }, {...} for i=1,#lst do @@ -557,15 +554,6 @@ function table.merged(...) return tmp end ---~ function table.imerge(t, ...) ---~ for _, list in ipairs({...}) do ---~ for _, v in ipairs(list) do ---~ t[#t+1] = v ---~ end ---~ end ---~ return t ---~ end - function table.imerge(t, ...) local lst = {...} for i=1,#lst do @@ -577,16 +565,6 @@ function table.imerge(t, ...) return t end ---~ function table.imerged(...) ---~ local tmp = { } ---~ for _, list in ipairs({...}) do ---~ for _,v in pairs(list) do ---~ tmp[#tmp+1] = v ---~ end ---~ end ---~ return tmp ---~ end - function table.imerged(...) local tmp, lst = { }, {...} for i=1,#lst do @@ -734,7 +712,6 @@ do end if n == #t then local tt = { } - -- for _,v in ipairs(t) do for i=1,#t do local v = t[i] local tv = type(v) @@ -789,7 +766,7 @@ do local inline = compact and table.serialize_inline local first, last = nil, 0 -- #root cannot be trusted here if compact then - for k,v in ipairs(root) do -- NOT: for k=1,#root do + for k,v in ipairs(root) do -- NOT: for k=1,#root do (why) if not first then first = k end last = last + 1 end @@ -971,7 +948,8 @@ end do local function flatten(t,f,complete) - for _,v in ipairs(t) do + for i=1,#t do + local v = t[i] if type(v) == "table" then if complete or type(v[1]) == "table" then flatten(v,f,complete) @@ -1437,7 +1415,7 @@ do local one = lpeg.C(1-lpeg.S(''))^1 function number.toset(n) - return lpeg.match(one,tostring(n)) + return one:match(tostring(n)) end end @@ -1839,17 +1817,53 @@ if lfs then do else path, rest = pattern:match("^([^/]*)/(.-)$") end - patt = rest:gsub("([%.%-%+])", "%%%1") + if rest then + patt = rest:gsub("([%.%-%+])", "%%%1") + end patt = patt:gsub("%*", "[^/]*") patt = patt:gsub("%?", "[^/]") patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*") if path == "" then path = "." end - -- print(pattern, path, patt) - recurse = patt:find("%.%*/") + recurse = patt:find("%.%*/") ~= nil glob_pattern(path,patt,recurse,action) return t end + local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V + + local pattern = Ct { + [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3), + [2] = C(((1-S("*?/"))^0 * P("/"))^0), + [3] = C(P(1)^0) + } + + local filter = Cs ( ( + P("**") / ".*" + + P("*") / "[^/]*" + + P("?") / "[^/]" + + P(".") / "%." + + P("+") / "%+" + + P("-") / "%-" + + P(1) + )^0 ) + + function glob(str) + local split = pattern:match(str) + if split then + local t = { } + local action = action or function(name) t[#t+1] = name end + local root, path, base = split[1], split[2], split[3] + local recurse = base:find("**") + local start = root .. path + local result = filter:match(start .. base) + -- print(str, start, result) + glob_pattern(start,result,recurse,action) + return t + else + return { } + end + end + dir.glob = glob --~ list = dir.glob("**/*.tif") @@ -2162,6 +2176,8 @@ xml.trace_lpath = false xml.trace_print = false xml.trace_remap = false +local format, concat = string.format, table.concat + -- todo: some things per xml file, liek namespace remapping --[[ldx-- @@ -2172,7 +2188,7 @@ find based solution where we loop over an array of patterns. Less code and much cleaner.</p> --ldx]]-- -xml.xmlns = { } +xml.xmlns = xml.xmlns or { } do @@ -2312,9 +2328,9 @@ do local toclose = remove(stack) top = stack[#stack] if #stack < 1 then - errorstr = string.format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "") + errorstr = format("nothing to close with %s %s", tag, xml.check_error(top,toclose) or "") elseif toclose.tg ~= tag then -- no namespace check - errorstr = string.format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "") + errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.check_error(top,toclose) or "") end dt = top.dt dt[#dt+1] = toclose @@ -2438,8 +2454,10 @@ do errorstr = "empty xml file" elseif not grammar:match(data) then errorstr = "invalid xml file" + else + errorstr = "" end - if errorstr then + if errorstr and errorstr ~= "" then result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={}, er = true } }, error = true } setmetatable(stack, mt) if xml.error_handler then xml.error_handler("load",errorstr) end @@ -2449,7 +2467,9 @@ do if not no_root then result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={} } setmetatable(result, mt) - for k,v in ipairs(result.dt) do + local rdt = result.dt + for k=1,#rdt do + local v = rdt[k] if type(v) == "table" and not v.special then -- always table -) result.ri = k -- rootindex break @@ -2560,138 +2580,141 @@ do local fallbackhandle = (tex and tex.sprint) or io.write - function xml.serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands) + local function serialize(e, handle, textconverter, attributeconverter, specialconverter, nocommands) if not e then - -- quit - elseif not nocommands and e.command and xml.command then - xml.command(e) - else - handle = handle or fallbackhandle - local etg = e.tg - if etg then - -- local format = string.format - if e.special then - local edt = e.dt - local spc = specialconverter and specialconverter[etg] - if spc then - local result = spc(edt[1]) - if result then - handle(result) - else - -- no need to handle any further + return + elseif not nocommands then + local ec = e.command + if ec then + local xc = xml.command + if xc then + xc(e,ec) + return + end + end + end + handle = handle or fallbackhandle + local etg = e.tg + if etg then + if e.special then + local edt = e.dt + local spc = specialconverter and specialconverter[etg] + if spc then + local result = spc(edt[1]) + if result then + handle(result) + else + -- no need to handle any further + end + elseif etg == "@pi@" then + -- handle(format("<?%s?>",edt[1])) + handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt) + elseif etg == "@cm@" then + -- handle(format("<!--%s-->",edt[1])) + handle("<!--" .. edt[1] .. "-->") + elseif etg == "@cd@" then + -- handle(format("<![CDATA[%s]]>",edt[1])) + handle("<![CDATA[" .. edt[1] .. "]]>") + elseif etg == "@dd@" then + -- handle(format("<!DOCTYPE %s>",edt[1])) + handle("<!DOCTYPE " .. edt[1] .. ">") + elseif etg == "@rt@" then + serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands) + end + else + local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn + local ats = eat and next(eat) and { } + if ats then + if attributeconverter then + for k,v in pairs(eat) do + ats[#ats+1] = format('%s=%q',k,attributeconverter(v)) + end + else + for k,v in pairs(eat) do + ats[#ats+1] = format('%s=%q',k,v) end - elseif etg == "@pi@" then - -- handle(format("<?%s?>",edt[1])) - handle("<?" .. edt[1] .. "?>") -- maybe table.join(edt) - elseif etg == "@cm@" then - -- handle(format("<!--%s-->",edt[1])) - handle("<!--" .. edt[1] .. "-->") - elseif etg == "@cd@" then - -- handle(format("<![CDATA[%s]]>",edt[1])) - handle("<![CDATA[" .. edt[1] .. "]]>") - elseif etg == "@dd@" then - -- handle(format("<!DOCTYPE %s>",edt[1])) - handle("<!DOCTYPE " .. edt[1] .. ">") - elseif etg == "@rt@" then - xml.serialize(edt,handle,textconverter,attributeconverter,specialconverter,nocommands) end - else - local ens, eat, edt, ern = e.ns, e.at, e.dt, e.rn - local ats = eat and next(eat) and { } + end + if ern and xml.trace_remap then if ats then - local format = string.format - if attributeconverter then - for k,v in pairs(eat) do - ats[#ats+1] = format('%s=%q',k,attributeconverter(v)) - end - else - for k,v in pairs(eat) do - ats[#ats+1] = format('%s=%q',k,v) - end - end + ats[#ats+1] = format("xmlns:remapped='%s'",ern) + else + ats = { format("xmlns:remapped='%s'",ern) } end - if ern and xml.trace_remap then + end + if ens ~= "" then + if edt and #edt > 0 then if ats then - ats[#ats+1] = string.format("xmlns:remapped='%s'",ern) + -- handle(format("<%s:%s %s>",ens,etg,concat(ats," "))) + handle("<" .. ens .. ":" .. etg .. " " .. concat(ats," ") .. ">") else - ats = { string.format("xmlns:remapped='%s'",ern) } + -- handle(format("<%s:%s>",ens,etg)) + handle("<" .. ens .. ":" .. etg .. ">") end - end - if ens ~= "" then - if edt and #edt > 0 then - if ats then - -- handle(format("<%s:%s %s>",ens,etg,table.concat(ats," "))) - handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. ">") - else - -- handle(format("<%s:%s>",ens,etg)) - handle("<" .. ens .. ":" .. etg .. ">") - end - local serialize = xml.serialize - for i=1,#edt do - local e = edt[i] - if type(e) == "string" then - if textconverter then - handle(textconverter(e)) - else - handle(e) - end + for i=1,#edt do + local e = edt[i] + if type(e) == "string" then + if textconverter then + handle(textconverter(e)) else - serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands) + handle(e) end - end - -- handle(format("</%s:%s>",ens,etg)) - handle("</" .. ens .. ":" .. etg .. ">") - else - if ats then - -- handle(format("<%s:%s %s/>",ens,etg,table.concat(ats," "))) - handle("<" .. ens .. ":" .. etg .. " " .. table.concat(ats," ") .. "/>") else - -- handle(format("<%s:%s/>",ens,etg)) - handle("<" .. ens .. ":" .. "/>") + serialize(e,handle,textconverter,attributeconverter,specialconverter,nocommands) end end + -- handle(format("</%s:%s>",ens,etg)) + handle("</" .. ens .. ":" .. etg .. ">") else - if edt and #edt > 0 then - if ats then - -- handle(format("<%s %s>",etg,table.concat(ats," "))) - handle("<" .. etg .. " " .. table.concat(ats," ") .. ">") - else - -- handle(format("<%s>",etg)) - handle("<" .. etg .. ">") - end - local serialize = xml.serialize - for i=1,#edt do - serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands) - end - -- handle(format("</%s>",etg)) - handle("</" .. etg .. ">") + if ats then + -- handle(format("<%s:%s %s/>",ens,etg,concat(ats," "))) + handle("<" .. ens .. ":" .. etg .. " " .. concat(ats," ") .. "/>") else - if ats then - -- handle(format("<%s %s/>",etg,table.concat(ats," "))) - handle("<" .. etg .. " " .. table.concat(ats," ") .. "/>") - else - -- handle(format("<%s/>",etg)) - handle("<" .. etg .. "/>") - end + -- handle(format("<%s:%s/>",ens,etg)) + handle("<" .. ens .. ":" .. "/>") end end - end - elseif type(e) == "string" then - if textconverter then - handle(textconverter(e)) else - handle(e) + if edt and #edt > 0 then + if ats then + -- handle(format("<%s %s>",etg,concat(ats," "))) + handle("<" .. etg .. " " .. concat(ats," ") .. ">") + else + -- handle(format("<%s>",etg)) + handle("<" .. etg .. ">") + end + for i=1,#edt do + serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands) + end + -- handle(format("</%s>",etg)) + handle("</" .. etg .. ">") + else + if ats then + -- handle(format("<%s %s/>",etg,concat(ats," "))) + handle("<" .. etg .. " " .. concat(ats," ") .. "/>") + else + -- handle(format("<%s/>",etg)) + handle("<" .. etg .. "/>") + end + end end + end + elseif type(e) == "string" then + if textconverter then + handle(textconverter(e)) else - local serialize = xml.serialize - for i=1,#e do - serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands) - end + handle(e) + end + else + for i=1,#e do + serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands) end end end - function xml.checkbom(root) + xml.serialize = serialize + + function xml.checkbom(root) -- can be made faster if root.ri then local dt, found = root.dt, false for k,v in ipairs(dt) do @@ -2707,24 +2730,24 @@ do end end -end - ---[[ldx-- -<p>At the cost of some 25% runtime overhead you can first convert the tree to a string -and then handle the lot.</p> ---ldx]]-- + --[[ldx-- + <p>At the cost of some 25% runtime overhead you can first convert the tree to a string + and then handle the lot.</p> + --ldx]]-- -function xml.tostring(root) -- 25% overhead due to collecting - if root then - if type(root) == 'string' then - return root - elseif next(root) then - local result = { } - xml.serialize(root,function(s) result[#result+1] = s end) - return table.concat(result,"") + function xml.tostring(root) -- 25% overhead due to collecting + if root then + if type(root) == 'string' then + return root + elseif next(root) then + local result = { } + serialize(root,function(s) result[#result+1] = s end) + return concat(result,"") + end end -end - return "" + return "" + end + end --[[ldx-- @@ -2852,14 +2875,14 @@ do [40] = "processing instruction", } - local function make_expression(str) + local function make_expression(str) --could also be an lpeg str = str:gsub("@([a-zA-Z%-_]+)", "(a['%1'] or '')") str = str:gsub("position%(%)", "i") str = str:gsub("text%(%)", "t") str = str:gsub("!=", "~=") str = str:gsub("([^=!~<>])=([^=!~<>])", "%1==%2") str = str:gsub("([a-zA-Z%-_]+)%(", "functions.%1(") - return str, loadstring(string.format("return function(functions,i,a,t) return %s end", str))() + return str, loadstring(format("return function(functions,i,a,t) return %s end", str))() end local map = { } @@ -2945,6 +2968,9 @@ do local expression = (is_one * is_expression)/ function(...) map[#map+1] = { 31, true, ... } end local dont_expression = (is_none * is_expression)/ function(...) map[#map+1] = { 31, false, ... } end + local self_expression = ( is_expression)/ function(...) map[#map+1] = { 31, true, "", "*", ... } end + local dont_self_expression = (exclam * is_expression)/ function(...) map[#map+1] = { 31, true, "", "*", ... } end + local instruction = (instructiontag * text ) / function(...) map[#map+1] = { 40, ... } end local nothing = (empty ) / function( ) map[#map+1] = { 15 } end -- 15 ? local crap = (1-slash)^1 @@ -2970,6 +2996,7 @@ do dont_match_and_eq + dont_match_and_ne + match_and_eq + match_and_ne + dont_expression + expression + +dont_self_expression + self_expression + has_attribute + has_value + dont_match_one_of + match_one_of + dont_match + match + @@ -2981,7 +3008,7 @@ do followup = ((slash + parenttag + childtag + selftag)^0 * selector)^1, } - function compose(str) + local function compose(str) if not str or str == "" then -- wildcard return true @@ -3003,7 +3030,7 @@ do -- root return false end - elseif #map == 2 and m == 12 and map[2][1] == 20 then + elseif #map == 2 and m == 12 and map[2][1] == 20 then -- return { { 29, map[2][2], map[2][3], map[2][4], map[2][5] } } map[2][1] = 29 return { map[2] } @@ -3011,6 +3038,7 @@ do if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then table.insert(map, 1, { 16 }) end + -- print((table.serialize(map)):gsub("[ \n]+"," ")) return map end end @@ -3045,7 +3073,7 @@ do report(" -: wildcard\n") else if type(pattern) == "string" then - report(string.format("pattern: %s\n",pattern)) + report(format("pattern: %s\n",pattern)) end for k,v in ipairs(lp) do if #v > 1 then @@ -3058,9 +3086,9 @@ do t[#t+1] = (vv and "==") or "<>" end end - report(string.format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," "))) + report(format("%2i: %s %s -> %s\n", k,v[1],actions[v[1]],table.join(t," "))) else - report(string.format("%2i: %s %s\n", k,v[1],actions[v[1]])) + report(format("%2i: %s %s\n", k,v[1],actions[v[1]])) end end end @@ -3181,7 +3209,7 @@ do start, stop, step = stop, start, -1 end local idx = 0 - for k=start,stop,step do + for k=start,stop,step do -- we used to have functions for all but a case is faster local e = rootdt[k] local ns, tg = e.rn or e.ns, e.tg if tg then @@ -3256,15 +3284,19 @@ do if tg == tg_a then matched = ns == action[3] elseif tg_a == '*' then matched, multiple = ns == action[3], true else matched = false end if not action[2] then matched = not matched end if matched then - matched = action[6](functions,idx,e.at,edt[1]) + matched = action[6](functions,idx,e.at or { },edt[1]) end end if matched then -- combine tg test and at test if index == #pattern then if handle(root,rootdt,root.ri or k) then return false end ---~ if wildcard and multiple then -if wildcard or multiple then - if not traverse(e,pattern,handle,reverse,index,root,true) then return false end + if wildcard then + if multiple then + if not traverse(e,pattern,handle,reverse,index,root,true) then return false end + else + -- maybe or multiple; anyhow, check on (section|title) vs just section and title in example in lxml + if not traverse(e,pattern,handle,reverse,index,root) then return false end + end end else if not traverse(e,pattern,handle,reverse,index+1,root) then return false end |