diff options
Diffstat (limited to 'tex/context/base/mkiv/mlib-lua.lua')
-rw-r--r-- | tex/context/base/mkiv/mlib-lua.lua | 1175 |
1 files changed, 744 insertions, 431 deletions
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua index 19e731b85..d7c2a0fc3 100644 --- a/tex/context/base/mkiv/mlib-lua.lua +++ b/tex/context/base/mkiv/mlib-lua.lua @@ -10,11 +10,11 @@ if not modules then modules = { } end modules ['mlib-lua'] = { -- maybe we need mplib.model, but how with instances -local type, tostring, select, loadstring = type, tostring, select, loadstring +local type, tostring, tonumber, select, loadstring = type, tostring, tonumber, select, loadstring local find, match, gsub, gmatch = string.find, string.match, string.gsub, string.gmatch +local concat, insert, remove = table.concat, table.insert, table.remove local formatters = string.formatters -local concat = table.concat local lpegmatch = lpeg.match local lpegpatterns = lpeg.patterns @@ -26,105 +26,18 @@ local report_message = logs.reporter("metapost") local trace_luarun = false trackers.register("metapost.lua",function(v) trace_luarun = v end) local trace_enabled = true -local be_tolerant = true directives.register("metapost.lua.tolerant",function(v) be_tolerant = v end) +local be_tolerant = true directives.register("metapost.lua.tolerant", function(v) be_tolerant = v end) -mp = mp or { } -- system namespace -MP = MP or { } -- user namespace +local get, set, aux = { }, { }, { } -local buffer, n, max = { }, 0, 10 -- we reuse upto max - -function mp._f_() - if trace_enabled and trace_luarun then - local result = concat(buffer," ",1,n) - if n > max then - buffer = { } - end - n = 0 - report_luarun("data: %s",result) - return result - else - if n == 0 then - return "" - end - local result - if n == 1 then - result = buffer[1] - else - result = concat(buffer," ",1,n) - end - if n > max then - buffer = { } - end - n = 0 - return result - end -end - -local f_code = formatters["%s return mp._f_()"] - -local f_numeric = formatters["%.16f"] -local f_integer = formatters["%i"] -local f_pair = formatters["(%.16f,%.16f)"] -local f_triplet = formatters["(%.16f,%.16f,%.16f)"] -local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"] - -local function mpprint(...) -- we can optimize for n=1 - for i=1,select("#",...) do - local value = select(i,...) - if value ~= nil then - n = n + 1 - local t = type(value) - if t == "number" then - buffer[n] = f_numeric(value) - elseif t == "string" then - buffer[n] = value - elseif t == "table" then - buffer[n] = "(" .. concat(value,",") .. ")" - else -- boolean or whatever - buffer[n] = tostring(value) - end - end - end -end - -local r = P('%') / "percent" - + P('"') / "dquote" - + P('\n') / "crlf" - -- + P(' ') / "space" -local a = Cc("&") -local q = Cc('"') -local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q) - -local function mpvprint(...) -- variable print - for i=1,select("#",...) do - local value = select(i,...) - if value ~= nil then - n = n + 1 - local t = type(value) - if t == "number" then - buffer[n] = f_numeric(value) - elseif t == "string" then - buffer[n] = lpegmatch(p,value) - elseif t == "table" then - local m = #t - if m == 2 then - buffer[n] = f_pair(unpack(t)) - elseif m == 3 then - buffer[n] = f_triplet(unpack(t)) - elseif m == 4 then - buffer[n] = f_quadruple(unpack(t)) - else -- error - buffer[n] = "" - end - else -- boolean or whatever - buffer[n] = tostring(value) - end - end - end -end +mp = mp or { -- system namespace + set = set, + get = get, + aux = aux, +} -mp.print = mpprint -mp.vprint = mpvprint +MP = MP or { -- user namespace +} -- We had this: -- @@ -139,150 +52,540 @@ mp.vprint = mpvprint -- lua.mp("somedefdname","foo") table.setmetatablecall(mp,function(t,k,...) return t[k](...) end) +table.setmetatablecall(MP,function(t,k,...) return t[k](...) end) -function mp.boolean(b) - n = n + 1 - buffer[n] = b and "true" or "false" -end +do -function mp.numeric(f) - n = n + 1 - buffer[n] = f and f_numeric(f) or "0" -end + local currentmpx = nil + local stack = { } -function mp.integer(i) - n = n + 1 - -- buffer[n] = i and f_integer(i) or "0" - buffer[n] = i or "0" -end + local get_numeric = mplib.get_numeric + local get_string = mplib.get_string + local get_boolean = mplib.get_boolean + local get_path = mplib.get_path + local set_path = mplib.set_path + + get.numeric = function(s) return get_numeric(currentmpx,s) end + get.string = function(s) return get_string (currentmpx,s) end + get.boolean = function(s) return get_boolean(currentmpx,s) end + get.path = function(s) return get_path (currentmpx,s) end + get.number = function(s) return get_numeric(currentmpx,s) end -function mp.pair(x,y) - n = n + 1 - if type(x) == "table" then - buffer[n] = f_pair(x[1],x[2]) - else - buffer[n] = f_pair(x,y) + set.path = function(s,t) return set_path(currentmpx,s,t) end -- not working yet + + function metapost.pushscriptrunner(mpx) + insert(stack,mpx) + currentmpx = mpx end -end -function mp.triplet(x,y,z) - n = n + 1 - if type(x) == "table" then - buffer[n] = f_triplet(x[1],x[2],x[3]) - else - buffer[n] = f_triplet(x,y,z) + function metapost.popscriptrunner() + currentmpx = remove(stack,mpx) end + end -function mp.quadruple(w,x,y,z) - n = n + 1 - if type(w) == "table" then - buffer[n] = f_quadruple(w[1],w[2],w[3],w[4]) - else - buffer[n] = f_quadruple(w,x,y,z) +do + + local buffer = { } + local n = 0 + local max = 20 -- we reuse upto max + local nesting = 0 + local runs = 0 + + local function _f_() + if trace_enabled and trace_luarun then + local result = concat(buffer," ",1,n) + if n > max then + buffer = { } + end + n = 0 + report_luarun("%i: data: %s",nesting,result) + return result + else + if n == 0 then + return "" + end + local result + if n == 1 then + result = buffer[1] + else + result = concat(buffer," ",1,n) + end + if n > max then + buffer = { } + end + n = 0 + return result + end + end + + mp._f_ = _f_ -- convenient to have it in a top module + aux.flush = _f_ + + ----- f_code = formatters["%s return mp._f_()"] + + local f_integer = formatters["%i"] + + local f_numeric = formatters["%n"] -- maybe %N + local f_pair = formatters["(%n,%n)"] + local f_ctrl = formatters["(%n,%n) .. controls (%n,%n) and (%n,%n)"] + local f_triplet = formatters["(%n,%n,%n)"] + local f_quadruple = formatters["(%n,%n,%n,%n)"] + + local f_points = formatters["%p"] + local f_pair_pt = formatters["(%p,%p)"] + local f_ctrl_pt = formatters["(%p,%p) .. controls (%p,%p) and (%p,%p)"] + local f_triplet_pt = formatters["(%p,%p,%p)"] + local f_quadruple_pt = formatters["(%p,%p,%p,%p)"] + + local r = P('%') / "percent" + + P('"') / "dquote" + + P('\n') / "crlf" + -- + P(' ') / "space" + local a = Cc("&") + local q = Cc('"') + local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q) + + mp.cleaned = function(s) return lpegmatch(p,s) or s end + + -- local function mpprint(...) -- we can optimize for n=1 + -- for i=1,select("#",...) do + -- local value = (select(i,...)) + -- if value ~= nil then + -- n = n + 1 + -- local t = type(value) + -- if t == "number" then + -- buffer[n] = f_numeric(value) + -- elseif t == "string" then + -- buffer[n] = value + -- elseif t == "table" then + -- buffer[n] = "(" .. concat(value,",") .. ")" + -- else -- boolean or whatever + -- buffer[n] = tostring(value) + -- end + -- end + -- end + -- end + + local function mpp(value) + n = n + 1 + local t = type(value) + if t == "number" then + buffer[n] = f_numeric(value) + elseif t == "string" then + buffer[n] = value + elseif t == "table" then + buffer[n] = "(" .. concat(value,",") .. ")" + else -- boolean or whatever + buffer[n] = tostring(value) + end + end + + local function mpprint(first,second,...) + if second == nil then + if first ~= nil then + mpp(first) + end + else + for i=1,select("#",first,second,...) do + local value = (select(i,first,second,...)) + if value ~= nil then + mpp(value) + end + end + end end -end -function mp.path(t,connector,cycle) - if type(t) == "table" then - local tn = #t - if tn > 0 then - if connector == true then - connector = "--" - cycle = true - elseif not connector then - connector = "--" + local function mpp(value) + n = n + 1 + local t = type(value) + if t == "number" then + buffer[n] = f_numeric(value) + elseif t == "string" then + buffer[n] = lpegmatch(p,value) + elseif t == "table" then + if #t > 4 then + buffer[n] = "" + else + buffer[n] = "(" .. concat(value,",") .. ")" end - local ti = t[1] - n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2]) - for i=2,tn do - local ti = t[i] - n = n + 1 ; buffer[n] = connector - n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2]) + else -- boolean or whatever + buffer[n] = tostring(value) + end + end + + local function mpvprint(first,second,...) -- variable print + if second == nil then + if first ~= nil then + mpp(first) end - if cycle then - n = n + 1 ; buffer[n] = connector - n = n + 1 ; buffer[n] = "cycle" + else + for i=1,select("#",first,second,...) do + local value = (select(i,first,second,...)) + if value ~= nil then + mpp(value) + end end end end -end -function mp.size(t) - n = n + 1 - buffer[n] = type(t) == "table" and f_numeric(#t) or "0" -end + local function mpstring(value) + n = n + 1 + buffer[n] = lpegmatch(p,value) + end -local mpnamedcolor = attributes.colors.mpnamedcolor + local function mpboolean(b) + n = n + 1 + buffer[n] = b and "true" or "false" + end -mp.NamedColor = function(str) - mpprint(mpnamedcolor(str)) -end + local function mpnumeric(f) + n = n + 1 + if not f or f == 0 then + buffer[n] = "0" + else + buffer[n] = f_numeric(f) + end + end --- experiment: names can change + local function mpinteger(i) + n = n + 1 + -- buffer[n] = i and f_integer(i) or "0" + buffer[n] = i or "0" + end -local datasets = { } -mp.datasets = datasets + local function mppoints(i) + n = n + 1 + if not i or i == 0 then + buffer[n] = "0pt" + else + buffer[n] = f_points(i) + end + end -function datasets.load(tag,filename) - if not filename then - tag, filename = file.basename(tag), tag + local function mppair(x,y) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_pair(x[1],x[2]) + else + buffer[n] = f_pair(x,y) + end end - local data = mp.dataset(io.loaddata(filename) or "") - datasets[tag] = { - Data = data, - Line = function(n) mp.path(data[n or 1]) end, - Size = function() mp.size(data) end, - } -end --- + local function mppairpoints(x,y) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_pair_pt(x[1],x[2]) + else + buffer[n] = f_pair_pt(x,y) + end + end + + local function mptriplet(x,y,z) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_triplet(x[1],x[2],x[3]) + else + buffer[n] = f_triplet(x,y,z) + end + end -local replacer = lpeg.replacer("@","%%") + local function mptripletpoints(x,y,z) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_triplet_pt(x[1],x[2],x[3]) + else + buffer[n] = f_triplet_pt(x,y,z) + end + end -function mp.fprint(fmt,...) - n = n + 1 - if not find(fmt,"%",1,true) then - fmt = lpegmatch(replacer,fmt) + local function mpquadruple(w,x,y,z) + n = n + 1 + if type(w) == "table" then + buffer[n] = f_quadruple(w[1],w[2],w[3],w[4]) + else + buffer[n] = f_quadruple(w,x,y,z) + end end - buffer[n] = formatters[fmt](...) -end -local function mpquoted(fmt,s,...) - n = n + 1 - if s then + local function mpquadruplepoints(w,x,y,z) + n = n + 1 + if type(w) == "table" then + buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4]) + else + buffer[n] = f_quadruple_pt(w,x,y,z) + end + end + + -- we have three kind of connectors: + -- + -- .. ... -- (true) + + local function mp_path(f2,f6,t,connector,cycle) + if type(t) == "table" then + local tn = #t + if tn == 1 then + local t1 = t[1] + n = n + 1 ; buffer[n] = f2(t1[1],t1[2]) + elseif tn > 0 then + if connector == true or connector == nil then + connector = ".." + elseif connector == false then + connector = "--" + end + if cycle == nil then + cycle = t.cycle + if cycle == nil then + cycle = true + end + end + local six = connector == ".." -- otherwise we use whatever gets asked for + local controls = connector -- whatever + local a = t[1] + local b = t[2] + n = n + 1 + if six and #a == 6 and #b == 6 then + buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4]) + controls = ".." + else + buffer[n] = f2(a[1],a[2]) + controls = connector + end + for i=2,tn-1 do + a = b + b = t[i+1] + n = n + 1 + buffer[n] = connector + n = n + 1 + if six and #a == 6 and #b == 6 then + buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4]) + controls = ".." + else + buffer[n] = f2(a[1],a[2]) + controls = connector + end + end + n = n + 1 + buffer[n] = connector + a = b + b = t[1] + n = n + 1 + if cycle then + if six and #a == 6 and #b == 6 then + buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4]) + controls = ".." + else + buffer[n] = f2(a[1],a[2]) + controls = connector + end + n = n + 1 + buffer[n] = connector + n = n + 1 + buffer[n] = "cycle" + else + buffer[n] = f2(a[1],a[2]) + end + end + end + end + + local function mppath(...) + mp_path(f_pair,f_ctrl,...) + end + + local function mppathpoints(...) + mp_path(f_pair_pt,f_ctrl_pt,...) + end + + local function mpsize(t) + n = n + 1 + buffer[n] = type(t) == "table" and f_numeric(#t) or "0" + end + + local replacer = lpeg.replacer("@","%%") + + local function mpfprint(fmt,...) + n = n + 1 if not find(fmt,"%",1,true) then fmt = lpegmatch(replacer,fmt) end - -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"' - buffer[n] = lpegmatch(p,formatters[fmt](s,...)) - elseif fmt then - -- buffer[n] = '"' .. fmt .. '"' - buffer[n] = lpegmatch(p,fmt) - else - -- something is wrong + buffer[n] = formatters[fmt](...) end + + local function mpquoted(fmt,s,...) + if s then + n = n + 1 + if not find(fmt,"%",1,true) then + fmt = lpegmatch(replacer,fmt) + end + -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"' + buffer[n] = lpegmatch(p,formatters[fmt](s,...)) + elseif fmt then + n = n + 1 + -- buffer[n] = '"' .. fmt .. '"' + buffer[n] = lpegmatch(p,fmt) + else + -- something is wrong + end + end + + aux.print = mpprint + aux.vprint = mpvprint + aux.boolean = mpboolean + aux.string = mpstring + aux.numeric = mpnumeric + aux.number = mpnumeric + aux.integer = mpinteger + aux.points = mppoints + aux.pair = mppair + aux.pairpoints = mppairpoints + aux.triplet = mptriplet + aux.tripletpoints = mptripletpoints + aux.quadruple = mpquadruple + aux.quadruplepoints = mpquadruplepoints + aux.path = mppath + aux.pathpoints = mppathpoints + aux.size = mpsize + aux.fprint = mpfprint + aux.quoted = mpquoted + + -- we need access to the variables + + function metapost.nofscriptruns() + return runs + end + + -- sometimes we gain (e.g. .5 sec on the sync test) + + local cache = table.makeweak() + + function metapost.runscript(code) + nesting = nesting + 1 + local trace = trace_enabled and trace_luarun + if trace then + report_luarun("%i: code: %s",nesting,code) + end + runs = runs + 1 + local f = cache[code] + if not f then + f = loadstring(code .. " return mp._f_()") + if f then + cache[code] = f + elseif be_tolerant then + f = loadstring(code) + if f then + cache[code] = f + end + end + end + if f then + local _buffer_ = buffer + local _n_ = n + buffer = { } + n = 0 + local result = f() + if result then + local t = type(result) + if t == "number" then + result = f_numeric(result) + elseif t ~= "string" then + result = tostring(result) + end + if trace then + if #result == 0 then + report_luarun("%i: no result",nesting) + else + report_luarun("%i: result: %s",nesting,result) + end + end + buffer = _buffer_ + n = _n_ + nesting = nesting - 1 + return result + elseif trace then + report_luarun("%i: no result",nesting) + end + buffer, n = _buffer_, _n_ + else + report_luarun("%i: no result, invalid code: %s",nesting,code) + end + nesting = nesting - 1 + return "" + end + + -- for the moment + + for k, v in next, aux do mp[k] = v end + end -mp.quoted = mpquoted +do + + local mpnamedcolor = attributes.colors.mpnamedcolor + local mpprint = aux.print -function mp.n(t) + mp.mf_named_color = function(str) + mpprint(mpnamedcolor(str)) + end + +end + +function mp.n(t) -- used ? return type(t) == "table" and #t or 0 end -local whitespace = lpegpatterns.whitespace -local newline = lpegpatterns.newline -local setsep = newline^2 -local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0 -local value = (1-whitespace)^1 / tonumber -local entry = Ct( value * whitespace * value) -local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1) -local series = Ct((set * whitespace^0)^1) +do + + -- experiment: names can change + + local mppath = aux.path + local mpsize = aux.size + + local whitespace = lpegpatterns.whitespace + local newline = lpegpatterns.newline + local setsep = newline^2 + local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0 + local value = (1-whitespace)^1 / tonumber + local entry = Ct( value * whitespace * value) + local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1) + local series = Ct((set * whitespace^0)^1) + + local pattern = whitespace^0 * series -local pattern = whitespace^0 * series + local datasets = { } + mp.datasets = datasets + + function mp.dataset(str) + return lpegmatch(pattern,str) + end + + function datasets.load(tag,filename) + if not filename then + tag, filename = file.basename(tag), tag + end + local data = lpegmatch(pattern,io.loaddata(filename) or "") + datasets[tag] = { + data = data, + line = function(n) mppath(data[n or 1]) end, + size = function() mpsize(data) end, + } + end + + table.setmetatablecall(datasets,function(t,k,f,...) + local d = datasets[k] + local t = type(d) + if t == "table" then + d = d[f] + if type(d) == "function" then + d(...) + else + mpvprint(...) + end + elseif t == "function" then + d(f,...) + end + end) -function mp.dataset(str) - return lpegmatch(pattern,str) end -- \startluacode @@ -314,255 +617,157 @@ end -- endfor ; -- \stopMPpage -local cache, n = { }, 0 -- todo: when > n then reset cache or make weak - -function metapost.runscript(code) - local trace = trace_enabled and trace_luarun - if trace then - report_luarun("code: %s",code) - end - local f - if n > 100 then - cache = nil -- forget about caching - f = loadstring(f_code(code)) - if not f and be_tolerant then - f = loadstring(code) - end - else - f = cache[code] - if not f then - f = loadstring(f_code(code)) - if f then - n = n + 1 - cache[code] = f - elseif be_tolerant then - f = loadstring(code) - if f then - n = n + 1 - cache[code] = f - end - end - end - end - if f then - local result = f() - if result then - local t = type(result) - if t == "number" then - result = f_numeric(result) - elseif t ~= "string" then - result = tostring(result) - end - if trace then - report_luarun("result: %s",result) - end - return result - elseif trace then - report_luarun("no result") - end - else - report_luarun("no result, invalid code: %s",code) - end - return "" -end - --- function metapost.initializescriptrunner(mpx) --- mp.numeric = function(s) return mpx:get_numeric(s) end --- mp.string = function(s) return mpx:get_string (s) end --- mp.boolean = function(s) return mpx:get_boolean(s) end --- mp.number = mp.numeric --- end - -local get_numeric = mplib.get_numeric -local get_string = mplib.get_string -local get_boolean = mplib.get_boolean -local get_number = get_numeric - --- function metapost.initializescriptrunner(mpx) --- mp.numeric = function(s) return get_numeric(mpx,s) end --- mp.string = function(s) return get_string (mpx,s) end --- mp.boolean = function(s) return get_boolean(mpx,s) end --- mp.number = mp.numeric --- end - -local currentmpx = nil - -local get = { } -mp.get = get - -get.numeric = function(s) return get_numeric(currentmpx,s) end -get.string = function(s) return get_string (currentmpx,s) end -get.boolean = function(s) return get_boolean(currentmpx,s) end -get.number = mp.numeric - -function metapost.initializescriptrunner(mpx,trialrun) - currentmpx = mpx - if trace_luarun then - report_luarun("type of run: %s", trialrun and "trial" or "final") - end - -- trace_enabled = not trialrun blocks too much -end - -- texts: -local factor = 65536*(7227/7200) -local textexts = nil -local mptriplet = mp.triplet -local nbdimensions = nodes.boxes.dimensions - -function mp.tt_initialize(tt) - textexts = tt -end +do --- function mp.tt_wd(n) --- local box = textexts and textexts[n] --- mpprint(box and box.width/factor or 0) --- end --- function mp.tt_ht(n) --- local box = textexts and textexts[n] --- mpprint(box and box.height/factor or 0) --- end --- function mp.tt_dp(n) --- local box = textexts and textexts[n] --- mpprint(box and box.depth/factor or 0) --- end - -function mp.tt_dimensions(n) - local box = textexts and textexts[n] - if box then - -- could be made faster with nuts but not critical - mptriplet(box.width/factor,box.height/factor,box.depth/factor) - else - mptriplet(0,0,0) - end -end + local mptriplet = mp.triplet -function mp.tb_dimensions(category,name) - local w, h, d = nbdimensions(category,name) - mptriplet(w/factor,h/factor,d/factor) -end + local bpfactor = number.dimenfactors.bp + local textexts = nil + local mptriplet = mp.triplet + local nbdimensions = nodes.boxes.dimensions -function mp.report(a,b) - if b then - report_message("%s : %s",a,b) - elseif a then - report_message("%s : %s","message",a) + function mp.mf_tt_initialize(tt) + textexts = tt end -end --- + function mp.mf_tt_dimensions(n) + local box = textexts and textexts[n] + if box then + -- could be made faster with nuts but not critical + mptriplet(box.width*bpfactor,box.height*bpfactor,box.depth*bpfactor) + else + mptriplet(0,0,0) + end + end -local hashes = { } + function mp.mf_tb_dimensions(category,name) + local w, h, d = nbdimensions(category,name) + mptriplet(w*bpfactor,h*bpfactor,d*bpfactor) + end -function mp.newhash() - for i=1,#hashes+1 do - if not hashes[i] then - hashes[i] = { } - mpprint(i) - return + function mp.report(a,b,c,...) + if c then + report_message("%s : %s",a,formatters[(gsub(b,"@","%%"))](c,...)) + elseif b then + report_message("%s : %s",a,b) + elseif a then + report_message("%s : %s","message",a) end end -end -function mp.disposehash(n) - hashes[n] = nil end -function mp.inhash(n,key) - local h = hashes[n] - mpprint(h and h[key] and true or false) -end +do + + local mpprint = aux.print + local modes = tex.modes + local systemmodes = tex.systemmodes -function mp.tohash(n,key) - local h = hashes[n] - if h then - h[key] = true + function mp.mode(s) + mpprint(modes[s] and true or false) end -end -local modes = tex.modes -local systemmodes = tex.systemmodes + function mp.systemmode(s) + mpprint(systemmodes[s] and true or false) + end -function mp.mode(s) - mpprint(modes[s] and true or false) -end + mp.processingmode = mp.mode -function mp.systemmode(s) - mpprint(systemmodes[s] and true or false) end -- for alan's nodes: -function mp.isarray(str) - mpprint(find(str,"%d") and true or false) -end +do + + local mpprint = aux.print + local mpquoted = aux.quoted + + function mp.isarray(str) + mpprint(find(str,"%d") and true or false) + end + + function mp.prefix(str) + mpquoted(match(str,"^(.-)[%d%[]") or str) + end + + -- function mp.dimension(str) + -- local n = 0 + -- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg + -- n = n + 1 + -- end + -- mpprint(n) + -- end + + mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint) + + -- faster and okay as we don't have many variables but probably only + -- basename makes sense and even then it's not called that often + + -- local hash = table.setmetatableindex(function(t,k) + -- local v = find(k,"%d") and true or false + -- t[k] = v + -- return v + -- end) + -- + -- function mp.isarray(str) + -- mpprint(hash[str]) + -- end + -- + -- local hash = table.setmetatableindex(function(t,k) + -- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"' + -- t[k] = v + -- return v + -- end) + -- + -- function mp.prefix(str) + -- mpprint(hash[str]) + -- end -function mp.prefix(str) - mpquoted(match(str,"^(.-)[%d%[]") or str) end --- function mp.dimension(str) --- local n = 0 --- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg --- n = n + 1 --- end --- mpprint(n) --- end +do -mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint) + local getmacro = tex.getmacro + local getdimen = tex.getdimen + local getcount = tex.getcount + local gettoks = tex.gettoks + local setmacro = tex.setmacro + local setdimen = tex.setdimen + local setcount = tex.setcount + local settoks = tex.settoks --- faster and okay as we don't have many variables but probably only --- basename makes sense and even then it's not called that often + local mpprint = mp.print + local mpquoted = mp.quoted --- local hash = table.setmetatableindex(function(t,k) --- local v = find(k,"%d") and true or false --- t[k] = v --- return v --- end) --- --- function mp.isarray(str) --- mpprint(hash[str]) --- end --- --- local hash = table.setmetatableindex(function(t,k) --- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"' --- t[k] = v --- return v --- end) --- --- function mp.prefix(str) --- mpprint(hash[str]) --- end + local bpfactor = number.dimenfactors.bp -local getdimen = tex.getdimen -local getcount = tex.getcount -local gettoks = tex.gettoks -local setdimen = tex.setdimen -local setcount = tex.setcount -local settoks = tex.settoks + -- more helpers -local mpprint = mp.print -local mpquoted = mp.quoted + local function getmacro(k) mpprint (getmacro(k)) end + local function getdimen(k) mpprint (getdimen(k)*bpfactor) end + local function getcount(k) mpprint (getcount(k)) end + local function gettoks (k) mpquoted(gettoks (k)) end -local factor = number.dimenfactors.bp + local function setmacro(k,v) setmacro(k,v) end + local function setdimen(k,v) setdimen(k,v/bpfactor) end + local function setcount(k,v) setcount(k,v) end + local function settoks (k,v) settoks (k,v) end --- more helpers + -- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix -function mp.getdimen(k) mpprint (getdimen(k)*factor) end -function mp.getcount(k) mpprint (getcount(k)) end -function mp.gettoks (k) mpquoted(gettoks (k)) end -function mp.setdimen(k,v) setdimen(k,v/factor) end -function mp.setcount(k,v) setcount(k,v) end -function mp.settoks (k,v) settoks (k,v) end + mp._get_macro_ = getmacro mp.getmacro = getmacro + mp._get_dimen_ = getdimen mp.getdimen = getdimen + mp._get_count_ = getcount mp.getcount = getcount + mp._get_toks_ = gettoks mp.gettoks = gettoks --- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix + mp._set_macro_ = setmacro mp.setmacro = setmacro + mp._set_dimen_ = setdimen mp.setdimen = setdimen + mp._set_count_ = setcount mp.setcount = setcount + mp._set_toks_ = settoks mp.settoks = settoks -mp._get_dimen_ = mp.getdimen -mp._get_count_ = mp.getcount -mp._get_toks_ = mp.gettoks -mp._set_dimen_ = mp.setdimen -mp._set_count_ = mp.setcount -mp._set_toks_ = mp.settoks +end -- position fun @@ -658,6 +863,21 @@ end do + local mppair = mp.pair + + function mp.textextanchor(s) + local x, y = match(s,"tx_anchor=(%S+) (%S+)") -- todo: make an lpeg + if x and y then + x = tonumber(x) + y = tonumber(y) + end + mppair(x or 0,y or 0) + end + +end + +do + local mprint = mp.print local qprint = mp.quoted local getmacro = tokens.getters.macro @@ -674,31 +894,65 @@ end do - local mpvprint = mp.vprint + local mpprint = aux.print + local mpvprint = aux.vprint - local stores = { } + local hashes = { } - function mp.newstore(name) - stores[name] = { } + function mp.newhash(name) + if name then + hashes[name] = { } + else + for i=1,#hashes+1 do + if not hashes[i] then + hashes[i] = { } + mpvprint(i) + return + end + end + end end - function mp.disposestore(name) - stores[name] = nil + function mp.disposehash(n) + if tonumber(n) then + hashes[n] = false + else + hashes[n] = nil + end end - function mp.tostore(name,key,value) - stores[name][key] = value + function mp.inhash(n,key) + local h = hashes[n] + mpvprint(h and h[key] and true or false) end - function mp.fromstore(name,key) - mpvprint(stores[name][key]) -- type specific + function mp.tohash(n,key,value) + local h = hashes[n] + if h then + if value == nil then + h[key] = true + else + h[key] = value + end + end + end + + function mp.fromhash(n,key) + local h = hashes[n] + mpvprint(h and h[key] or false) end interfaces.implement { - name = "getMPstored", + name = "MPfromhash", arguments = "2 strings", actions = function(name,key) - context(stores[name][key]) + local h = hashes[name] or hashes[tonumber(name)] + if h then + local v = h[key] or h[tonumber(key)] + if v then + context(v) + end + end end } @@ -706,11 +960,70 @@ end do - local mpprint = mp.print - local texmodes = tex.modes + -- a bit overkill: just a find(str,"mf_object=") can be enough - function mp.processingmode(s) - mpprint(tostring(texmodes[s])) + local mpboolean = aux.boolean + + local p1 = P("mf_object=") + local p2 = lpegpatterns.eol * p1 + local pattern = (1-p2)^0 * p2 + p1 + + function mp.isobject(str) + mpboolean(pattern and str ~= "" and lpegmatch(pattern,str)) end end + +do + + local mpnumeric = aux.numeric + local mppair = aux.pair + local mpgetpath = get.path + + local p = nil + local n = 0 + + local function mf_path_length(name) + p = mpgetpath(name) + n = p and #p or 0 + mpnumeric(n) + end + + local function mf_path_point(i) + if i > 0 and i <= n then + local pi = p[i] + mppair(pi[1],pi[2]) + end + end + + local function mf_path_left(i) + if i > 0 and i <= n then + local pi = p[i] + mppair(pi[5],pi[6]) + end + end + + local function mf_path_right(i) + if i > 0 and i <= n then + local pn + if i == 1 then + pn = p[2] or p[1] + else + pn = p[i+1] or p[1] + end + mppair(pn[3],pn[4]) + end + end + + local function mf_path_reset() + p = nil + n = 0 + end + + mp.mf_path_length = mf_path_length mp.pathlength = mf_path_length + mp.mf_path_point = mf_path_point mp.pathpoint = mf_path_point + mp.mf_path_left = mf_path_left mp.pathleft = mf_path_left + mp.mf_path_right = mf_path_right mp.pathright = mf_path_right + mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset + +end |