summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/mlib-lua.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/mlib-lua.lua')
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua1175
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