summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2012-09-10 02:00:22 +0300
committerMarius <mariausol@gmail.com>2012-09-10 02:00:22 +0300
commit40012d63f567ccc7ce33e0307069f35926fc5d6a (patch)
treeefdaaf9e16d0f3b562974629bf0ea3559258e72d
parent5b4c6dd791dfcb02838191ccee764cbb215b7cc4 (diff)
downloadcontext-40012d63f567ccc7ce33e0307069f35926fc5d6a.tar.gz
beta 2012.09.10 00:57
-rw-r--r--context/data/scite/scite-context.properties2
-rw-r--r--scripts/context/lua/mtx-context.lua6
-rw-r--r--scripts/context/lua/mtxrun.lua163
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua163
-rw-r--r--scripts/context/stubs/unix/mtxrun163
-rw-r--r--tex/context/base/cont-new.mkii2
-rw-r--r--tex/context/base/cont-new.mkiv2
-rw-r--r--tex/context/base/context-version.pdfbin4143 -> 4145 bytes
-rw-r--r--tex/context/base/context-version.pngbin105007 -> 106487 bytes
-rw-r--r--tex/context/base/context.mkii2
-rw-r--r--tex/context/base/context.mkiv4
-rw-r--r--tex/context/base/data-lua.lua35
-rw-r--r--tex/context/base/file-job.lua1
-rw-r--r--tex/context/base/l-string.lua8
-rw-r--r--tex/context/base/l-unicode.lua10
-rw-r--r--tex/context/base/luat-lib.mkiv1
-rw-r--r--tex/context/base/luat-mac.lua92
-rw-r--r--tex/context/base/lxml-lpt.lua4
-rw-r--r--tex/context/base/s-abr-01.tex3
-rw-r--r--tex/context/base/sort-lan.lua3
-rw-r--r--tex/context/base/status-files.pdfbin24587 -> 24586 bytes
-rw-r--r--tex/context/base/status-lua.pdfbin194861 -> 195007 bytes
-rw-r--r--tex/context/base/status-mkiv.lua7
-rw-r--r--tex/context/base/trac-deb.mkiv2
-rw-r--r--tex/context/base/trac-lmx.lua23
-rw-r--r--tex/context/base/util-sql.lua371
-rw-r--r--tex/context/base/util-tab.lua61
-rw-r--r--tex/context/base/util-tpl.lua45
-rw-r--r--tex/context/base/x-mathml.mkiv2425
-rw-r--r--tex/context/base/x-xfdf.mkiv71
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua10
31 files changed, 895 insertions, 2784 deletions
diff --git a/context/data/scite/scite-context.properties b/context/data/scite/scite-context.properties
index 03aaf383b..739967d3c 100644
--- a/context/data/scite/scite-context.properties
+++ b/context/data/scite/scite-context.properties
@@ -56,7 +56,7 @@ textwrapper.length=68
file.patterns.tex=
file.patterns.latex=
-file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;
+file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;*.mkix;*.mkxi;
open.suffix.$(file.patterns.context)=.tex
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index f164aadd4..4381840b2 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -1053,6 +1053,8 @@ function scripts.context.touch()
touchfiles("mkii")
touchfiles("mkiv")
touchfiles("mkvi")
+ touchfiles("mkix")
+ touchfiles("mkxi")
else
report("touching needs --expert")
end
@@ -1061,7 +1063,7 @@ end
-- modules
local labels = { "title", "comment", "status" }
-local cards = { "*.mkvi", "*.mkiv", "*.tex" }
+local cards = { "*.mkvi", "*.mkiv", "*.mkxi", "*.mkix", "*.tex" }
function scripts.context.modules(pattern)
local list = { }
@@ -1086,7 +1088,7 @@ function scripts.context.modules(pattern)
if not done[base] then
done[base] = true
local suffix = file.suffix(base)
- if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" then
+ if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then
local prefix = match(base,"^([xmst])%-")
if prefix then
v = resolvers.findfile(base) -- so that files on my dev path are seen
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index a299e3a2b..829c3f11d 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -169,6 +169,14 @@ string.unquote = string.unquoted
string.itself = function(s) return s end
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -4132,7 +4140,7 @@ if not modules then modules = { } end modules ['l-unicode'] = {
local concat = table.concat
local type = type
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local utftype = patterns.utftype
local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
@@ -4573,6 +4581,14 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+--
+
+local pattern = Ct(C(patterns.utf8char)^0)
+
+function utf.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -4788,14 +4804,6 @@ function tables.encapsulate(core,capsule,protect)
end
end
-local escaped = Cs ( (
- P('\\' ) +
- P('"' )/'\\"' +
- P('\n')/'\\n' +
- P('\r')/'\\r' +
- 1
-)^0 )
-
local function serialize(t,r,outer) -- no mixes
r[#r+1] = "{"
local n = #t
@@ -4837,7 +4845,19 @@ local function serialize(t,r,outer) -- no mixes
end
function table.fastserialize(t,prefix)
- return concat(serialize(t,{ prefix },true))
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
end
-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
@@ -4857,6 +4877,45 @@ function table.load(filename)
end
end
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
end -- of closure
@@ -9944,12 +10003,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -15763,7 +15822,10 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- on the developments (the loaders must not trigger kpse); we could
-- of course use a more extensive lib path spec
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
@@ -15772,7 +15834,8 @@ local unpack = unpack or table.unpack
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
+-- local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' }
+local libformats = { 'lua', 'tex' }
local clibformats = { 'lib' }
local _path_, libpaths, _cpath_, clibpaths
@@ -15796,7 +15859,7 @@ end
local function thepath(...)
local t = { ... } t[#t+1] = "?.lua"
local path = file.join(unpack(t))
- if trace_locating then
+ if trace_libraries then
report_libraries("! appending '%s' to 'package.path'",path)
end
return path
@@ -15818,11 +15881,11 @@ local function loaded(libpaths,name,simple)
for i=1,#libpaths do -- package.path, might become option
local libpath = libpaths[i]
local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
end
return loadfile(resolved)
@@ -15833,22 +15896,22 @@ end
package.loaders[2] = function(name) -- was [#package.loaders+1]
if file.suffix(name) == "" then
name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s' with forced suffix",name)
end
else
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s'",name)
end
end
for i=1,#libformats do
local format = libformats[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
end
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
end
return loadfile(resolved)
@@ -15871,11 +15934,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for p=1,#paths do
local path = paths[p]
local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
end
return package.loadlib(resolved,name)
@@ -15885,11 +15948,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for i=1,#clibpaths do -- package.path, might become option
local libpath = clibpaths[i]
local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
end
return package.loadlib(resolved,name)
@@ -15901,12 +15964,12 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
end
local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
return loadfile(resolved)
end
- if trace_locating then
+ if trace_libraries then
report_libraries('? unable to locate lib: %s',name)
end
-- return "unable to locate " .. name
@@ -15925,6 +15988,7 @@ package.obsolete.append_libpath = appendtolibpath -- will become obsolete
package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -16446,6 +16510,8 @@ local report_template = logs.reporter("template")
local format = string.format
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)
@@ -16459,40 +16525,59 @@ local function replacekey(k,t)
if trace_template then
report_template("setting key %q to value %q",k,v)
end
- -- return v
return lpegmatch(replacer,v,1,t) -- recursive
end
end
------ leftmarker = P("<!-- ") / ""
------ rightmarker = P(" --!>") / ""
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t))
+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 escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
local key = nosingle * (C((1-nosingle)^1 * Carg(1))/replacekey) * nosingle
-local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1))/function(s,t) return format("%q",replacekey(s,t)) end) * norquoted
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2))/replacekeyunquoted) * norquoted
local any = P(1)
replacer = Cs((unquoted + escape + key + any)^0)
-local function replace(str,mapping)
+local function replace(str,mapping,how)
if mapping then
- return lpegmatch(replacer,str,1,mapping) or str
+ return lpegmatch(replacer,str,1,mapping,how or "lua") or str
else
return str
end
end
--- print(replace("test %[x]% test",{ x = [[a "x" a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
templates.replace = replace
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index a299e3a2b..829c3f11d 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -169,6 +169,14 @@ string.unquote = string.unquoted
string.itself = function(s) return s end
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -4132,7 +4140,7 @@ if not modules then modules = { } end modules ['l-unicode'] = {
local concat = table.concat
local type = type
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local utftype = patterns.utftype
local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
@@ -4573,6 +4581,14 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+--
+
+local pattern = Ct(C(patterns.utf8char)^0)
+
+function utf.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -4788,14 +4804,6 @@ function tables.encapsulate(core,capsule,protect)
end
end
-local escaped = Cs ( (
- P('\\' ) +
- P('"' )/'\\"' +
- P('\n')/'\\n' +
- P('\r')/'\\r' +
- 1
-)^0 )
-
local function serialize(t,r,outer) -- no mixes
r[#r+1] = "{"
local n = #t
@@ -4837,7 +4845,19 @@ local function serialize(t,r,outer) -- no mixes
end
function table.fastserialize(t,prefix)
- return concat(serialize(t,{ prefix },true))
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
end
-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
@@ -4857,6 +4877,45 @@ function table.load(filename)
end
end
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
end -- of closure
@@ -9944,12 +10003,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -15763,7 +15822,10 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- on the developments (the loaders must not trigger kpse); we could
-- of course use a more extensive lib path spec
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
@@ -15772,7 +15834,8 @@ local unpack = unpack or table.unpack
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
+-- local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' }
+local libformats = { 'lua', 'tex' }
local clibformats = { 'lib' }
local _path_, libpaths, _cpath_, clibpaths
@@ -15796,7 +15859,7 @@ end
local function thepath(...)
local t = { ... } t[#t+1] = "?.lua"
local path = file.join(unpack(t))
- if trace_locating then
+ if trace_libraries then
report_libraries("! appending '%s' to 'package.path'",path)
end
return path
@@ -15818,11 +15881,11 @@ local function loaded(libpaths,name,simple)
for i=1,#libpaths do -- package.path, might become option
local libpath = libpaths[i]
local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
end
return loadfile(resolved)
@@ -15833,22 +15896,22 @@ end
package.loaders[2] = function(name) -- was [#package.loaders+1]
if file.suffix(name) == "" then
name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s' with forced suffix",name)
end
else
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s'",name)
end
end
for i=1,#libformats do
local format = libformats[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
end
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
end
return loadfile(resolved)
@@ -15871,11 +15934,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for p=1,#paths do
local path = paths[p]
local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
end
return package.loadlib(resolved,name)
@@ -15885,11 +15948,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for i=1,#clibpaths do -- package.path, might become option
local libpath = clibpaths[i]
local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
end
return package.loadlib(resolved,name)
@@ -15901,12 +15964,12 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
end
local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
return loadfile(resolved)
end
- if trace_locating then
+ if trace_libraries then
report_libraries('? unable to locate lib: %s',name)
end
-- return "unable to locate " .. name
@@ -15925,6 +15988,7 @@ package.obsolete.append_libpath = appendtolibpath -- will become obsolete
package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -16446,6 +16510,8 @@ local report_template = logs.reporter("template")
local format = string.format
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)
@@ -16459,40 +16525,59 @@ local function replacekey(k,t)
if trace_template then
report_template("setting key %q to value %q",k,v)
end
- -- return v
return lpegmatch(replacer,v,1,t) -- recursive
end
end
------ leftmarker = P("<!-- ") / ""
------ rightmarker = P(" --!>") / ""
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t))
+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 escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
local key = nosingle * (C((1-nosingle)^1 * Carg(1))/replacekey) * nosingle
-local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1))/function(s,t) return format("%q",replacekey(s,t)) end) * norquoted
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2))/replacekeyunquoted) * norquoted
local any = P(1)
replacer = Cs((unquoted + escape + key + any)^0)
-local function replace(str,mapping)
+local function replace(str,mapping,how)
if mapping then
- return lpegmatch(replacer,str,1,mapping) or str
+ return lpegmatch(replacer,str,1,mapping,how or "lua") or str
else
return str
end
end
--- print(replace("test %[x]% test",{ x = [[a "x" a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
templates.replace = replace
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index a299e3a2b..829c3f11d 100644
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -169,6 +169,14 @@ string.unquote = string.unquoted
string.itself = function(s) return s end
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -4132,7 +4140,7 @@ if not modules then modules = { } end modules ['l-unicode'] = {
local concat = table.concat
local type = type
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local utftype = patterns.utftype
local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
@@ -4573,6 +4581,14 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+--
+
+local pattern = Ct(C(patterns.utf8char)^0)
+
+function utf.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -4788,14 +4804,6 @@ function tables.encapsulate(core,capsule,protect)
end
end
-local escaped = Cs ( (
- P('\\' ) +
- P('"' )/'\\"' +
- P('\n')/'\\n' +
- P('\r')/'\\r' +
- 1
-)^0 )
-
local function serialize(t,r,outer) -- no mixes
r[#r+1] = "{"
local n = #t
@@ -4837,7 +4845,19 @@ local function serialize(t,r,outer) -- no mixes
end
function table.fastserialize(t,prefix)
- return concat(serialize(t,{ prefix },true))
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
end
-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
@@ -4857,6 +4877,45 @@ function table.load(filename)
end
end
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
end -- of closure
@@ -9944,12 +10003,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -15763,7 +15822,10 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- on the developments (the loaders must not trigger kpse); we could
-- of course use a more extensive lib path spec
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
@@ -15772,7 +15834,8 @@ local unpack = unpack or table.unpack
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
+-- local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' }
+local libformats = { 'lua', 'tex' }
local clibformats = { 'lib' }
local _path_, libpaths, _cpath_, clibpaths
@@ -15796,7 +15859,7 @@ end
local function thepath(...)
local t = { ... } t[#t+1] = "?.lua"
local path = file.join(unpack(t))
- if trace_locating then
+ if trace_libraries then
report_libraries("! appending '%s' to 'package.path'",path)
end
return path
@@ -15818,11 +15881,11 @@ local function loaded(libpaths,name,simple)
for i=1,#libpaths do -- package.path, might become option
local libpath = libpaths[i]
local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
end
return loadfile(resolved)
@@ -15833,22 +15896,22 @@ end
package.loaders[2] = function(name) -- was [#package.loaders+1]
if file.suffix(name) == "" then
name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s' with forced suffix",name)
end
else
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s'",name)
end
end
for i=1,#libformats do
local format = libformats[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
end
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
end
return loadfile(resolved)
@@ -15871,11 +15934,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for p=1,#paths do
local path = paths[p]
local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
end
return package.loadlib(resolved,name)
@@ -15885,11 +15948,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for i=1,#clibpaths do -- package.path, might become option
local libpath = clibpaths[i]
local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
end
return package.loadlib(resolved,name)
@@ -15901,12 +15964,12 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
end
local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
return loadfile(resolved)
end
- if trace_locating then
+ if trace_libraries then
report_libraries('? unable to locate lib: %s',name)
end
-- return "unable to locate " .. name
@@ -15925,6 +15988,7 @@ package.obsolete.append_libpath = appendtolibpath -- will become obsolete
package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -16446,6 +16510,8 @@ local report_template = logs.reporter("template")
local format = string.format
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)
@@ -16459,40 +16525,59 @@ local function replacekey(k,t)
if trace_template then
report_template("setting key %q to value %q",k,v)
end
- -- return v
return lpegmatch(replacer,v,1,t) -- recursive
end
end
------ leftmarker = P("<!-- ") / ""
------ rightmarker = P(" --!>") / ""
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t))
+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 escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
local key = nosingle * (C((1-nosingle)^1 * Carg(1))/replacekey) * nosingle
-local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1))/function(s,t) return format("%q",replacekey(s,t)) end) * norquoted
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2))/replacekeyunquoted) * norquoted
local any = P(1)
replacer = Cs((unquoted + escape + key + any)^0)
-local function replace(str,mapping)
+local function replace(str,mapping,how)
if mapping then
- return lpegmatch(replacer,str,1,mapping) or str
+ return lpegmatch(replacer,str,1,mapping,how or "lua") or str
else
return str
end
end
--- print(replace("test %[x]% test",{ x = [[a "x" a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
templates.replace = replace
diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii
index 386f7e557..e92106c05 100644
--- a/tex/context/base/cont-new.mkii
+++ b/tex/context/base/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.09.06 23:03}
+\newcontextversion{2012.09.10 00:57}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index 3b53d7d5d..b5125f072 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.09.06 23:03}
+\newcontextversion{2012.09.10 00:57}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 5642abc09..50e2e7800 100644
--- a/tex/context/base/context-version.pdf
+++ b/tex/context/base/context-version.pdf
Binary files differ
diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png
index 648fc8263..c4afeadb1 100644
--- a/tex/context/base/context-version.png
+++ b/tex/context/base/context-version.png
Binary files differ
diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii
index 8b40e2a7c..4d6937ead 100644
--- a/tex/context/base/context.mkii
+++ b/tex/context/base/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.09.06 23:03}
+\edef\contextversion{2012.09.10 00:57}
%D For those who want to use this:
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 5c81ac2e7..7bd9bb409 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -25,7 +25,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.09.06 23:03}
+\edef\contextversion{2012.09.10 00:57}
%D For those who want to use this:
@@ -145,7 +145,7 @@
\loadmarkfile{attr-eff}
\loadmarkfile{trac-tex}
-\loadmarkfile{trac-deb}
+\loadmarkfile{trac-deb} % will move up
\loadmarkfile{trac-ctx} % maybe move up
%loadmarkfile{blob-ini} % not to be used, we only use a helper
diff --git a/tex/context/base/data-lua.lua b/tex/context/base/data-lua.lua
index 906a611ee..ab762f3d4 100644
--- a/tex/context/base/data-lua.lua
+++ b/tex/context/base/data-lua.lua
@@ -10,7 +10,10 @@ if not modules then modules = { } end modules ['data-lua'] = {
-- on the developments (the loaders must not trigger kpse); we could
-- of course use a more extensive lib path spec
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
@@ -19,7 +22,8 @@ local unpack = unpack or table.unpack
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
+-- local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' }
+local libformats = { 'lua', 'tex' }
local clibformats = { 'lib' }
local _path_, libpaths, _cpath_, clibpaths
@@ -43,7 +47,7 @@ end
local function thepath(...)
local t = { ... } t[#t+1] = "?.lua"
local path = file.join(unpack(t))
- if trace_locating then
+ if trace_libraries then
report_libraries("! appending '%s' to 'package.path'",path)
end
return path
@@ -65,11 +69,11 @@ local function loaded(libpaths,name,simple)
for i=1,#libpaths do -- package.path, might become option
local libpath = libpaths[i]
local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
end
return loadfile(resolved)
@@ -80,22 +84,22 @@ end
package.loaders[2] = function(name) -- was [#package.loaders+1]
if file.suffix(name) == "" then
name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s' with forced suffix",name)
end
else
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! locating '%s'",name)
end
end
for i=1,#libformats do
local format = libformats[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
end
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
end
return loadfile(resolved)
@@ -118,11 +122,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for p=1,#paths do
local path = paths[p]
local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
+ if trace_libraries then -- mode detail
report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
end
return package.loadlib(resolved,name)
@@ -132,11 +136,11 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
for i=1,#clibpaths do -- package.path, might become option
local libpath = clibpaths[i]
local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
+ if trace_libraries then -- more detail
report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
end
if file.is_readable(resolved) then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
end
return package.loadlib(resolved,name)
@@ -148,12 +152,12 @@ package.loaders[2] = function(name) -- was [#package.loaders+1]
end
local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
if resolved ~= "" then
- if trace_locating then
+ if trace_libraries then
report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
return loadfile(resolved)
end
- if trace_locating then
+ if trace_libraries then
report_libraries('? unable to locate lib: %s',name)
end
-- return "unable to locate " .. name
@@ -170,3 +174,4 @@ package.prepend_libpath = prependtolibpath -- will become obsolete
package.obsolete.append_libpath = appendtolibpath -- will become obsolete
package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+
diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua
index 168300767..0705b8e5a 100644
--- a/tex/context/base/file-job.lua
+++ b/tex/context/base/file-job.lua
@@ -718,6 +718,7 @@ end
document = document or {
arguments = allocate(),
files = allocate(),
+ variables = allocate(), -- for templates
options = {
commandline = {
environments = allocate(),
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
index cdfa9b051..03616aa19 100644
--- a/tex/context/base/l-string.lua
+++ b/tex/context/base/l-string.lua
@@ -125,3 +125,11 @@ string.unquote = string.unquoted
-- handy fallback
string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua
index 6447fb040..cbcec8329 100644
--- a/tex/context/base/l-unicode.lua
+++ b/tex/context/base/l-unicode.lua
@@ -12,7 +12,7 @@ if not modules then modules = { } end modules ['l-unicode'] = {
local concat = table.concat
local type = type
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local utftype = patterns.utftype
local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
@@ -579,3 +579,11 @@ end
function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+
+--
+
+local pattern = Ct(C(patterns.utf8char)^0)
+
+function utf.totable(str)
+ return lpegmatch(pattern,str)
+end
diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv
index 2eba44931..6ca0ac05a 100644
--- a/tex/context/base/luat-lib.mkiv
+++ b/tex/context/base/luat-lib.mkiv
@@ -69,6 +69,7 @@
\registerctxluafile{luat-exe}{1.001}
\registerctxluafile{luat-iop}{1.001}
\registerctxluafile{luat-bwc}{1.001}
+\registerctxluafile{trac-lmx}{1.001} % might become l-lmx or luat-lmx
\registerctxluafile{luat-mac}{1.001}
\registerctxluafile{lxml-tab}{1.001}
diff --git a/tex/context/base/luat-mac.lua b/tex/context/base/luat-mac.lua
index f8f87a25a..199332bba 100644
--- a/tex/context/base/luat-mac.lua
+++ b/tex/context/base/luat-mac.lua
@@ -20,6 +20,8 @@ local lpegmatch, patterns = lpeg.match, lpeg.patterns
local insert, remove = table.insert, table.remove
local rep, sub = string.rep, string.sub
local setmetatable = setmetatable
+local filesuffix = file.suffix
+local convertlmxstring = lmx.convertstring
local pushtarget, poptarget = logs.pushtarget, logs.poptarget
@@ -199,18 +201,91 @@ function macros.version(data)
return lpegmatch(checker,data)
end
+-- function macros.processmkvi(str,filename)
+-- if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+-- local oldsize = #str
+-- str = lpegmatch(parser,str,1,true) or str
+-- pushtarget("log")
+-- report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str)
+-- poptarget("log")
+-- end
+-- return str
+-- end
+--
+-- utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
+
+-- the document variables hack is temporary
+
+local processors = { }
+
+function processors.mkvi(str,filename)
+ local oldsize = #str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function processors.mkix(str,filename) -- we could intercept earlier so that caching works better
+ if not document then -- because now we hash the string as well as the
+ document = { }
+ end
+ if not document.variables then
+ document.variables = { }
+ end
+ local oldsize = #str
+ str = convertlmxstring(str,document.variables,false) or str
+ pushtarget("log")
+ report_macros("processed mkix file %q, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function processors.mkxi(str,filename)
+ if not document then
+ document = { }
+ end
+ if not document.variables then
+ document.variables = { }
+ end
+ local oldsize = #str
+ str = convertlmxstring(str,document.variables,false) or str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkxi file %q, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function macros.processmk(str,filename)
+ if filename then
+ local suffix = filesuffix(filename)
+ local processor = processors[suffix] or processors[lpegmatch(checker,str)]
+ if processor then
+ str = processor(str,filename)
+ end
+ end
+ return str
+end
+
+utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmk")
+
function macros.processmkvi(str,filename)
- if (filename and file.suffix(filename) == "mkvi") or lpegmatch(checker,str) == "mkvi" then
- local result = lpegmatch(parser,str,1,true) or str
+ if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+ local oldsize = #str
+ str = lpegmatch(parser,str,1,true) or str
pushtarget("log")
- report_macros("processed file '%s', delta %s",filename,#str-#result)
+ report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str)
poptarget("log")
- return result
- else
- return str
end
+ return str
end
+utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
+
+-- bonus
+
if resolvers.schemes then
local function handler(protocol,name,cachename)
@@ -218,7 +293,7 @@ if resolvers.schemes then
local path = hashed.path
if path and path ~= "" then
local str = resolvers.loadtexfile(path)
- if file.suffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+ if filesuffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
-- already done automatically
io.savedata(cachename,str)
else
@@ -234,9 +309,6 @@ if resolvers.schemes then
resolvers.schemes.install('mkvi',handler,1) -- this will cache !
- utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
- -- utilities.sequencers.disableaction(resolvers.openers.helpers.textfileactions,"resolvers.macros.processmkvi")
-
end
-- print(macros.preprocessed(
diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua
index 426e07b15..a2926f03b 100644
--- a/tex/context/base/lxml-lpt.lua
+++ b/tex/context/base/lxml-lpt.lua
@@ -1205,12 +1205,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex
index cf2ade8a0..4033560a6 100644
--- a/tex/context/base/s-abr-01.tex
+++ b/tex/context/base/s-abr-01.tex
@@ -24,6 +24,8 @@
\logo [MKIII] {MkIII} % joke
\logo [MKIV] {MkIV}
\logo [MKVI] {MkVI}
+\logo [MKIX] {MkIX}
+\logo [MKXI] {MkXI}
\logo [MPII] {MpII}
\logo [MPIV] {MpIV}
@@ -145,6 +147,7 @@
\logo [LUAJIT] {LuaJIT}
\logo [LUATEX] {Lua\TeX}
\logo [LUATOOLS] {luatools}
+\logo [LMX] {lmx}
\logo [MACOSX] {MacOSX}
\logo [MACROTEX] {Macro\TeX}
\logo [MAKEMPY] {MakeMPY}
diff --git a/tex/context/base/sort-lan.lua b/tex/context/base/sort-lan.lua
index 84cd7aa49..d2fa276d7 100644
--- a/tex/context/base/sort-lan.lua
+++ b/tex/context/base/sort-lan.lua
@@ -7,6 +7,9 @@ if not modules then modules = { } end modules ['sort-lan'] = {
dataonly = true,
}
+-- todo: look into uts#10 (2012) ... some experiments ... something
+-- to finish in winter.
+
-- Many vectors were supplied by Wolfgang Schuster and Philipp
-- Gesang. However this is a quite adapted and reformatted variant
-- so it needs some checking. Other users provides tables and
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index ca09992dd..b5c7464c8 100644
--- a/tex/context/base/status-files.pdf
+++ b/tex/context/base/status-files.pdf
Binary files differ
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
index 8aa2791d6..51523908b 100644
--- a/tex/context/base/status-lua.pdf
+++ b/tex/context/base/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua
index 6690e7be6..f8c6c692b 100644
--- a/tex/context/base/status-mkiv.lua
+++ b/tex/context/base/status-mkiv.lua
@@ -2556,11 +2556,6 @@ return {
},
{
category = "lua",
- filename = "bibl-tst",
- status = "todo",
- },
- {
- category = "lua",
filename = "blob-ini",
status = "todo",
},
@@ -4481,7 +4476,7 @@ return {
category = "lua",
comment = "will be redone and extended",
filename = "trac-lmx",
- loading = "trac-lmx",
+ loading = "luat-lib",
status = "pending",
},
{
diff --git a/tex/context/base/trac-deb.mkiv b/tex/context/base/trac-deb.mkiv
index 10e462a31..fe5dd02dc 100644
--- a/tex/context/base/trac-deb.mkiv
+++ b/tex/context/base/trac-deb.mkiv
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Tracing Macros / Debugger}
-\registerctxluafile{trac-lmx}{1.001}
+%registerctxluafile{trac-lmx}{1.001}
\registerctxluafile{trac-deb}{1.001}
\unexpanded\def\breakpoint{\showdebuginfo\wait}
diff --git a/tex/context/base/trac-lmx.lua b/tex/context/base/trac-lmx.lua
index e83fdce7f..b39c8ca54 100644
--- a/tex/context/base/trac-lmx.lua
+++ b/tex/context/base/trac-lmx.lua
@@ -26,6 +26,9 @@ local report_error = logs.reporter("lmx","error")
lmx = lmx or { }
local lmx = lmx
+-- This will change: we will just pass the global defaults as argument, but then we need
+-- to rewrite some older code or come up with an ugly trick.
+
local lmxvariables = {
['title-default'] = 'ConTeXt LMX File',
['color-background-green'] = '#4F6F6F',
@@ -370,10 +373,6 @@ local luacodecss = beginluacss
* (1-endluacss)^1
* endluacss
--- local othercode = Cc(" p[==[")
--- * (1-beginluaxml-beginluacss)^1
--- * Cc("]==] ")
-
local othercode = (1-beginluaxml-beginluacss)^1 / " p[==[%0]==] "
local include = ((beginembedxml * P("lmx-include") * whitespace) / "")
@@ -416,7 +415,7 @@ local function wrapper(converter,defaults,variables)
end
end
-function lmxnew(data,defaults)
+function lmxnew(data,defaults,nocache) -- todo: use defaults in calling routines
data = data or ""
local known = cache[data]
if not known then
@@ -441,7 +440,7 @@ function lmxnew(data,defaults)
variables = defaults,
converter = converter,
}
- if cache_templates then
+ if cache_templates and nocache ~= false then
cache[data] = known
end
elseif variables then
@@ -472,23 +471,23 @@ lmx.result = lmxresult
local loadedfiles = { }
-function lmx.convertstring(templatestring,variables)
- return lmxresult(lmxnew(templatestring),variables)
+function lmx.convertstring(templatestring,variables,nocache)
+ return lmxresult(lmxnew(templatestring,nil,nocache),variables)
end
-function lmx.convertfile(templatefile,variables)
+function lmx.convertfile(templatefile,variables,nocache)
if trace_variables then -- will become templates
report_lmx("converting file: %s",templatefile)
end
local converter = loadedfiles[templatefile]
if not converter then
- converter = lmxnew(loadedfile(templatefile))
+ converter = lmxnew(loadedfile(templatefile),nil,nocache)
loadedfiles[templatefile] = converter
end
return lmxresult(converter,variables)
end
-function lmxconvert(templatefile,resultfile,variables) -- or (templatefile,variables)
+function lmxconvert(templatefile,resultfile,variables,nocache) -- or (templatefile,variables)
if trace_variables then -- will become templates
report_lmx("converting file: %s",templatefile)
end
@@ -497,7 +496,7 @@ function lmxconvert(templatefile,resultfile,variables) -- or (templatefile,varia
end
local converter = loadedfiles[templatefile]
if not converter then
- converter = lmxnew(loadedfile(templatefile))
+ converter = lmxnew(loadedfile(templatefile),nil,nocache)
if cache_files then
loadedfiles[templatefile] = converter
end
diff --git a/tex/context/base/util-sql.lua b/tex/context/base/util-sql.lua
index 798ef44af..aeee7c09b 100644
--- a/tex/context/base/util-sql.lua
+++ b/tex/context/base/util-sql.lua
@@ -6,30 +6,44 @@ if not modules then modules = { } end modules ['util-sql'] = {
license = "see context related readme files"
}
--- Of course we could use a library but we don't want another depedency and
--- there is a bit of flux in these libraries. Also, we want the data back in
--- a way that we like.
-
--- Todo: buffer templates when files.
+-- Of course we could use a library but we don't want another depedency and there is
+-- a bit of flux in these libraries. Also, we want the data back in a way that we
+-- like.
+--
+-- This is the first of set of sql related modules that are providing functionality
+-- for a web based framework that we use for typesetting (related) services. We're
+-- talking of session management, job ticket processing, storage, (xml) file processing
+-- and dealing with data from databases (often ambitiously called database publishing).
+--
+-- There is no generic solution for such services, but from our perspective, as we use
+-- context in a regular tds tree (the standard distribution) it makes sense to put shared
+-- code in the context distribution. That way we don't need to reinvent wheels every time.
local format = string.format
+local random = math.random
local rawset, setmetatable, loadstring, type = rawset, setmetatable, loadstring, type
local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match
local concat = table.concat
-local osclock = os.clock or os.time
-local fastserialize = table.fastserialize
-local lpegmatch = lpeg.match
+local osuuid = os.uuid
+local osclock = os.clock or os.time
-local trace_sql = false trackers.register("sql.trace",function(v) trace_sql = v end)
-local report_state = logs.reporter("sql")
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql")
-utilities.sql = utilities.sql or { }
-local sql = utilities.sql
+utilities.sql = utilities.sql or { }
+local sql = utilities.sql
local replacetemplate = utilities.templates.replace
local loadtemplate = utilities.templates.load
+local methods = { }
+sql.methods = methods
+
+sql.serialize = table.fastserialize
+sql.deserialize = table.deserialize
+
local defaults = { __index =
{
resultfile = "result.dat",
@@ -44,22 +58,21 @@ local defaults = { __index =
},
}
-local engine = "mysql"
-
-local runners = { -- --defaults-extra-file="%inifile"
- mysql = [[mysql --user="%username%" --password="%password%" --host="%host%" --port=%port% --database="%database%" < "%queryfile%" > "%resultfile%"]],
-}
-
-sql.runners = runners
-
-- Experiments with an p/action demonstrated that there is not much gain. We could do a runtime
-- capture but creating all the small tables is not faster and it doesn't work well anyway.
local separator = P("\t")
local newline = patterns.newline
-local entry = C((1-separator-newline)^0) -- C 10% faster than Cs
local empty = Cc("")
+local entry = C((1-separator-newline)^0) -- C 10% faster than Cs
+
+local unescaped = P("\\n") / "\n"
+ + P("\\t") / "\t"
+ + P("\\\\") / "\\"
+
+local entry = Cs((unescaped + (1-separator-newline))^0) -- C 10% faster than Cs but Cs needed due to nesting
+
local getfirst = Ct( entry * (separator * (entry+empty))^0) + newline
local skipfirst = (1-newline)^1 * newline
local getfirstline = C((1-newline)^0)
@@ -157,16 +170,39 @@ local function validspecification(specification)
return true
end
-local function dataprepared(specification)
- local query = false
- if specification.template then
- query = replacetemplate(specification.template,specification.variables)
- elseif specification.templatefile then
- query = loadtemplate(specification.templatefile,specification.variables)
+local function preparetemplate(specification)
+ local template = specification.template
+ if template then
+ local query = replacetemplate(template,specification.variables,'sql')
+ if not query then
+ report_state("error in template: %s",template)
+ elseif trace_queries then
+ report_state("query from template: %s",query)
+ end
+ return query
+ end
+ local templatefile = specification.templatefile
+ if templatefile then
+ local query = loadtemplate(templatefile,specification.variables,'sql')
+ if not query then
+ report_state("error in template file %q",templatefile)
+ elseif trace_queries then
+ report_state("query from template file %q: %s",templatefile,query)
+ end
+ return query
end
+ report_state("no query template or templatefile")
+end
+
+
+local function dataprepared(specification)
+ local query = preparetemplate(specification)
if query then
io.savedata(specification.queryfile,query)
os.remove(specification.resultfile)
+ if trace_queries then
+ report_state("query: %s",query)
+ end
return true
else
-- maybe push an error
@@ -175,17 +211,17 @@ local function dataprepared(specification)
end
end
-local function datafetched(specification)
- local command = replacetemplate(runners[engine],specification)
+local function datafetched(specification,runner)
+ local command = replacetemplate(runner,specification)
if trace_sql then
local t = osclock()
report_state("command: %s",command)
- os.execute(command)
+ local okay = os.execute(command)
report_state("fetchtime: %.3f sec",osclock()-t) -- not okay under linux
+ return okay == 0
else
- os.execute(command)
+ return os.execute(command) == 0
end
- return true
end
local function dataloaded(specification)
@@ -215,66 +251,100 @@ end
sql.splitdata = splitdata
-local methods = { }
-sql.methods = methods
-
-- todo: new, etc
-local function fetch(specification)
+local function execute(specification)
if trace_sql then
- report_state("fetching")
+ report_state("executing")
end
if not validspecification(specification) then
- report("error in specification")
+ report_state("error in specification")
return
end
if not dataprepared(specification) then
- report("error in preparation")
+ report_state("error in preparation")
return
end
- if not datafetched(specification) then
- report("error in fetching")
+ if not datafetched(specification,methods.client.runner) then
+ report_state("error in fetching, query: %s",string.collapsespaces(io.loaddata(specification.queryfile)))
return
end
local data = dataloaded(specification)
--- local data = datafetched(specification)
if not data then
- report("error in loading")
+ report_state("error in loading")
return
end
local data, keys = dataconverted(data)
if not data then
- report("error in converting")
+ report_state("error in converting")
return
end
return data, keys
end
--- local function reuse(specification)
--- if trace_sql then
--- report_state("reusing")
--- end
--- if not validspecification(specification) then
--- report("error in specification")
--- return
--- end
--- local data = dataloaded(specification)
--- if not data then
--- report("error in loading")
--- return
--- end
--- local data, keys = dataconverted(data)
--- if not data then
--- report("error in converting")
--- return
--- end
--- return data, keys
--- end
-
-sql.fetch = fetch
-
methods.client = {
- fetch = fetch,
+ runner = [[mysql --batch --user="%username%" --password="%password%" --host="%host%" --port=%port% --database="%database%" < "%queryfile%" > "%resultfile%"]],
+ execute = execute,
+ serialize = serialize,
+ deserialize = deserialize,
+}
+
+local function dataloaded(specification)
+ if trace_sql then
+ local t = osclock()
+ local data = table.load(specification.resultfile)
+ report_state("loadtime: %.3f sec",osclock()-t)
+ return data
+ else
+ return table.load(specification.resultfile)
+ end
+end
+
+local function dataconverted(data)
+ if trace_sql then
+ local data, keys = data.data, data.keys
+ report_state("keys: %s ",#keys)
+ report_state("entries: %s ",#data)
+ return data, keys
+ else
+ return data.data, data.keys
+ end
+end
+
+local function execute(specification)
+ if trace_sql then
+ report_state("executing")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ if not dataprepared(specification) then
+ report_state("error in preparation")
+ return
+ end
+ if not datafetched(specification,methods.lmxsql.runner) then
+ report_state("error in fetching, query: %s",string.collapsespaces(io.loaddata(specification.queryfile)))
+ return
+ end
+ local data = dataloaded(specification)
+ if not data then
+ report_state("error in loading")
+ return
+ end
+ local data, keys = dataconverted(data)
+ if not data then
+ report_state("error in converting")
+ return
+ end
+ return data, keys
+end
+
+methods.lmxsql = {
+ runner = [[lmx-sql %host% %port% "%username%" "%password%" "%database%" "%queryfile%" "%resultfile%"]],
+ execute = execute,
+ serialize = serialize,
+ deserialize = deserialize,
}
local mysql = nil
@@ -294,17 +364,7 @@ local function validspecification(specification)
return true
end
-local function dataprepared(specification)
- local query = false
- if specification.template then
- query = replacetemplate(specification.template,specification.variables)
- elseif specification.templatefile then
- query = loadtemplate(specification.templatefile,specification.variables)
- end
- if query then
- return query
- end
-end
+local dataprepared = preparetemplate
local function connect(session,specification)
return session:connect(
@@ -317,9 +377,17 @@ local function connect(session,specification)
end
local whitespace = patterns.whitespace^0
-local quoted = patterns.quoted
local separator = P(";")
-local query = whitespace * Cs((quoted + 1 - separator)^1 * Cc(";")) * whitespace
+local escaped = patterns.escaped
+local dquote = patterns.dquote
+local squote = patterns.squote
+local dsquote = squote * squote
+---- quoted = patterns.quoted
+local quoted = dquote * (escaped + (1-dquote))^0 * dquote
+ + squote * (escaped + dsquote + (1-squote))^0 * squote
+local query = whitespace
+ * Cs((quoted + 1 - separator)^1 * Cc(";"))
+ * whitespace
local splitter = Ct(query * (separator * query)^0)
local function datafetched(specification,query)
@@ -348,7 +416,9 @@ local function datafetched(specification,query)
for i=1,#query do
local q = query[i]
result, message = connection:execute(q)
--- io.savedata("e:/tmp/oeps.sql",q)
+ if message then
+ report_state("error in query: %s",string.collapsespaces(q))
+ end
end
if not result and id then
if session then
@@ -361,7 +431,11 @@ local function datafetched(specification,query)
connection = connect(session,specification)
cache[id] = { session = session, connection = connection }
for i=1,#query do
- result, message = connection:execute(query[i])
+ local q = query[i]
+ result, message = connection:execute(q)
+ if message then
+ report_state("error in query: %s",string.collapsespaces(q))
+ end
end
end
local data, keys
@@ -397,7 +471,7 @@ local function datafetched(specification,query)
return data, keys
end
-local function fetch(specification)
+local function execute(specification)
if not mysql then
local lib = require("luasql.mysql")
if lib then
@@ -407,31 +481,49 @@ local function fetch(specification)
end
end
if trace_sql then
- report_state("fetching")
+ report_state("executing")
end
if not validspecification(specification) then
- report("error in specification")
+ report_state("error in specification")
return
end
local query = dataprepared(specification)
if not query then
- report("error in preparation")
+ report_state("error in preparation")
return
end
local data, keys = datafetched(specification,query)
if not data then
- report("error in fetching")
+ report_state("error in fetching")
return
end
return data, keys
end
methods.library = {
- fetch = fetch,
+ runner = function() end, -- never called
+ execute = execute,
+ serialize = serialize,
+ deserialize = deserialize,
}
-- -- --
+local currentmethod
+
+function sql.setmethod(method)
+ local m = methods[method]
+ if m then
+ currentmethod = method
+ sql.execute = m.execute
+ return m
+ else
+ return methods[currentmethod]
+ end
+end
+
+sql.setmethod("client")
+
-- local data = utilities.sql.prepare {
-- templatefile = "test.sql",
-- variables = { },
@@ -466,93 +558,42 @@ methods.library = {
-- presets = "...",
-- }
--- -- --
-
-local e_pattern = lpeg.replacer { { '\\"','\\\\""' }, {'"','""'}, {'\\\n', "\\n" }, {'\\\r', "\\r" }, {'\t', " " } }
-local u_pattern = lpeg.replacer { { '\\\\','\\' } }
-local u_pattern = lpeg.replacer { { '\\\\','\\' }, { "\n","\\n" } }
-
--- library:
-
-function methods.library.serialize(t)
- local str = fastserialize(t,"return")
- local escaped = lpegmatch(e_pattern,str)
- return escaped
-end
-
-function methods.library.deserialize(str)
- local unescaped = lpegmatch(u_pattern,str)
- if not unescaped then
- return
- end
- local code = loadstring(unescaped)
- if not code then
- return
- end
- code = code()
- if not code then
- return
- end
- return code
-end
-
--- client
-
-local e_pattern = lpeg.replacer { { '\\"','\\\\""' }, {'"','""'}, {'\\\n', "\\n" }, {'\\\r', "\\r" } }
-local u_pattern = lpeg.replacer { { '\\\\','\\' } }
-
-function methods.client.serialize(t)
- return lpegmatch(e_pattern,fastserialize(t,"return"))
-end
-
-function methods.client.deserialize(str)
- local unescaped = lpegmatch(u_pattern,str)
- if not unescaped then
- return
- end
- local code = loadstring(unescaped)
- if not code then
- return
- end
- code = code()
- if not code then
- return
- end
- return code
-end
-
-sql.serialize = methods.client.serialize
-sql.deserialize = methods.client.deserialize
-
-function sql.escape(str)
- return lpegmatch(e_pattern,str)
-end
-
-function sql.unescape(str)
- return lpegmatch(u_pattern,str)
-end
-
--- local s = sql.serialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } }
--- local u = sql.unescape(s)
--- local t = sql.deserialize(s)
--- inspect(s)
--- inspect(u)
--- inspect(t)
+sql.tokens = {
+ length = 42,
+ new = function()
+ return format("%s+%05x",osuuid(),random(1,0xFFFFF)) -- 36 + 1 + 5 = 42
+ end,
+}
-- -- --
if tex and tex.systemmodes then
- function sql.prepare(specification)
+ local droptable = table.drop
+ local threshold = 16 * 1024 -- use slower but less memory hungry variant
+
+ function sql.prepare(specification,tag)
+ -- could go into tuc if needed
+ -- todo: serialize per column
+ local filename = format("%s-sql-result-%s.tuc",tex.jobname,tag or "last")
if tex.systemmodes["first"] then
- return sql.fetch(specification)
+ local data, keys = sql.execute(specification)
+ if not data then
+ data = { }
+ end
+ if not keys then
+ keys = { }
+ end
+ io.savedata(filename,droptable({ data = data, keys = keys },#keys*#data>threshold))
+ return data, keys
else
- return sql.reuse(specification)
+ local result = table.load(filename)
+ return result.data, result.keys
end
end
else
- sql.prepare = sql.fetch
+ sql.prepare = sql.execute
end
diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua
index d45b58f6f..f0977743b 100644
--- a/tex/context/base/util-tab.lua
+++ b/tex/context/base/util-tab.lua
@@ -168,14 +168,6 @@ function tables.encapsulate(core,capsule,protect)
end
end
-local escaped = Cs ( (
- P('\\' ) +
- P('"' )/'\\"' +
- P('\n')/'\\n' +
- P('\r')/'\\r' +
- 1
-)^0 )
-
local function serialize(t,r,outer) -- no mixes
r[#r+1] = "{"
local n = #t
@@ -217,7 +209,19 @@ local function serialize(t,r,outer) -- no mixes
end
function table.fastserialize(t,prefix)
- return concat(serialize(t,{ prefix },true))
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
end
-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
@@ -236,3 +240,42 @@ function table.load(filename)
end
end
end
+
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
diff --git a/tex/context/base/util-tpl.lua b/tex/context/base/util-tpl.lua
index 2a728d373..f6648b224 100644
--- a/tex/context/base/util-tpl.lua
+++ b/tex/context/base/util-tpl.lua
@@ -20,6 +20,8 @@ local report_template = logs.reporter("template")
local format = string.format
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)
@@ -33,40 +35,59 @@ local function replacekey(k,t)
if trace_template then
report_template("setting key %q to value %q",k,v)
end
- -- return v
return lpegmatch(replacer,v,1,t) -- recursive
end
end
------ leftmarker = P("<!-- ") / ""
------ rightmarker = P(" --!>") / ""
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t))
+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 escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
local key = nosingle * (C((1-nosingle)^1 * Carg(1))/replacekey) * nosingle
-local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1))/function(s,t) return format("%q",replacekey(s,t)) end) * norquoted
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2))/replacekeyunquoted) * norquoted
local any = P(1)
replacer = Cs((unquoted + escape + key + any)^0)
-local function replace(str,mapping)
+local function replace(str,mapping,how)
if mapping then
- return lpegmatch(replacer,str,1,mapping) or str
+ return lpegmatch(replacer,str,1,mapping,how or "lua") or str
else
return str
end
end
--- print(replace("test %[x]% test",{ x = [[a "x" a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
templates.replace = replace
diff --git a/tex/context/base/x-mathml.mkiv b/tex/context/base/x-mathml.mkiv
deleted file mode 100644
index 2fb5fb58a..000000000
--- a/tex/context/base/x-mathml.mkiv
+++ /dev/null
@@ -1,2425 +0,0 @@
-%D \module
-%D [ file=x-mathml,
-%D version=2008.05.29,
-%D title=\CONTEXT\ XML Modules,
-%D subtitle=Loading \MATHML\ Filters,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-% \xmlfilter{#1}{/*/name()} -> \xmltag
-
-% This module is under construction and will be cleaned up. We use a funny mix of
-% xml, tex and lua. I could rewrite the lot but it also shows how context evolves.
-%
-% no m:text strip (needs checking, maybe nbsp is mandate
-%
-% todo: more will be moved to lua (less hassle)
-% todo: move left/right to the lua end
-
-\writestatus{loading}{ConTeXt XML Macros / MathML Renderer}
-
-\unprotect
-
-\usemodule[x][calcmath]
-%usemodule[x][asciimath]
-
-\startmodule [mathml]
-
-\registerctxluafile{x-mathml}{}
-
-\def\ctxmodulemathml#1{\directlua\zerocount{moduledata.mathml.#1}}
-
-\startxmlsetups xml:mml:define
- \xmlsetsetup{#1} {(formula|subformula)} {mml:formula}
- \xmlfilter {#1} {omt:*/function(remapopenmath)}
- \xmlfilter {#1} {mml:bind/function(remapmmlbind)}
- \xmlfilter {#1} {mml:csymbol/function(remapmmlcsymbol)}
- \xmlsetsetup{#1} {mml:*} {mml:*}
- \xmlsetsetup{#1} {mml:apply/mml:apply/mml:inverse/../..} {mml:apply:inverse}
- \xmlstrip {#1} {(mml:mi|mml:mo|mml:mn|mml:csymbol)}
-\stopxmlsetups
-
-\xmlregisterns{omt}{openmath}
-\xmlregisterns{mml}{mathml}
-
-\xmlregistersetup{xml:mml:define}
-
-\unexpanded\def\MMLhack
- {\let\MMLpar\par
- \let\par\relax
- \everyvbox{\let\par\MMLpar}}
-
-\xmlmapvalue {mml:math:mode} {display} {\displaymathematics} % we had this already
-\xmlmapvalue {mml:math:mode} {inline} {\inlinemathematics }
-
-\xmlmapvalue {mml:math:display} {block} {\displaymathematics} % before this showed up
-\xmlmapvalue {mml:math:display} {inline} {\inlinemathematics }
-
-\xmlmapvalue {mml:math:dir} {ltr} {\setfalse\c_math_right_to_left\math_basics_synchronize_direction}
-\xmlmapvalue {mml:math:dir} {rtl} {\settrue \c_math_right_to_left\math_basics_synchronize_direction}
-
-\startxmlsetups mml:math
- \begingroup
- \xmlval {mml:math:dir} {\xmlatt{#1}{dir}} {}
- \xmlval {mml:math:display} {\xmlatt{#1}{display}} {
- \xmlval {mml:math:mode} {\xmlatt{#1}{mode}} {
- \automathematics
- }
- }
- {
- \MMLhack\xmlflush{#1}
- }
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:imath
- \inlinemathematics{\MMLhack\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:dmath
- \displaymathematics{\MMLhack\xmlflush{#1}}
-\stopxmlsetups
-
-%D First we define some general formula elements.
-
-\startxmlsetups mml:formula
- \edef\mmlformulalabel {\xmlatt{#1}{label}\xmlatt{#1}{id}}
- \edef\mmlformulasublabel{\xmlatt{#1}{sublabel}\xmlatt{#1}{id}}
- \doifsomething\mmlformulalabel{\placeformula[\mmlformulalabel]{\mmlformulasublabel}}
- \startformula\MMLhack\xmlfirst{#1}{/mml:math}\stopformula
-\stopxmlsetups
-
-\setfalse\mmlignoredelimiter
-\settrue \mmlsomeleftdelimiter
-
-\def\MMLleftorright
- {\ifconditional\mmlsomeleftdelimiter
- \setfalse\mmlsomeleftdelimiter\expandafter\MMLleft
- \else
- \settrue \mmlsomeleftdelimiter\expandafter\MMLright
- \fi}
-
-\ifx\MMLleft \undefined \let\MMLleft \firstofoneargument \fi
-\ifx\MMLright \undefined \let\MMLright \firstofoneargument \fi
-\ifx\MMLmiddle\undefined \let\MMLmiddle\firstofoneargument \fi
-
-\def\mmlleftdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLleft #1}\fi}
-\def\mmlrightdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLright #1}\fi}
-\def\mmlmiddledelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLmiddle #1}\fi}
-\def\mmlleftorrightdelimiter#1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLleftorright#1}\fi}
-
-\def\mmlchar#1{\char#1 } % used in lua code
-
-% \newcount\delimiternesting \appendtoks \delimiternesting\zerocount \to \everymathematics
-
-% \def\mmlleftdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{%
-% \advance\delimiternesting\plusone \MMLleft #1}\fi}
-% \def\mmlrightdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{%
-% \advance\delimiternesting\plusone \MMLright#1}\fi}
-% \def\mmlmiddledelimiter#1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{%
-% \ifcase\delimiternesting\MMLleft\else\MMLmiddle\fi#1}\fi}
-
-%D Remark: from now on this is a module and no longer an xtag
-%D filter. There is an intermediate cleaner module but it has
-%D some namespace limitations. Here we do it the \MKIV\ way.
-
-\def\widevec#1%
- {\vbox{\mathsurround\zeropoint\ialign{##\crcr
- \rightarrowfill\crcr\noalign{\nointerlineskip}%
- \startimath\hfil\displaystyle{#1}\hfil\stopimath\crcr}}}
-
-%D The rendering macros:
-
-\def\MMLrm{\mr}
-
-\def\MMLseparator#1{\removeunwantedspaces{#1}\ignorespaces} % nils space after separator
-\def\MMLseparator#1{,} % todo, for europe we need to block the space
-
-%D Since I only had the draft of MathML 2 and later 3 as example of
-%D rendering, there are probably a lot of omissions and
-%D misinterpretations. At least I learned some bits and
-%D pieces of math rendering.
-%D
-%D The main complications were not so much the math, but to
-%D find the most efficient way to handle elements without
-%D spacing beging messed up. The first implementation was
-%D aimed at getting reasonable output, this second
-%D implementation is already better in terms of handling
-%D nesting, and I will definitely need a third one that has
-%D more efficient and less ugly code.
-%D
-%D The \TEX\ part is not that complicated and once the
-%D preprocessor was okay, the rest way just a lot of keying
-%D and testing. It all comes down to gobbling, redefining,
-%D and not so much to parsing.
-%D
-%D The second implementation expanded the whole math sequence
-%D into an internal \TEX\ representation. This is a rather clean
-%D and fast process. Filtering and testing takes place by
-%D redefining teh internal representation macros.
-%D
-%D The third implementation may look a bit more messy in some
-%D respects. This is because in \TEX\ it's not that trivial to
-%D implement a tree handler. We use a stack for the \type {apply}
-%D element and other sequential content. Occasionally we need to
-%D peek into child elements which involves messy code. This
-%D implementation is closer to the normal \XML\ handling in
-%D \CONTEXT.
-
-%D We start with the parent elements and the option handler.
-
-\def\xmlmathmldirective#1{\dosetvalue{MML#1}}
-
-%def\xmlmathmldirective#1#2#3{[#1][#2][#3]\dosetvalue{MML#1}{#2}{#3}}
-
-%D In the styles, options can be set with:
-
-\unexpanded\def\setupMMLappearance[#1]{\dodoubleargument\getparameters[MML#1]} % no @@ because passed to lua
-
-%D We will apply inner math to all bits and pieces made up by an
-%D \type {apply}.
-
-\def\MMLmathinner
- {\ifinner
- \expandafter\firstofoneargument
- \else
- \expandafter\mathinner
- \fi}
-
-%D Auxiliary MathML macros: (to be generalized)
-
-\def\mmlfirst #1{\xmlelement{#1}{1}} % we can move these inline if needed
-\def\mmlsecond #1{\xmlelement{#1}{2}}
-\def\mmlthird #1{\xmlelement{#1}{3}}
-\def\mmlprelast#1{\xmlelement{#1}{-2}}
-\def\mmllast #1{\xmlelement{#1}{-1}}
-
-\starttexdefinition doifelsemmlfunction #1
- \xmldoifelse {#1} {/mml:fn} {
- \firstoftwoarguments
- } {
- \xmldoifelse {#1} {/mml:apply/mml:fn} {
- \firstoftwoarguments
- } {
- \xmldoifelse {#1} {/mml:ci[@type=='fn']} {
- \firstoftwoarguments
- } {
- \secondoftwoarguments
- }
- }
- }
-\stoptexdefinition
-
-%D Special features:
-
- \newtoks \@@postponedMMLactions \setfalse \somepostponedMMLactions
-
- \def\postponeMMLactions#1%
- {\global\settrue\somepostponedMMLactions
- \global\@@postponedMMLactions\expandafter{\the\@@postponedMMLactions#1}}
-
- \def\postponedMMLactions
- {\global\setfalse\somepostponedMMLactions
- \@EA\global\@EA\@@postponedMMLactions\@EA\emptytoks
- \the\@@postponedMMLactions}
-
-%D A couple of lists:
-
-\convertargument
- mml:times|mml:divide|mml:power|%
- mml:lt|mml:gt|mml:eq|mml:leq|mml:geq|%
- mml:in|mml:inverse|%
- mml:fn|%
- mml:floor|mml:ceiling|%
- mml:mean|%
- mml:selector|%
- mml:abs|mml:int|mml:limit|mml:sum|mml:product|%
- mml:outerproduct|mml:innerproduct|mml:scalarproduct%
-\to \MMLcmainresetlist
-
-\convertargument
- mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|%
- mml:cos|mml:arccos|mml:cosh|mml:arccosh|%
- mml:tan|mml:arctan|mml:tanh|mml:arctanh|%
- mml:cot|mml:arccot|mml:coth|mml:arccoth|%
- mml:csc|mml:arccsc|mml:csch|mml:arccsch|%
- mml:sec|mml:arcsec|mml:sech|mml:arcsech|%
- mml:ln|mml:exp|mml:log|%
- mml:abs|mml:int|mml:limit|mml:sum|mml:product|%
- mml:fn%
-\to \MMLcfunctionlist
-
-\convertargument
- mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|%
- mml:cos|mml:arccos|mml:cosh|mml:arccosh|%
- mml:tan|mml:arctan|mml:tanh|mml:arctanh|%
- mml:cot|mml:arccot|mml:coth|mml:arccoth|%
- mml:csc|mml:arccsc|mml:csch|mml:arccsch|%
- mml:sec|mml:arcsec|mml:sech|mml:arcsech|%
- mml:ln|mml:exp|mml:log|%
- mml:abs%
-\to \MMLcpurefunctionlist
-
-\convertargument
- mml:diff|mml:partialdiff|mml:root%
-\to \MMLcconstructlist
-
-%D We use inner and grouping (begin/end and no b/e) else we
-%D get problems with 1/2(1+2) and alike (todo: ask taco).
-%D
-%D The problem with apply is that we need to take care of
-%D several situations, like:
-%D
-%D \starttyping
-%D <apply> <.../> ...
-%D <apply> <fn> ...
-%D <apply> <apply> <ci> ...
-%D <apply> <apply> <fn> <ci> ...
-%D \stoptyping
-%D
-%D Because we translated version 2 of this renderer into
-%D version 3 the following definitions may be sub optimal or
-%D more complex than actually needed.
-
-%D We will more more to lua ...
-
-% simple version
-
-\newcount\@MMLlevel \def\MMLcreset{\@MMLlevel\zerocount}
-
-\let\MMLctempresetlist\empty \def\setMMLcreset{\edef\MMLctempresetlist}
-
-\let\MMLdoL\donothing
-\let\MMLdoR\donothing
-
-\newcount\mmlapplydepth \def\MMLcreset{\mmlapplydepth\zerocount}
-
-\startxmlsetups mml:apply
- \MMLmathinner {
- \xmldoif {#1} {/(\MMLcmainresetlist\string|\MMLctempresetlist)} {
- % \MMLcreset
- }
- \edef\mmlapplyopentoken {\xmlatt{#1}{open}}
- \edef\mmlapplyclosetoken{\xmlatt{#1}{close}}
- \ifcase\mmlapplydepth \else
- \ifx\mmlapplyopentoken\empty
- \def\mmlapplyopentoken {(}
- \def\mmlapplyclosetoken{)}
- \fi
- \fi
- \advance\mmlapplydepth\plusone
- \begingroup
- \ifx\mmlapplyopentoken\empty
- \let\MMLdoL\donothing
- \let\MMLdoR\donothing
- \else
- \edef\MMLdoL{\noexpand\left \mmlapplyopentoken }
- \edef\MMLdoR{\noexpand\right\mmlapplyclosetoken}
- \fi
- \let\MMLctempresetlist\empty
- \xmldoifelse {#1} {/mml:apply} {
-% % <apply> <apply> ... </apply> <ci> .. </ci> </apply>
-% \xmldoifelse {#1} {/mml:apply(mml:plus|mml:minus)} {% [a]
-% % yet incomplete and rather untested
-% % <apply> <apply> <minus/> <tan/> <cos/> </apply> <ci>x</ci> </apply>
- } {% [b]
-% \MMLcreset
- }
-% \MMLdoL
-% \mmlfirst{#1}
-% \ifconditional\somepostponedMMLactions
-% \postponedMMLactions
-% \else
-% \left(\MMLcreset\mmlsecond{#1}\right)
-% \fi
-% \MMLdoR
-% } {
- \edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}}
- \doifsetupselse {mml:apply:mml:\mmlapplyaction} {
- \xmlsetup{#1}{mml:apply:mml:\mmlapplyaction}
- } {
-% \MMLdoL
- \xmlsetup{#1}{mml:\xmlfilter{#1}{/*/name()}}
-% \MMLdoR
- }
-% }
- \endgroup
- \advance\mmlapplydepth\minusone
- }
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:apply
- \xmlflush{#1}
- \xmlall{#1}{../[position()>1]}
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:fn
- \xmldoifelse {#1} {/mml:fn/mml:ci} {
- \edef\mmlfnci{\xmlstripped{#1}{/mml:fn/mml:ci}}% was xmlcontent
- \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:...
- \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
- } {
- \MMLcreset
- \MMLdoL
- \mmlfirst{#1}
- \ifnum\xmlcount{#1}{/*}>\plusone
- \negthinspace % not enough
- \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
- \fi
- \MMLdoR
- }
- } {
- \MMLcreset
- \MMLdoL
- \xmlall{#1}{/*}
- \MMLdoR
- }
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:csymbol
- \xmlsetup{#1}{mml:csymbol}% \MMLdoL/MMLdoR to be handled in plugin
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:ci
- \xmlfirst{#1}{/mml:ci}
- \ifnum\xmlcount{#1}{/*}>\plusone
- \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
- \fi
-\stopxmlsetups
-
-% reln
-
-\startxmlsetups mml:reln
- \writestatus{XML}{MathML element "reln" is obsolete}
-\stopxmlsetups
-
-% fn
-
-% plusminus ±
-
-\startxmlsetups mmc:fn:\utfchar{"00B1}
- \MMLdoL
- \xmlconcat{#1}{/[position()>1]}{\utfchar{"00B1}}
- \MMLdoR
-\stopxmlsetups
-
-% minusplus
-
-\startxmlsetups mmc:fn:\utfchar{"2213}
- \MMLdoL
- \xmlconcat{#1}{/[position()>1]}{\utfchar{"2213}}
- \MMLdoR
-\stopxmlsetups
-
-\startxmlsetups mmc:fn
- \begingroup
- \edef\mmlnoffn{\xmlcount{#1}{/*}}
- \ifnum\mmlnoffn>\plustwo
- \def\MMCfnleft {\left(}
- \def\MMCfnright{\right)}
- \else
- \let\MMCfnleft \relax
- \let\MMCfnright\relax
- \fi
- \xmldoifelse {#1} {/mml:ci} { % first
- \edef\mmlfnci{\xmltext{#1}{/mml:ci}}% was xmlcontent
- \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:...
- \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
- } {
- \MMLcreset
- \mmlfirst{#1}
- }
- } {
- \xmldoifelse {#1} {/mml:apply} { % first
- \xmldoifelse {#1} {/(mml:plus\string|mml:minus)} {
- \left(\mmlfirst{#1}\right)
- } {
- \mmlfirst{#1}
- }
- \ifnum\mmlnoffn>\plusone
- \left(\xmlall{#1}{/!mml:apply}\right)
- \fi
- } {
- \MMLcreset
- \negthinspace
- \MMCfnleft
- \ifnum\mmlnoffn=\plustwo,\fi
- \xmlconcat{#1}{/*}{2}{}{\MMLseparator,}
- \MMCfnright
- }
- }
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mmc:fn:apply % where used?
- \xmldoifelse {#1} {/mml:ci} { % first
- \edef\mmlfnci{\xmltext{#1}{/mml:ci}}% was xmlcontent
- \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:...
- \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
- } {
- \MMLcreset
- \mmlfirst{#1}
- \ifnum\xmlcount{#1}{/*}>\plusone
- \negthinspace
- \left(\MMLcreset\xmlconcat{#1}{2}{}{\MMLseparator,}\right)
- \fi
- }
- } {
- \endgroup
- \MMLcreset
- \mmlfirst{#1}
- }
-\stopxmlsetups
-
-%D The next definition provide a kind of plug-in mechanism (see
-%D the open math extension module).
-
-% http://www.publishers.com/somename
-%
-% called at the lua end
-
-\starttexdefinition mmlapplycsymbol #1#2#3#4
- % #1=full url, #2=name, #3=encoding, #4=text
- \doifelse {#3} {text} {
-% {\mr #4}
- \text{#4}
- } {
- \doifsetupselse {mml:csymbol:#1} {
- % full url
- \directsetup{mml:csymbol:#1}
- } {
- % somename (fallback)
- \doifsetupselse {mml:csymbol:#2} {
- \directsetup{mml:csymbol:#2}
- } {
- \xmlval{mmc:cs}{#3}{}% todo
- }
- }
- }
-\stoptexdefinition
-
-\startxmlsetups mml:csymbol
- \ctxmodulemathml{csymbol("#1")}
-\stopxmlsetups
-
-\startxmlsetups mml:csymbol:cdots
- \cdots
-\stopxmlsetups
-
-% \startxmlsetups mml:csymbol:<url> \stopxmlsetups
-
-%D Alternative b will convert periods into comma's:
-
-\setupMMLappearance[cn] [\c!alternative=\v!a]
-\setupMMLappearance[polar] [\c!alternative=\v!a] % a|b|c
-\setupMMLappearance[float] [\c!symbol=\v!no] % \v!yes|dot
-\setupMMLappearance[enotation][\c!symbol=\v!no] % \v!yes|dot
-\setupMMLappearance[base] [\c!symbol=\v!numbers] % digits|characters|text|no
-
-\startxmlsetups mml:cs \xmlcommand{#1}{/}{mml:cs:\xmlattdef{#1}{type}{default}} \stopxmlsetups
-\startxmlsetups mml:ci \xmlcommand{#1}{/}{mml:ci:\xmlattdef{#1}{type}{default}} \stopxmlsetups
-\startxmlsetups mml:cn \xmlcommand{#1}{/}{mml:cn:\xmlattdef{#1}{type}{default}} \stopxmlsetups
-
-% helpers cn / todo: \mn{...}
-
-\startxmlsetups mml:cn:default
- \mathopnolimits{\xmlflush{#1}}
-\stopxmlsetups
-
-% helpers ci
-
-\startxmlsetups mml:ci:default
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:set
- {\blackboard{\xmlflush{#1}}} % todo
-\stopxmlsetups
-
-\startxmlsetups mml:ci:vector
- \widevec{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:matrix
- {\bi\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:function
- \xmlflush{#1}% \negthinspace
-\stopxmlsetups
-
-\startxmlsetups mml:ci:fn
- \xmlsetup{#1}{mml:ci:function}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:complex-cartesian
- \xmlsetup{#1}{mml:cn:complex}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:complex
- \xmlsetup{#1}{mml:cn:complex}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:complex-polar
- \xmlsetup{#1}{mml:cn:polar}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:polar
- \xmlsetup{#1}{mml:cn:polar}
-\stopxmlsetups
-
-% helpers ci
-
-\startxmlsetups mml:cn:default
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:integer
- \edef\mmlintegerbase{\xmlattdef{#1}{base}{}}
- \ifx\mmlintegerbase\empty
- \xmlflush{#1}
- \else
- \doifelse \MMLbasesymbol \v!no {
- \MMLcCNbasedata{\xmlflush{#1}}
- } {
- \MMLcCNbasedata{\xmlflush{#1}}\normalsubscript{
- \hbox {\startimath
- \mr
- \scriptscriptstyle
- \processaction
- [\MMLbasesymbol]
- [\v!characters=>\MMLcCNbasestring BODH,
- \v!text=>\MMLcCNbasestring{BIN}{OCT}{DEC}{HEX},
- \s!unknown=>\mmlintegerbase]
- \stopimath}
- }
- }
- \fi
-\stopxmlsetups
-
-\def\MMLcCNbasedata#1%
- {\ifnum\mmlintegerbase>10 \relax{\mr#1}\else#1\fi}
-
-\def\MMLcCNbasestring#1#2#3#4%
- {\ifnum\mmlintegerbase= 2 #1\else
- \ifnum\mmlintegerbase= 8 #2\else
- \ifnum\mmlintegerbase=10 #3\else
- \ifnum\mmlintegerbase=16 #4\else
- \mmlintegerbase \fi\fi\fi\fi}
-
-\startxmlsetups mml:cn:polar
- \xmlsetup{#1}{mml:cn:polar:\MMLpolaralternative}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:polar:a
- \ctxmodulemathml{cpolar_a("#1")}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:polar:b
- {\mr e}\normalsuperscript{\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:polar:c
- \exp\left(\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}\right)
-\stopxmlsetups
-
-\startxmlsetups mml:cn:complex-polar
- \xmlsetup{#1}{mml:cn:polar}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:complex % todo ( )
- \left(\xmlsnippet{#1}{1} + \xmlsnippet{#1}{3}\thinspace{\mr i}\right)
-\stopxmlsetups
-
-\startxmlsetups mml:cn:complex-cartesian
- \xmlsetup{#1}{mml:cn:complex}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:float
- \doifelse \MMLfloatsymbol \v!no {
- % make sure that e shows up ok
- \mathopnolimits{\xmlflush{#1}}
- } {
- % we should ignore \entities !
- \edef\mmlfloatstring{\xmlflush{#1}}
- \splitstring\mmlfloatstring\at e\to\first\and\last
- \ifx\first\empty
- \mmlfloatstring
- \else\ifx\last\empty
- \mmlfloatstring
- \else
- \first
- \doifelse \MMLfloatsymbol {dot} \cdot \times
- 10\normalsuperscript{\last}
- \fi \fi
- }
-\stopxmlsetups
-
-\startxmlsetups mml:cn:real
- \xmlsetup{#1}{mml:cn:float}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:e-notation
- \doifelse \MMLenotationsymbol \v!no {
- \xmlsnippet{#1}{1}
- \unskip\mathopnolimits{e}\ignorespaces
- \xmlsnippet{#1}{3}
- } {
- \xmlsnippet{#1}{1}
- \doifelse \MMLenotationsymbol {dot} \cdot
- \times10\normalsuperscript{\xmlsnippet{#1}{3}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:cn:logical
- \mathopnolimits{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:rational
- \xmldoifelse {#1} {/mml:sep} {
- \frac
- {\xmlsnippet{#1}{1}}
- {\xmlsnippet{#1}{3}}
- } {
- \xmlflush{#1}
- }
-\stopxmlsetups
-
-% interval
-
-\setupMMLappearance[interval][\c!alternative=\v!a,\c!separator={,}]
-
-% when empty element, then it's an apply
-
-\startxmlsetups mml:interval
- \doifelse {\xmltag{#1}} {apply} {
- % #1 == apply
- \let\mmlintervalfirst \mmlsecond
- \let\mmlintervalsecond\mmlthird
- \xmlsetup{#1}{mml:interval:\xmlattributedef{#1}{/mml:interval}{closure}{closed}}
- } {
- % #1 == interval
- \let\mmlintervalfirst \mmlfirst
- \let\mmlintervalsecond\mmlsecond
- \xmlsetup{#1}{mml:interval:\xmlattdef{#1}{closure}{closed}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:interval:closed
- \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
-\stopxmlsetups
-
-\startxmlsetups mml:interval:open-closed
- \doifelse \MMLintervalalternative \v!b {
- \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
- } {
- \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
- }
-\stopxmlsetups
-
-\startxmlsetups mml:interval:closed-open
- \doifelse \MMLintervalalternative \v!b {
- \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right>
- } {
- \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right)
- }
-\stopxmlsetups
-
-\startxmlsetups mml:interval:open
- \doifelse \MMLintervalalternative \v!b {
- \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right>
- } {
- \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right)
- }
-\stopxmlsetups
-
-% inverse
-
-\setfalse\xmlinversefunction
-
-\startxmlsetups mml:apply:inverse
- \settrue\xmlinversefunction
- \xmlsetup{#1}{mml:\xmlfilter{#1}{/mml:apply/*[2]/name()}}
-\stopxmlsetups
-
-% condition
-
-% maybe a fast \xmlnonfirst
-
-% instead of the following we could do \xmlcontent{#1}{/mml:bvar} etc
-
-\startxmlsetups mml:bvar \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:lowlimit \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:uplimit \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:degree \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:logbase \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:fn \xmlflush{#1} \stopxmlsetups
-
-\startxmlsetups mml:condition
-% \xmldoif {#1} {/mml:bvar} {
-% \xmlfirst{#1}{/mml:bvar}\mid
-% }
- \xmlall{#1}{/!(mml:condition\string|mml:bvar)}
-\stopxmlsetups
-
-% declare
-
-\setupMMLappearance[declare][\c!state=\v!start]
-
-\startxmlsetups mml:declare
- \doif \MMLdeclarestate \v!start {
- \mathopnolimits{declare}
- \mmlfirst{#1}
- \ifnum\xmlcount{#1}{/*}>\plusone
- \thickspace
- \mathopnolimits{as}
- \thickspace
- \fi
- \mmlsecond{#1}
- }
-\stopxmlsetups
-
-% lambda
-
-\setupMMLappearance[lambda][\c!alternative=b]
-
-\startxmlsetups mml:lambda
- \begingroup
- \doifelse \MMLlambdaalternative \v!a {
- \lambda\left(\xmlconcat{#1}{/!mml:lambda}{\MMLseparator,}\right)
- } {
- \ifnum\xmlcount{#1}{/mml:bvar}>\plusone
- \left(\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}\right)
- \else
- \xmlfirst{#1}{/mml:bvar}
- \fi
- \mapsto
- \MMLcreset
- \xmlall{#1}{/!(mml:bvar|mml:lambda)}
- }
- \endgroup
-\stopxmlsetups
-
-% compose
-
-\startxmlsetups mml:compose
- \begingroup
- \MMLcreset
-% \let\MMLcCIfunction\firstofoneargument % brrr ? ? ?
- \doifelsemmlfunction {#1} {
- \left(\xmlconcat{#1}{/!mml:compose}{\circ}\right)
- } {
- \xmlconcat{#1}{/!mml:compose}{\circ}
- }
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:image
- \mathopnolimits{image} \left( {\mr\xmlfilter{#1}{/!mml:image/tag()}} \right)
-\stopxmlsetups
-
-\setupMMLappearance[piece][\c!separator=]
-
-\startxmlsetups mml:piecewise
- \processaction
- [\MMLpieceseparator]
- [ \v!yes=>\def\theMMLpieceseparator{,&},
- \v!no=>\def\theMMLpieceseparator{&},
- \s!default=>\def\theMMLpieceseparator{&},
- \s!unknown=>\def\theMMLpieceseparator{\,\,\hbox{\MMLpieceseparator}\,\,}]
- \cases{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:piece
- \mmlfirst{#1}\theMMLpieceseparator\mathematics{\mmlsecond{#1}}\crcr
-\stopxmlsetups
-
-\startxmlsetups mml:otherwise
-% \xmlflush{#1}\MMLcPIECEseparator&{\mr otherwise}\crcr
- \xmlflush{#1}&{\mr otherwise}\crcr
-\stopxmlsetups
-
-% end of piece
-
-\startxmlsetups mml:quotient
- \lfloor\mmlsecond{#1}/\mmlthird{#1}\rfloor
-\stopxmlsetups
-
-\startxmlsetups mml:factorial
- \xmlall{#1}{/!factorial}!
-\stopxmlsetups
-
-\setupMMLappearance [divide] [\c!level=\!!maxcard,\c!alternative=\v!a]
-
-\newcount\mmldividelevel
-
-\startxmlsetups mml:divide
- \advance\mmldividelevel\plusone
- \doifelse \MMLdividealternative \v!b {
- \mmlsecond{#1}/\mmlthird{#1}
- } {
- \ifnum \mmldividelevel > \MMLdividelevel \relax % threshold
- \mmlsecond{#1}/\mmlthird{#1}
- \else
- \MMLcreset
- \frac{\MMLcreset\mmlsecond{#1}}{\MMLcreset\mmlthird{#1}}
- \fi
- }
- \advance\mmldividelevel\minusone
-\stopxmlsetups
-
-% min max
-
-\startxmlsetups mml:min \mathopnolimits{min} \xmlsetup{#1}{mml:minmax} \stopxmlsetups
-\startxmlsetups mml:max \mathopnolimits{max} \xmlsetup{#1}{mml:minmax} \stopxmlsetups
-
-\startxmlsetups mml:minmax
- \xmldoif {#1} {/mml:bvar} {
- {}\normalsubscript{\xmlfirst{#1}{/mml:bvar}}
- }
- \left\{
- \xmlconcat{#1}{/!(mml:bvar\string|mml:max\string|mml:min)}{\MMLseparator,}
- \right\}
-\stopxmlsetups
-
-% minus plus
-
-\setupMMLappearance [plus] [\c!alternative=\v!a] % b = no sign -> 3 1/4
-\setupMMLappearance [sign] [\c!reduction=\v!yes]
-
-% alternative b -> geen sign
-
-% branch needed, else (a-b) + (c-d) goes wrong
-% reset check in case of (-x) + 37
-% reset check in case of (-x) + 37
-
-\newcount\mmlpluscounter
-
-\startxmlsetups mml:plus
- \doifelse \MMLsignreduction \v!yes {
- \MMLdoL
- \xmlsetup{#1}{mml:plus:reset}
- \xmlcommand{#1}{/!mml:plus}{mml:plus:body}
- \MMLdoR
- } {
- \ifnum\xmlcount{#1}{/!mml:plus}=\plusone
- +\xmlfirst{#1}{/!mml:plus}
- \else
- \MMLdoL
- \xmlconcat{#1}{/!mml:plus}{+}
- \MMLdoR
- \fi
- }
-\stopxmlsetups
-
-\startxmlsetups mml:plus:reset
- \mmlpluscounter\zerocount
-\stopxmlsetups
-
-\startxmlsetups mml:plus:body
- \advance\mmlpluscounter\plusone
- \ifnum\mmlpluscounter>\plusone
- \xmldoifelse{#1}{/mml:minus} {
- \ifnum\xmlcount{#1}{/!mml:minus}>\plusone
- +
- \fi
- } {
- \doifelse {\xmlatt{#1}{type}} {rational} {
- % fraction
- } {
- +
- }
- }
- \fi
- \xmldirect{#1}
-\stopxmlsetups
-
-\newcount\mmlminuscounter
-
-\startsetups mml:minus
- \doifelse \MMLsignreduction \v!yes {
- \ifnum\xmlcount{#1}{/!mml:minus}=\plusone
- -\xmlfirst{#1}{/!mml:minus}
- \else
- \MMLdoL
- \xmlsetup{#1}{mml:minus:reset}
- \xmlcommand{#1}{/!mml:minus}{mml:minus:body}
- \MMLdoR
- \fi
- } {
- \left( % \MMLdoL
- \ifnum\xmlcount{#1}{/!mml:minus}=\plusone
- -\xmlfirst{#1}{/!mml:minus}
- \else
- \xmlsetup{#1}{mml:minus:reset}
- \xmlcommand{#1}{/!mml:minus}{mml:minus:body}
- \fi
- \right) % \MMLdoR
- }
-\stopsetups
-
-\startxmlsetups mml:minus:reset
- \mmlminuscounter\zerocount
-\stopxmlsetups
-
-\startxmlsetups mml:minus:body
- % we can slso use concat here
- \advance\mmlminuscounter\plusone
- \ifnum\mmlminuscounter>\plusone
- -
- \fi
- \xmldirect{#1}
-\stopxmlsetups
-
-% power
-
-\setupMMLappearance[power][\c!reduction=\v!yes]
-
-\let\MMLpowerelement\empty
-
-\startxmlsetups mml:power
- \xmldoifelse {#1} {/mml:apply} {
- \doifelse \MMLpowerreduction \v!yes {
- \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist)} {
- \gdef\MMLpowerelement{\mmlthird{#1}}% postpone, no xdef
- \MMLcreset\mmlsecond{#1}
- } {
- \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}}
- }
- } {
- \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}}
- }
- } {
- \mmlsecond{#1}\normalsuperscript{\MMLcreset\mmlthird{#1}}
- }
-\stopxmlsetups
-
-% rem
-
-\startxmlsetups mml:rem
- \xmlconcat{#1}{/!mml:rem}{\mathopnolimits{mod}}
-\stopxmlsetups
-
-\setupMMLappearance [times] [\c!symbol=\v!no,\c!auto=\v!yes] % new, auto catches cn cn cn
-
-\startxmlsetups mml:times
- \setMMLcreset{\MMLcfunctionlist\string|\MMLcconstructlist}%
- \doifelse\MMLtimesauto\v!no {
- \let\MMLtimes@@symbol\MMLtimessymbol
- } {
- \xmldoifelse {#1} {/mml:cn[name(1) == 'mml:cn']} {% name(1) is next one
- \doifinsetelse\MMLtimessymbol{\v!yes,\v!no} {
- \let\MMLtimes@@symbol\v!yes
- } {
- \let\MMLtimes@@symbol\MMLtimessymbol
- }
- } {
- \let\MMLtimes@@symbol\MMLtimessymbol
- }
- }
- \doifelse\MMLtimes@@symbol\v!yes {
- \xmlconcat{#1}{/!mml:times}{\times}
- } {
- \doifelse\MMLtimes@@symbol{dot} {
- \xmlconcat{#1}{/!mml:times}{\cdot}
- } {
- \doifelse\MMLtimes@@symbol{times} {
- \xmlconcat{#1}{/!mml:times}{\times}
- } {
- \xmlall{#1}{/!mml:times}
- }
- }
- }
-\stopxmlsetups
-
-\setupMMLappearance[root][\c!symbol=\v!yes]
-
-\startxmlsetups mml:root
- \xmldoifelse {#1} {/mml:degree} {
- \root
- \doifnot\MMLrootsymbol\v!no{\MMLcreset\xmltext{#1}{/mml:degree}}
- \of
- } {
- \sqrt
- }
- {\MMLcreset\xmlall{#1}{/!(mml:degree\string|mml:root)}}
-\stopxmlsetups
-
-% gcd
-
-\startxmlsetups mml:gcd
- \begingroup
- \gcd\left(\MMLcreset\xmlconcat{#1}{/!mml:gcd}{\MMLseparator,}\right)
- \endgroup
-\stopxmlsetups
-
-% and or xor implies, not
-
-\startxmlsetups mml:and \xmlconcat{#1}{/!mml:and} {\wedge} \stopxmlsetups
-\startxmlsetups mml:or \xmlconcat{#1}{/!mml:or} {\vee} \stopxmlsetups
-\startxmlsetups mml:xor \xmlconcat{#1}{/!mml:xor} {\mathopnolimits{xor}} \stopxmlsetups
-\startxmlsetups mml:implies \xmlconcat{#1}{/!mml:implies}{\Rightarrow} \stopxmlsetups
-\startxmlsetups mml:not \neg \xmlall {#1}{/!mml:not} \stopxmlsetups
-
-% forall exists
-
-%D We need to shift left below rotated A.
-
-\startxmlsetups mml:forall
- \forall \negthinspace \xmlsetup{#1}{mml:forallexists}
-\stopxmlsetups
-
-\startxmlsetups mml:exists
- \exists \xmlsetup{#1}{mml:forallexists}
-\stopxmlsetups
-
-\def\mmlforallexistslist{mml:bvar\string|mml:forall\string|mml:exists\string|mml:condition}
-
-\startxmlsetups mml:forallexists
- \normalsubscript{\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}}
- \xmldoifelse {#1} {/mml:condition} {
- \thickspace
- \begingroup
- \xmlfirst{#1}{/mml:condition}
- \endgroup
- \ifcase\xmlcount{#1}{/!(\mmlforallexistslist)}\relax
- % nothing
- \or
- % == snelle volgende
- \left\vert
- \MMLcreset \medspace \xmlconcat{#1}{/!(\mmlforallexistslist)}{}
- \right.
- \else
- % special case
- \left\vert
- \matrix {
- \xmlconcat{#1}{/!(\mmlforallexistslist)}{\hfill\crcr}
- }
- \right.
- \fi
- } {
- :\xmlfirst{#1}{/!(\mmlforallexistslist)}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:abs
- \left\vert \MMLcreset\xmlall{#1}{/!mml:abs} \right\vert
-\stopxmlsetups
-
-\startxmlsetups mml:conjugate % watch extra {}
- {\overline{\MMLcreset\xmlall{#1}{/!mml:conjugate}}}
-\stopxmlsetups
-
-\startxmlsetups mml:arg
- \mathopnolimits{arg} \left( \MMLcreset\xmlall{#1}{/!mml:arg} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:real
- \Re \left( \MMLcreset \xmlall{#1}{/!mml:real} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:imaginary
- \Im \ left( \MMLcreset \xmlall{#1}{/!mml:imaginary} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:lcm
- \mathopnolimits{lcm} \left( \xmlconcat{#1}{/!mml:lcm}{\MMLseparator,} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:floor
- \lfloor \xmlall{#1}{/!mml:floor} \rfloor
-\stopxmlsetups
-
-\startxmlsetups mml:ceiling
- \lceiling \xmlall{#1}{/!mml:ceiling} \rceiling
-\stopxmlsetups
-
-% relations
-
-% apply attr or eq
-
-\setupMMLappearance[relation][\c!align=\v!no]
-
-\xmlmapvalue {mml:relation} {eq} {=}
-\xmlmapvalue {mml:relation} {neq} {\neq}
-\xmlmapvalue {mml:relation} {gt} {>}
-\xmlmapvalue {mml:relation} {lt} {<}
-\xmlmapvalue {mml:relation} {geq} {\geq}
-\xmlmapvalue {mml:relation} {leq} {\leq}
-\xmlmapvalue {mml:relation} {equivalent} {\equiv}
-\xmlmapvalue {mml:relation} {approx} {\approx}
-\xmlmapvalue {mml:relation} {factorof} {\mid}
-
-\startxmlsetups mml:eq \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:neq \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:gt \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:lt \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:geq \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:leq \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:equivalent \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:approx \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:factorof \xmlsetup{#1}{mml:relation} \stopxmlsetups
-
-\startxmlsetups mml:relation
- \edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}}
- \MMLcreset \xmlsetup{#1}{mml:relation:\xmlattdef{#1}{align}{\MMLrelationalign}}
-\stopxmlsetups
-
-\startxmlsetups mml:relation:default
- \xmlconcatrange{#1}{/*}{2}{}{\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}}
-\stopxmlsetups
-\startxmlsetups mml:relation:last
- \eqalign {
- \xmlconcatrange{#1}{/*}{2}{-2}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
- \mmlprelast{#1}&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}\mmllast{#1}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:first
- \eqalign {
- \mmlsecond{#1}\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}
- &\xmlconcatrange{#1}{/*}{3}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:left
- \eqalign {
- \xmlconcatrange{#1}{/*}{2}{}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:right
- \eqalign {
- &\xmlconcatrange{#1}{/*}{2}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:no
- \xmlsetup{#1}{mml:relation:default}
-\stopxmlsetups
-\startxmlsetups mml:relation:yes
- \xmlsetup{#1}{mml:relation:left}
-\stopxmlsetups
-
-% personal goody:
-
-\edef\MMLcmainresetlist{\MMLcmainresetlist\string|becomes}
-
-\xmlmapvalue {mml:relation} {mml:becomes} {:=}
-
-\startxmlsetups mml:becomes \xmlsetup{#1}{mml:relation} \stopxmlsetups
-
-% calculus and vector calculus
-
-\startxmlsetups mml:domainofapplication
- \xmlall{#1}{/!mml:domainofapplication}
-\stopxmlsetups
-
-\setupMMLappearance[int][\c!location=\v!top]
-
-\def\doMMLlimits#1{\doifelsevalue{MML#1\c!location}\v!top\limits\nolimits}
-
-\startxmlsetups mml:int
- \MMLcreset
- \xmldoifelse {#1} {/mml:domainofapplication} {
- \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:domainofapplication}}\relax
- } {
- \xmldoifelse {#1} {/mml:condition} {
- \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:condition}}\relax
- } {
- \xmldoifelse {#1} {/mml:lowlimit} {
- \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:lowlimit}}\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}
- } {
- % funny, why do we have lowlimit/uplimit then
- \xmldoifelse {#1} {/mml:apply/mml:interval} {
- \int \doMMLlimits{int}\normalsubscript{\xmlindex{#1}{/mml:apply}{2}}\normalsuperscript{\xmlindex{#1}{/mml:apply}{3}}
- } {
- \int
- }
- }
- }
- }
- \MMLcreset
- \xmldoifelse {#1} {/mml:apply} {
- \doifelsemmlfunction {#1} { % todo test
- \xmlfirst{#1}{/mml:apply}
- } {
- % if there are too many () now, we need to be more clever
- \left( \xmlfirst{#1}{/mml:apply} \right)
- }
- } {
- \xmlfirst{#1}{/mml:ci}
- }
- \xmldoifelse {#1} {/mml:bvar} {
- \thinspace {\mr d} \xmlfirst{#1}{/mml:bvar}
- } {
- % nothing
- }
-\stopxmlsetups
-
-\setupMMLappearance[diff][\c!location=\v!top,\c!alternative=\v!a]
-
-\startxmlsetups mml:diff
- \MMLcreset
- \doifelse \MMLdiffalternative \v!a {
- \xmldoifelse {#1} {/mml:lambda} {
- % a special case (mathadore/openmath)
- \frac {
- d
- \normalsuperscript
- {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
- {\xmlfirst{#1}{/mml:lambda}\xmlfirst{#1}{/mml:ci}}
- } {
- d
- {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:ci}}
- \normalsuperscript
- {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
- }
- } {
- \xmldoifelse {#1} {/mml:bvar} {
- \frac {
- {\mr d}{
- \xmldoifelse {#1} {/mml:degree} {
- \normalsuperscript{\xmlconcat{#1}{/mml:degree}\empty}
- } {
- \xmldoif {#1} {/mml:bvar/mml:degree} {
- \normalsuperscript{\xmlconcat{#1}{/mml:bvar/mml:degree}+}
- }
- }
- }
- \doif \MMLdifflocation \v!top {
- \xmldoifelse {#1} {/mml:ci} {
- \xmlfirst{#1}{/mml:ci}
- } {
- \MMLcreset
-\ifnum\xmlcount{#1}{/mml:apply/*}>\plustwo % hack
- \left(
- \xmlfirst{#1}{/mml:apply}
- \right)
-\else
- \xmlfirst{#1}{/mml:apply}
-\fi
- }
- }
- } {
- {\mr d}
- \xmlfirst{#1}{/mml:bvar/!mml:degree}
- \xmldoif {#1} {/mml:bvar/mml:degree} {
- \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}}
- }
- }
- \doifnot \MMLdifflocation \v!top {
- \left(\MMLcreset\xmlfirst{#1}{/(mml:apply\string|mml:ci)}\right)
- }
- } {
- % beware, the second {} is needed for the superscript
- \xmlconcatrange{#1}{/*}{2}{}{}\normalsuperscript\prime
- }
- }
- } {
- \MMLcreset
- \xmlfirst{#1}{/(mml:apply\string|mml:ci)}
- % there can be problems with nested diff's: \normalsuperscript\normalsuperscript{} error
- % so we add an empty group here
- {}\normalsuperscript
- {
- \xmldoifelse {#1} {/mml:degree} {
- \edef\mmldegree{\xmlfirst{#1}{/mml:degree/mml:cn}}
- \ifx\mmldegree\empty
- % what to do here
- \else
- \dorecurse\mmldegree\prime
- \fi
- } {
- \prime
- }
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:partialdiff
- \xmldoifelse {#1} {/mml:list} {
- {\mr D}\normalsubscript{
- \begingroup
- \setfalse\mmllistdelimiters
- \xmlall{#1}{/mml:list}
- \endgroup
- }
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- } {
- \xmldoifelse {#1} {/mml:bvar} {
- \frac {
- {\mr d}\normalsuperscript{
- \xmldoifelse {#1} {/mml:degree} {
- \xmlconcat{#1}{/mml:degree}\empty
- } {
- \xmlconcat{#1}{/mml:bvar/mml:degree}+
- }
- }
- \MMLcreset
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- } {
- \xmldoif {#1}{/mml:bvar/!mml:degree} {
- \xmlfirst{#1}{/mml:bvar/!mml:degree} \,
- }
- {\mr d}\xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- \xmldoif {#1} {/mml:bvar/mml:degree} {
- \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}}
- }
- }
- } {
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:divergence \mathopnolimits{div} \xmlall{#1}{/!mml:divergence} \stopxmlsetups
-\startxmlsetups mml:grad \mathopnolimits{grad} \xmlall{#1}{/!mml:grad} \stopxmlsetups
-\startxmlsetups mml:curl \mathopnolimits{curl} \xmlall{#1}{/!mml:curl} \stopxmlsetups
-\startxmlsetups mml:laplacian \nabla\normalsuperscript2 \xmlall{#1}{/!mml:laplacian} \stopxmlsetups
-\startxmlsetups mml:ident \mathopnolimits{identity} \xmlall{#1}{/!mml:ident} \stopxmlsetups
-
-\setupMMLappearance[domain] [symbol=]
-\setupMMLappearance[codomain][symbol=]
-
-\startxmlsetups mml:domain
- \doifelsenothing \MMLdomainsymbol {
- \mathopnolimits{domain}\MMLcreset\xmlall{#1}{/!mml:domain}
- } {
- \MMLdomainsymbol\normalsubscript{\xmlall{#1}{/!mml:domain}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:codomain
- \doifelsenothing \MMLcodomainsymbol {
- \mathopnolimits{codomain}\MMLcreset\xmlall{#1}{/!mml:codomain}
- } {
- \MMLcodomainsymbol\normalsubscript{\xmlall{#1}{/!mml:codomain}}
- }
-\stopxmlsetups
-
-% theory of sets
-
-\startxmlsetups mml:set
- \left\{
- \xmldoifelse {#1} {/mml:condition} {
- \xmlfirst{#1}{/mml:bvar}\,\middle\vert\,\xmlfirst{#1}{/mml:condition}
- } {
- \xmlconcat{#1}{/!mml:set}{\MMLseparator,}
- }
- \right\}
- \relax % needed
-\stopxmlsetups
-
-\settrue\mmllistdelimiters
-
-\startxmlsetups mml:list
- \begingroup
- \ifconditional\mmllistdelimiters\left [\fi
- \begingroup
- \settrue\mmllistdelimiters
- \xmlconcat{#1}{/!mml:list}{\MMLseparator,}
- \endgroup
- \ifconditional\mmllistdelimiters\right]\fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:union \mmlsecond{#1} \cup \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:intersect \mmlsecond{#1} \cap \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:in \mmlsecond{#1} \in \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:notin \mmlsecond{#1} {\not\in} \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:subset \mmlsecond{#1} \subset \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:prsubset \mmlsecond{#1} \subseteq \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:notsubset \mmlsecond{#1} {\not\subset} \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:notprsubset \mmlsecond{#1} {\not\subseteq} \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:setdiff \mmlsecond{#1} \setminus \mmlthird{#1} \stopxmlsetups
-
-\startxmlsetups mml:card
- \left\vert \xmlall{#1}{/!mml:card} \right\vert
-\stopxmlsetups
-
-\startxmlsetups mml:cartesianproduct
- \xmlconcat{#1}{/!mml:cartesianproduct}{\times}
-\stopxmlsetups
-
-% sequences and series
-
-\setupMMLappearance[sum] [\c!location=\v!top]
-\setupMMLappearance[product][\c!location=\v!top]
-
-\xmlmapvalue {mml:sumprod} {sum} {\sum}
-\xmlmapvalue {mml:sumprod} {product} {\prod}
-
-\startxmlsetups mml:sum \edef\mmlsumprodname{sum} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups
-\startxmlsetups mml:product \edef\mmlsumprodname{product} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups
-
-\def\mmlstackedsubscripts#1%
- {\vbox
- {\baselineskip\zeropoint % hack, taco vragen
- \halign{\startimath\scriptstyle\hss\alignmark\alignmark\hss\stopimath\cr#1\crcr}}}
-
-% unfinished
-
-\startxmlsetups mml:sumprod
- \begingroup
- \xmldoifelse {#1} {/(mml:condition\string|mml:bvar\string|mml:lowlimit)} {
- \def\mmlsumprodlower{
- \normalsubscript{
- \xmldoifelse {#1} {/mml:condition} {
- \mmlstackedsubscripts{\xmlconcat{#1}{/mml:condition}{\crcr}}
- } {
- \xmldoif {#1} {/mml:bvar} {
- \xmlfirst{#1}{/mml:bvar}
- \xmldoif{#1}{/mml:lowlimit}{=}
- }
- \xmlfirst{#1}{/mml:lowlimit}
- }
- }
- }
- } {
- \let\mmlsumprodlower\empty
- }
- \xmldoifelse {#1} {/mml:uplimit} {
- \def\mmlsumprodupper{\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}}
- } {
- \let\mmlsumprodupper\empty
- }
- \xmldoif {#1} {/mml:interval} { % open math converter gives this
- \edef\mmlintervalfrom{\xmlindex{#1}{/mml:interval}{1}}
- \edef\mmlintervalto {\xmlindex{#1}{/mml:interval}{2}}
- \ifx \mmlintervalfrom \empty \else
- \def\mmlsumprodlower{\normalsubscript{\xmldoif{#1}{/mml:bvar}{\xmlfirst{#1}{/mml:bvar}{=}}\mmlintervalfrom}}
- \fi
- \ifx \mmlintervalto \empty \else
- \def\mmlsumprodupper{\normalsuperscript{\mmlintervalto}}
- \fi
- }
- \MMLcreset
- \xmlval{mml:sumprod}{\mmlsumprodname}{}\doMMLlimits\mmlsumprodname\mmlsumprodupper\mmlsumprodlower
- \MMLcreset
- \xmldoifelse {#1} {/mml:lambda/mml:apply} {
- \xmlfirst{#1}{/mml:lambda/mml:apply}% a bit of open math conversion mess
- } {
- \xmlfirst{#1}{/(mml:apply\string|mml:lambda\string|mml:ci)}%
- }
- \endgroup
-\stopxmlsetups
-
-\setupMMLappearance[limit][\c!location=\v!top]
-
-\startxmlsetups mml:limit
- \MMLcreset \lim
- \doMMLlimits {limit}\normalsubscript{
- \MMLcreset
- \xmldoifelse {#1} {/mml:condition} {
- \xmlfirst{#1}{/mml:condition}
- } {
- \xmldoif {#1} {/mml:bvar} {
- \xmlfirst{#1}{/mml:bvar}\rightarrow
- }
- \xmlfirst{#1}{/mml:lowlimit}
- }
- }
- \begingroup
- % a bit of open math conversion mess, lambda needed for openmath, ok?
- \MMLcreset
- \xmlfirst{#1}{/mml:lambda/mml:apply}
- \xmlfirst{#1}{/(mml:apply\string|mml:lambda)}
- \endgroup
-\stopxmlsetups
-
-% consider a faster index
-
-\startxmlsetups mml:tendsto
- \MMLcreset \mmlsecond{#1}
- \xmlval {mml:tendsto:type} {\xmlattdef{#1}{type}{default}} {\rightarrow}
- \MMLcreset \mmlthird{#1}
-\stopxmlsetups
-
-\xmlmapvalue {mml:tendsto:type} {above} {\downarrow}
-\xmlmapvalue {mml:tendsto:type} {below} {\uparrow}
-\xmlmapvalue {mml:tendsto:type} {default} {\rightarrow}
-
-% elementary classical functions
-
-\setupMMLappearance[log][\c!location=\v!right]
-
-\startxmlsetups mml:exp
-% {\mr e}\normalsuperscript{\xmlfirst{#1}{/mml:apply\string|mml:reln\string|mml:ci\string|mml:cn}}
- {\mr e}\normalsuperscript{\xmlfirst{#1}{/!mml:exp}}
-\stopxmlsetups
-
-\startxmlsetups mml:log
- \xmldoifelse {#1} {/mml:logbase} {
- \doifelse \MMLloglocation \v!left {
- \mathop {
- {}\normalsuperscript{\xmlfirst{#1}{/mml:logbase}}\negthinspace\mathopnolimits{log}
- }
- } {
- \mathopnolimits{log}\normalsubscript{\xmlfirst{#1}{/mml:logbase}}
- }
-% \MMLcreset
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
-% \xmlsetup{#1}{mml:function} % todo, we start elsewhere
-% \mmlthird{#1}
- } {
- \mathopnolimits{log}
-% \MMLcreset
-% \xmlsetup{#1}{mml:function} % todo, we start elsewhere
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
-% \mmlsecond{#1}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:ln
- \mathopnolimits{ln}
- \xmlsetup{#1}{mml:function}
-\stopxmlsetups
-
-% statistics
-
-\startxmlsetups mml:mean \overline {\mmlsecond{#1}} \stopxmlsetups
-\startxmlsetups mml:sdev \sigma \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
-\startxmlsetups mml:variance \sigma \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript2 \stopxmlsetups
-\startxmlsetups mml:median \mathopnolimits{median}\left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
-\startxmlsetups mml:mode \mathopnolimits{mode} \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
-
-% moments
-
-\startxmlsetups mml:moment
- \left\langle
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}\normalsuperscript{\xmlfirst{#1}{/mml:degree}}
- \right\rangle
- \xmldoif {#1} {mml:momentabout} {
- \normalsubscript{\xmlfirst{#1}{mml:momentabout}}
- }
-\stopxmlsetups
-
-% linear algebra
-
-\setupMMLappearance [vector] [\c!direction=\v!horizontal,\c!separator={,}]
-
-\startxmlsetups mml:vector
- \begingroup
- \ifnum\xmlcount{#1}{/*}>\plusone
- \doifelse\MMLvectordirection\v!horizontal {
- \left(\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}\right)
- } {
- \MMLcreset\left(\matrix{\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}}\right)
- }
- \else
- \overrightarrow{\charhtstrut\mmlfirst{#1}}
- \fi
- \endgroup
-\stopxmlsetups
-
-\settrue\MMCdelmatrix % ( ) when true
-
-\startxmlsetups mml:matrix
- \begingroup
- \MMLcreset
- \ifconditional\MMCdelmatrix
- \left(\matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}\right)
- \else
- \settrue\MMCdelmatrix
- \matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}
- \fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:matrixrow
- \begingroup
- \MMLcreset
- \left(\xmlsetup{#1}{mml:matrixrow:do}\right)
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:matrixrow:do
- \xmlconcat{#1}{/*}{&}\crcr
-\stopxmlsetups
-
-\startxmlsetups mml:determinant
- \begingroup
- \setfalse\MMCdelmatrix
- \left|\mmlsecond{#1}\right|
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:transpose
- \mmlsecond{#1}\normalsuperscript{\mathopnolimits{T}}
-\stopxmlsetups
-
-\startxmlsetups mml:selector
- \MMLmathinner{\mmlsecond{#1}\normalsubscript{\MMLcreset\xmlconcatrange{#1}{/*}{3}{}{\MMLseparator,}}}
-\stopxmlsetups
-
-\startxmlsetups mml:vectorproduct \mmlsecond{#1}\times \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:scalarproduct \mmlsecond{#1}\cdot \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:outerproduct \mmlsecond{#1}\otimes\mmlthird{#1} \stopxmlsetups
-
-% semantic mapping elements
-
-\setupMMLappearance[semantics][\c!state=\v!start]
-
-\startxmlsetups mml:semantics
- \doifelse\MMLsemanticsstate\v!start {
- \xmlall{#1}{/mml:annotation}
- } {
- \xmlall{#1}{/!mml:annotation}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:annotation
- \xmldoifelse {#1} {.[oneof(@encoding,'TeX','tex','TEX','ConTeXt','context','CONTEXT','ctx')]} {
- \xmlflushcontext{#1}
- } {
- \xmldoifelse {#1} {.[oneof(@encoding,'calcmath','cm')]} {
- \expanded{\calcmath{\xmlflush{#1}}}
- } {
- \xmldoifelse {#1} {.[oneof(@encoding,'asciimath','am')]} {
- \ifdefined\asciimath
- \expanded{\asciimath{\xmlflush{#1}}}
- \else
- \hbox{\tt no am loaded}%
- \fi
- } {
- \xmlall{#1}{../!mml:annotation}
- }
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:annotation-xml
- % maybe diagnostics
-\stopxmlsetups
-
-% misc
-
-\startxmlsetups mml:integers \integers \stopxmlsetups
-\startxmlsetups mml:reals \reals \stopxmlsetups
-\startxmlsetups mml:rationals \rationals \stopxmlsetups
-\startxmlsetups mml:naturalnumbers \naturalnumbers \stopxmlsetups
-\startxmlsetups mml:complexes \complexes \stopxmlsetups
-\startxmlsetups mml:primes \primes \stopxmlsetups
-\startxmlsetups mml:exponentiale \mathopnolimits{e} \stopxmlsetups
-\startxmlsetups mml:imaginaryi \mathopnolimits{i} \stopxmlsetups
-\startxmlsetups mml:notanumber \mathopnolimits{NaN} \stopxmlsetups
-\startxmlsetups mml:true \mathopnolimits{true} \stopxmlsetups
-\startxmlsetups mml:false \mathopnolimits{false} \stopxmlsetups
-\startxmlsetups mml:emptyset \mathopnolimits{\O} \stopxmlsetups
-\startxmlsetups mml:pi \pi \stopxmlsetups
-\startxmlsetups mml:eulergamma \gamma \stopxmlsetups
-\startxmlsetups mml:infinity \infty \stopxmlsetups
-
-% gonio functions
-
-\setupMMLappearance[function][\c!reduction=\v!yes]
-
-% todo: \mfunction which adapts itself when registered as command
-
-% todo: \def\mmlcfunction#1#2{\mathopnolimits{#2}\xmlsetup{#1}{mml:function}}
-
-\startxmlsetups mml:sin \mathcommand {sin}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:sinh \mathcommand {sinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:cos \mathcommand {cos}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:cosh \mathcommand {cosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:tan \mathcommand {tan}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:tanh \mathcommand {tanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:cot \mathcommand {cot}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:coth \mathcommand {coth}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:csc \mathcommand {csc}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:csch \mathcommand {csch}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:sec \mathcommand {sec}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:sech \mathcommand {sech}\xmlsetup{#1}{mml:function} \stopxmlsetups
-
-\startxmlsetups mml:arcsin \mathcommand {arcsin}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arcsinh \mathcommand{arcsinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccos \mathcommand {arccos}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccosh \mathcommand{arccosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arctan \mathcommand {arctan}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arctanh \mathcommand{arctanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccot \mathcommand {arccot}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccoth \mathcommand{arccoth}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccsc \mathcommand {arccsc}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccsch \mathcommand{arccsch}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arcsec \mathcommand {arcsec}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arcsech \mathcommand{arcsech}\xmlsetup{#1}{mml:function} \stopxmlsetups
-
-\startxmlsetups mml:function
- \ifx\MMLpowerelement\empty
- \ifconditional\xmlinversefunction\normalsuperscript{-1}\fi
- \setfalse\xmlinversefunction
- \else
- \normalsuperscript{\ifconditional\xmlinversefunction-\fi\MMLpowerelement}
- \setfalse\xmlinversefunction
- \glet\MMLpowerelement\empty
- \fi
- \xmlsetup{#1}{mml:function:argument}
-\stopxmlsetups
-
-\startxmlsetups mml:function:argument
- \doifelse \MMLfunctionreduction \v!yes {
- \xmldoifelse {#1} {/mml:apply} {
- \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist\string|mml:divide)}
- \donefalse
- \donetrue
- } {
- \donefalse
- }
- } {
- \donetrue
- }
- % beware, we still flush from 2 up
- \ifdone
- \left(
- \MMLcreset
- \xmlall{#1}{/[position()>1]}% \xmlconcatrange{#1}{/*}{2}{}\empty
- \right)
- \else
- \MMLcreset
- \xmlall{#1}{/[position()>1]}
- \fi
-\stopxmlsetups
-
-% PRESENTATION MATHML
-%
-% there are some rough edges that need to be sorted out
-
-% helpers
-
-\xmlmapvalue {mml} {normal} {\tf}
-\xmlmapvalue {mml} {double-struck} {\bf}
-\xmlmapvalue {mml} {italic} {\it}
-\xmlmapvalue {mml} {fraktur} {\bf}
-\xmlmapvalue {mml} {script} {\tf}
-\xmlmapvalue {mml} {bold} {\bf}
-\xmlmapvalue {mml} {bold-italic} {\bi}
-\xmlmapvalue {mml} {bold-fraktur} {\bf}
-\xmlmapvalue {mml} {bold-script} {\bf}
-\xmlmapvalue {mml} {sans-serif} {\ss}
-\xmlmapvalue {mml} {bold-sans-serif} {\ss\bf}
-\xmlmapvalue {mml} {sans-serif-italic} {\ss\it}
-\xmlmapvalue {mml} {sans-serif-bold-italic} {\ss\bi}
-\xmlmapvalue {mml} {monospace} {\tt}
-
-% todo: displaystyle=true/false (or whatever else shows up)
-
-\starttexdefinition setmmlmathstyle #1
- \xmlval {mml} {\xmlatt{#1}{mathvariant}} \empty % was: \mmmr
-\stoptexdefinition
-
-\starttexdefinition applymmlmathcolor #1#2
- \edef\mmlmathcolor{\xmlatt{#1}{mathcolor}}
- \ifx \mmlmathcolor \empty
- #2
- \else
- \color[\mmlmathcolor]{#2}
- \fi
-\stoptexdefinition
-
-% todo: textbackgrounds
-
-\starttexdefinition applymmlmathbackground #1#2
- \edef\mmlmathbackground{\xmlatt{#1}{mathbackground}}
- \ifx \mmlmathbackground \empty
- #2
- \else
- \backgroundline[\mmlmathbackground]{#2}
- \fi
-\stoptexdefinition
-
-\newsignal\mmltextsignal % not used
-
-\starttexdefinition applymmlsometext #1#2
- \applymmlmathbackground {#1} {
- \applymmlmathcolor {#1} {
- \setmmlmathstyle {#1}
- #2
- }
- }
-\stoptexdefinition
-
-% probably bugged:
-
-\starttexdefinition doMMLfiller #1
- \pushmacro\doMMLfiller
- \let\doMMLfiller\gobbleoneargument
- \gdef\dodoMMLfiller{% where used
- \disablefiller
- \mathematics{#1}
- }
- \hbox {
- \def\normalorfiller##1##2{
- \gdef\dodoMMLfiller{\enablefiller#1}%
- \let\normalorfiller\gobbletwoarguments
- }
- \mathematics{#1}
- }
- \popmacro\doMMLfiller
-\stoptexdefinition
-
-% setups
-
-\startxmlsetups mml:mi % todo: mathvariant mathsize mathcolor mathbackground
- \ctxmodulemathml{mi("#1")}
-\stopxmlsetups
-
-\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground
-% \begingroup
-% \mr
- \ctxmodulemathml{mn("#1")}% no \hbox, would be ok for . , but spoils rest
-% \endgroup
-\stopxmlsetups
-
-% <m:mo>-</m:mo><m:mn>2</m:mn> and <m:mn>1</m:mn><m:mo>-</m:mo><m:mn>2</m:mn>
-%
-% spacing between - and 2 is taken care of by tex itself
-
-\startxmlsetups mml:mo
- \doif {\xmlatt{#1}{maxsize}} {1} {\settrue\mmlignoredelimiter}
- \doif {\xmlatt{#1}{stretchy}} {false} {\settrue\mmlignoredelimiter}
- \ctxmodulemathml{mo("#1")}
- \setfalse\mmlignoredelimiter
-\stopxmlsetups
-
-\startxmlsetups mml:mfenced % {} around separator is needed for spacing
- \def\MMLleft {\left }% weird
- \def\MMLright {\right}
- \def\MMLmiddle{\middle}
- \ctxmodulemathml{mfenced("#1")}
-\stopxmlsetups
-
-\defineoverlay [mml:enclose:box] [\useMPgraphic{mml:enclose:box}]
-\defineoverlay [mml:enclose:roundedbox] [\useMPgraphic{mml:enclose:roundedbox}]
-\defineoverlay [mml:enclose:circle] [\useMPgraphic{mml:enclose:circle}]
-\defineoverlay [mml:enclose:left] [\useMPgraphic{mml:enclose:left}]
-\defineoverlay [mml:enclose:right] [\useMPgraphic{mml:enclose:right}]
-\defineoverlay [mml:enclose:top] [\useMPgraphic{mml:enclose:top}]
-\defineoverlay [mml:enclose:bottom] [\useMPgraphic{mml:enclose:bottom}]
-\defineoverlay [mml:enclose:updiagonalstrike] [\useMPgraphic{mml:enclose:updiagonalstrike}]
-\defineoverlay [mml:enclose:downdiagonalstrike] [\useMPgraphic{mml:enclose:downdiagonalstrike}]
-\defineoverlay [mml:enclose:horizontalstrike] [\useMPgraphic{mml:enclose:horizontalstrike}]
-\defineoverlay [mml:enclose:verticalstrike] [\useMPgraphic{mml:enclose:verticalstrike}]
-
-\startuseMPgraphic{mml:enclose:box}
- draw OverlayBox withpen pencircle scaled (ExHeight/10) ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:roundedbox}
- draw OverlayBox cornered .5ExHeight withpen pencircle scaled (ExHeight/10) ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:circle}
- draw fullcircle xysized(bbwidth(OverlayBox),bbheight(OverlayBox)) withpen pencircle scaled (ExHeight/10) ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:left}
- draw leftboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:right}
- draw rightboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:top}
- draw topboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:bottom}
- draw bottomboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:updiagonalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw llcorner p -- urcorner p withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:downdiagonalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw ulcorner p -- lrcorner p withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:horizontalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw .5[llcorner p,ulcorner p] -- .5[lrcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:verticalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw .5[llcorner p,lrcorner p] -- .5[ulcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-
-\startxmlsetups mml:menclose
- \edef\mmlmenclosenotation{\ctxmodulemathml{menclosepattern("#1")}}
- \ifx\mmlmenclosenotation\empty
- \xmlflush{#1}
- \else
- \doifelse \mmlmenclosenotation {mml:enclose:longdiv} {
- \overline{\left)\strut\xmlflush{#1}\right.}
- } {
- \doifelse \mmlmenclosenotation {mml:enclose:actuarial} {
- \overline{\left.\strut\xmlflush{#1}\right|}
- } {
- \doifelse \mmlmenclosenotation {mml:enclose:radical} {
- \sqrt{\xmlflush{#1}}
- } {
- % todo: no framed when longdiv, actuarial or radical ? spec ?
- \vcenter {
- \framed
- [frame=off,strut=no,background={\mmlmenclosenotation}] % offset is kind of undefined
- {\startimath
- \expanded{\doifinsetelse {mml:enclose:longdiv} {\mmlmenclosenotation}} {
- \overline{\left)\strut\xmlflush{#1}\right.}
- } {
- \expanded{\doifinsetelse {mml:enclose:actuarial} {\mmlmenclosenotation}} {
- \overline{\left.\strut\xmlflush{#1}\right|}
- } {
- \expanded{\doifinsetelse {mml:enclose:radical} {\mmlmenclosenotation}} {
- \sqrt{\xmlflush{#1}}
- } {
- \xmlflush{#1}
- }
- }
- }
- \stopimath}
- }
- }
- }
- }
- \fi
-\stopxmlsetups
-
-\xmlmapvalue {mml:mfrac:linethickness} {thin} {.2pt}
-\xmlmapvalue {mml:mfrac:linethickness} {medium} {.4pt}
-\xmlmapvalue {mml:mfrac:linethickness} {thick} {.8pt}
-\xmlmapvalue {mml:mfrac:linethickness} {0} {0pt}
-
-\startxmlsetups mml:mfrac % dodo: handle linethickness in lua + unit
- \begingroup
- \edef\mmlfraclinethickness{\xmlatt{#1}{linethickness}}
- \ifx\mmlfraclinethickness\empty
- \doifelse{\xmlatt{#1}{bevelled}}{true} {
- \left.\mmlfirst{#1}\middle/\mmlsecond{#1}\right.% \thinspace\middle/\thinspace
- } {
- \frac{\mmlfirst{#1}}{\mmlsecond{#1}}
- }
- \else
- \doifelse {\xmlval{mml:mfrac:linethickness}{\mmlfraclinethickness}{}} {} {
- \scratchdimen\xmlval{mml:mfrac:linethickness}\mmlfraclinethickness{.4pt}
- } {
- % probably not yet ok
- \setdimensionwithunit\scratchdimen\mmlfraclinethickness{pt}
- }
- {
- {\mmlfirst{#1}}
- \above\scratchdimen
- {\mmlsecond{#1}}
- }
- \fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:ms
- \hbox {
- \tf % else encoding problems
- \edef\mmllquote{\xmlatt{#1}{lquote}}
- \edef\mmlrquote{\xmlatt{#1}{rquote}}
- \ifx\mmllquote\empty\symbol[leftquotation]\else\mmllquote\fi
- \applymmlsometext{#1}{\xmlflush{#1}}
- \ifx\mmlrquote\empty\symbol[rightquotation]\else\mmlrquote\fi
- }
-\stopxmlsetups
-
-\startxmlsetups mml:mstyle
- \begingroup
- \setmmlmathstyle{#1}
- \xmlflush{#1}
- \endgroup
-\stopxmlsetups
-
-\setupMMLappearance[text][\c!alternative=\v!b] % a=normal, b=keep spaces
-
-\startxmlsetups mml:mtext
- \text {
- \applymmlsometext{#1}{
- \doifelse \MMLtextalternative \v!a {
- %\ctxmodulemathml{stripped(\!!bs\xmlflush{#1}\!!es)}
- \ignorespaces
- \xmlflush{#1}
- \removeunwantedspaces
- } {
- \xmlflush{#1}
- }
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:merror
- \hbox{\startimath\displaystyle\xmlflush{#1}\stopimath}
-\stopxmlsetups
-
-\startxmlsetups mml:mphantom
-% \phantom{\ignorespaces{}\xmlflush{#1}\unskip} % watch spacing {} hack
-% \phantom{\mathstyle{\ignorespaces{}\xmlflush{#1}\unskip}}%
- \phantom{\triggermathstyle\normalmathstyle\ignorespaces\xmlflush{#1}\removeunwantedspaces}
-% \mktriggereffect\v!hidden
-% \ignorespaces{}\xmlflush{#1}\unskip % no attributes in math yet
-% \mktriggereffect\v!normal
-\stopxmlsetups
-
-\startxmlsetups mml:mpadded % todo
- \xmlflush{#1}
-\stopxmlsetups
-
-% mrow / option: no fenced
-
-\startxmlsetups mml:maction
- \xmlflush{#1}
-\stopxmlsetups
-
-% \startxmlsetups mml:mrow
-% \begingroup
-% \edef\nofmmlrows{\xmlcount{#1}{/mml:mo}}%
-% \ifnum\nofmmlrows=\plustwo
-% \xmldoifelse {#1} {/mml:mo[position()==1 or position()==\nofmmlrows]} {% we need a {}
-% \def\MMLleft {\left }
-% \def\MMLright {\right}
-% \def\MMLmiddle{\middle}
-% \enabledelimiter
-% \checkdelimiters{\xmlall{#1}{/mml:mo}}
-% \fakeleftdelimiter
-% \xmlflush{#1}
-% \fakerightdelimiter
-% \disabledelimiter
-% } {
-% \xmlflush{#1}
-% }
-% \else
-% \xmlflush{#1}
-% \fi
-% \endgroup
-% \stopxmlsetups
-%
-% fails on { ... so we need
-
-\startxmlsetups mml:mrow
- \begingroup
- \xmldoifelse {#1} {/mml:mo[first() or last()]} {% we need a {}
- \def\MMLleft {\left }
- \def\MMLright {\right}
- \def\MMLmiddle{\middle}
- \enabledelimiter
- \checkdelimiters{\xmlall{#1}{/mml:mo}}
- \fakeleftdelimiter
- \xmlflush{#1}
- \fakerightdelimiter
- \disabledelimiter
- } {
- \xmlflush{#1}
- }
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:msqrt
- \sqrt{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:mroot
- \root{\mmlsecond{#1}}\of{\mmlfirst{#1}}
-\stopxmlsetups
-
-\setupMMLappearance[scripts][\c!alternative=\v!a] % {} rond base
-
-% brrr no { } when limop .. todo: better in lua
-% speed up with ifx and setups or just in lua
-
-\startxmlsetups mml:msub
- \edef\mmlnucleus{\xmlraw{#1}{/mml:*[1]}}
- \doifelse {\utfmathclass\mmlnucleus} {limop} {
- \mmlfirst{#1} \normalsubscript{\mmlsecond{#1}}
- } {
- \doifelse\MMLscriptsalternative\v!a {
- {\mmlfirst{#1}}\normalsubscript{\mmlsecond{#1}}
- } {
- \mmlfirst{#1} \normalsubscript{\mmlsecond{#1}}
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:msup
- \edef\mmlnucleus{\xmlraw{#1}{/mml:*[1]}}
- \doifelse {\utfmathclass\mmlnucleus} {limop} {
- \mmlfirst{#1} \normalsuperscript{\mmlsecond{#1}}
- } {
- \doifelse\MMLscriptsalternative\v!a {
- {\mmlfirst{#1}}\normalsuperscript{\mmlsecond{#1}}
- } {
- \mmlfirst{#1} \normalsuperscript{\mmlsecond{#1}}
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:msubsup
- \edef\mmlnucleus{\xmlraw{#1}{/mml:*[1]}}
- \doifelse {\utfmathclass\mmlnucleus} {limop} {
- \mmlfirst{#1}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
- } {
- \doifelse\MMLscriptsalternative\v!a {
- {\mmlfirst{#1}}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
- } {
- \mmlfirst{#1}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
- }
- }
-\stopxmlsetups
-
-\def\mmlexecuteifdefined#1%
- {\ifx#1\empty
- \expandafter\secondoftwoarguments
- \else\ifcsname#1\endcsname
- \doubleexpandafter\firstoftwoarguments
- \else
- \doubleexpandafter\secondoftwoarguments
- \fi\fi
- {\csname#1\endcsname}}
-
-\startxmlsetups mml:mover
-% \mathop {
- \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}}
- \doifelseutfmathaccent\mmlovertoken {
- \edef\mmlovercommand{\utfmathcommand\mmlovertoken}
- \mmlexecuteifdefined\mmlovercommand\mathematics{\mmlfirst{#1}}
- } {
- \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}}
- \edef\mmlbasecommand{\utfmathfiller\mmlbasetoken}
- \edef\mmlovercommand{\utfmathfiller\mmlovertoken}
-% todo: proper math mode/size
- \vbox {
- \mathsurround\zeropoint \ialign {
-% \hss##\hss
-\hss$##$\hss
- \crcr
- \noalign{\kern3\onepoint}%
-% \mmlexecuteifdefined\mmlovercommand{\mathematics{\mmlsecond{#1}}}
-\mmlexecuteifdefined\mmlovercommand{\mmlsecond{#1}}
- \crcr
- \noalign{\kern3\onepoint\nointerlineskip}%
-% \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}}
-\mmlexecuteifdefined\mmlbasecommand{\mmlfirst{#1}}
- \crcr
- }
- }
- }
-% }
-% \limits % spoils spacing
-\stopxmlsetups
-
-% messy: <munder><mo>(</mo><mo>&UnderBar;</mo></munder>
-
-\startxmlsetups mml:munder
-% \mathop {
- \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}}
- \doifelseutfmathaccent\mmlundertoken {
- \edef\mmlundercommand{\utfmathcommand\mmlundertoken}
- \mmlexecuteifdefined\mmlundercommand\mathematics{\mmlfirst{#1}}
- } {
- \edef\mmlbasetoken {\xmlraw{#1}{/mml:*[1]}}
- \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken}
- \edef\mmlundercommand{\utfmathfiller\mmlundertoken}
-% todo: proper math mode/size
- \vtop {
- \mathsurround\zeropoint \ialign {
-% \hss##\hss
-\hss$##$\hss
- \crcr
-% \mmlexecuteifdefined\mmlbasecommand {\mathematics{\mmlfirst{#1}}}
-\mmlexecuteifdefined\mmlbasecommand {\mmlfirst{#1}}
- \crcr
- \noalign{\kern3\onepoint\nointerlineskip}%
-% \mmlexecuteifdefined\mmlundercommand{\mathematics{\mmlsecond{#1}}}
-\mmlexecuteifdefined\mmlundercommand{\mmlsecond{#1}}
- \crcr
- \noalign{\kern3\onepoint}
- }
- }
- }
-% }
-% \limits % spoils spacing
-\stopxmlsetups
-
-\startxmlsetups mml:munderover
- \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}}
- \edef\mmlbasecommand{\utfmathcommand\mmlbasetoken}
- \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
-\stopxmlsetups
-
-% tables (mml:mtable, mml:mtr, mml:mlabledtr, mml:mtd)
-
-\startxmlsetups mml:mtable % some more attributes need to be supported
- \vcenter{\ctxmodulemathml{mtable("#1")}}
-\stopxmlsetups
-
-\startxmlsetups mml:mcolumn
- \ctxmodulemathml{mcolumn("#1")}
-\stopxmlsetups
-
-\def\mmlsetfakewidth#1{\setbox\scratchbox\hbox{#1}\scratchdimen\wd\scratchbox}
-
-\def\mmlmcolumndigitspace {\mmlsetfakewidth {0}\kern\scratchdimen}
-\def\mmlmcolumndigitrule {\mmlsetfakewidth {0}\vrule width \scratchdimen height .2pt depth .2pt\relax}
-\def\mmlmcolumnsymbolrule {\mmlsetfakewidth{\times}\vrule width \scratchdimen height .2pt depth .2pt\relax}
-\def\mmlmcolumnpunctuationrule{\mmlsetfakewidth {.}\vrule width \scratchdimen height .2pt depth .2pt\relax}
-
-\startxmlsetups mml:mspace
- \begingroup
- \edef\mmlspacetext{\xmlatt{#1}{spacing}}
- \ifx\mmlspacetext\empty
- \!!widtha \xmlattdef{#1}{width} \!!zeropoint % must be string
- \!!heighta\xmlattdef{#1}{height}\!!zeropoint
- \!!deptha \xmlattdef{#1}{depth} \!!zeropoint
- \ifdim\!!heighta=\zeropoint
- \ifdim\!!deptha=\zeropoint\else
- \hbox{\vrule\s!depth\!!deptha\s!height\zeropoint\s!width\zeropoint}%
- \fi
- \else
- \hbox{\vrule\s!depth\zeropoint\s!height\!!heighta\s!width\zeropoint}%
- \fi
- \ifdim\!!widtha=\zeropoint\else
- \hskip\!!widtha
- \fi
- \else
- \phantom{\triggermathstyle\normalmathstyle\mmlspacetext}
- \fi
- \endgroup
-\stopxmlsetups
-
-% later we can do a better job by manipulating node lists
-
-% \startxmlsetups mml:mline
-% % new, rather undefined, we need to capture a few keywords
-% \edef\mmllinewidth {\xmlatt{#1}{linethickness}}
-% \edef\mmllinetext {\xmlatt{#1}{spacing}}
-% \edef\mmllinelength{\xmlattdef{#1}{length}\!!zeropoint}
-% \ifx\mmllinewidth\empty
-% \!!deptha.5\linewidth
-% \else
-% \!!deptha.5\dimexpr\mmllinewidth\relax
-% \fi
-% \!!heighta\!!deptha
-% \ifx\mmllinetext\empty
-% \ifx\mmllinelength\empty
-% \!!widtha\zeropoint
-% \else
-% \!!widtha\mmllinelength
-% \fi
-% \else
-% \setbox\scratchbox\hbox{\mathematics{\mathstyle{\mmllinetext}}}% not ok
-% \!!widtha\wd\scratchbox
-% \fi
-% \hbox{\vrule\s!width\!!widtha\s!depth\!!deptha\s!height\!!heighta}
-% \stopxmlsetups
-
-\startxmlsetups mml:mglyph % probably never ok (hbox is needed in order to switch to normal font)
- \begingroup
- \edef\mmlglyphfontfamily{\xmlatt {#1}{fontfamily}}
- \edef\mmlglyphalt {\xmlattdef{#1}{alt}{unknown}}
- \edef\mmlglyphindex {\xmlatt {#1}{index}}
- \ifx \mmlglyphfontfamily \empty
- \hbox{\tttf[no fontfamily specified for \mmlglyphalt]}
- \else\ifx\mmlglyphindex\empty
- \hbox{\tttf[no index specified for \mmlglyphalt]}
- \else
- \hbox{\getglyph\mmlglyphfontfamily\mmlglyphindex}
- \fi\fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:maligngroup \stopxmlsetups % will be done when needed
-\startxmlsetups mml:malignmark \stopxmlsetups % will be done when needed
-
-\startxmlsetups mml:none \stopxmlsetups
-\startxmlsetups mml:mprescripts \stopxmlsetups
-
-\startxmlsetups mml:mmultiscripts
- \ctxmodulemathml{mmultiscripts("#1")}
-\stopxmlsetups
-
-% goodie
-
-\definebuffer[mml]
-
-\def\stopmml{\xmlprocessbuffer{@mml@}{\thedefinedbuffer{mml}}{}}
-
-\stopmodule
-
-\protect \endinput
-
-% TODO:
-%
-% <apply><divide/>
-% <apply><minus/>
-% <apply><minus/><ci>b</ci></apply>
-% <apply><minus/><ci>b</ci></apply>
-% <apply><root/> <ci>a</ci></apply>
-% </apply>
-% <apply><minus/>
-% <apply><minus/><ci>b</ci><ci>b</ci></apply>
-% <apply><minus/><ci>b</ci></apply>
-% <apply><root/> <ci>a</ci></apply>
-% </apply>
-% </apply>
-
-% \startmoduletestsection
-%
-% \def\xflushXMLstackwith#1#2#3#4% num bgroup egroup whatever
-% {\dostepwiserecurse{#1}\XMLstacklevel\plusone
-% {#2\relax
-% \ifnum\recurselevel>#1\relax#4\fi
-% \getXMLstackdata\recurselevel
-% #3}}
-%
-% \def\xflushXMLstackfrom#1#2#3%
-% {\dostepwiserecurse{#1}\XMLstacklevel\plusone
-% {#2\getXMLstackdata\recurselevel#3}}
-%
-% \startxmlsetups mml:minus
-% \doif \MMLsignreduction \v!yes {
-% \setMMLcreset{fn,\MMLcfunctionlist}
-% }
-% \ifcase\XMLstacklevel
-% \or
-% % self
-% \or
-% -\getXMLstackdata\plustwo
-% \else
-% \dostepwiserecurse \plustwo \XMLstacklevel \plusone {
-% \begingroup
-% \doifelse {\getXMLstackname\recurselevel} {apply} {
-% \ifnum\recurselevel=\plustwo
-% \begingroup
-% \dodoifelseMMCfunctioninapply \recurselevel {minus} {
-% \ifnum\XMLstacklevel>\plustwo
-% \endgroup
-% \else
-% \endgroup
-% \MMLcreset
-% \fi
-% } {
-% \endgroup
-% }
-% \else
-% \doifelseMMCfunctioninapply \recurselevel {\MMLcfunctionlist,\MMLcconstructlist} {
-% \MMLcreset
-% } {
-% }
-% \fi
-% } {
-% }
-% \getXMLstackdata\recurselevel
-% \ifnum\recurselevel<\XMLstacklevel\relax
-% -
-% \fi
-% \endgroup
-% }
-% \fi
-% \stopxmlsetups
-%
-% \stopmoduletestsection
diff --git a/tex/context/base/x-xfdf.mkiv b/tex/context/base/x-xfdf.mkiv
new file mode 100644
index 000000000..c4ca0c427
--- /dev/null
+++ b/tex/context/base/x-xfdf.mkiv
@@ -0,0 +1,71 @@
+%D \module
+%D [ file=x-xfdf,
+%D version=2011.09.07,
+%D title=\CONTEXT\ XML Modules,
+%D subtitle=\XFDF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a revival of using \XFDF, but now in a more \MKIV-ish way. We
+%D supported it long ago already in \MKII\ but never used it at a large
+%D scale (not that much user interest anyway).
+
+\startmodule[xfdf]
+
+% see xfdf-001.xfdf and xfdf-001.tex
+
+% %D Possible speedup but hardly worth the trouble.
+%
+% \startluacode
+%
+% local hashes = { } table.setmetatableindex(hashes,function(t,k) local v = { } t[k] = v return v end)
+%
+% function xml.functions.xfdf_collect_values(root)
+% local hash = hashes[root]
+% for c in xml.collected(root,"/xfdf/fields/field/value") do
+% hash[xml.parent(c).at.name] = c
+% end
+% end
+%
+% function xml.functions.xfdf_get_values(root,name)
+% return hashes[root][name]
+% end
+%
+% function lxml.xfdf_get_values(root,name)
+% xml.sprint(hashes[lxml.id(root)][name])
+% end
+%
+% \stopluacode
+%
+% \def\xfdfvalue#1#2%
+% {\ctxlua{lxml.xfdf_get_values("#1","#2")}}
+
+\startxmlsetups xfdf:define
+ \xmlsetsetup{#1}{*}{xfdf:*}
+ % \xmlfilter {#1}{./function(xfdf_collect_values)}
+\stopxmlsetups
+
+\xmlregisterns{xfdf}{http://ns.adobe.com/xfdf/}
+
+\xmlregisterdocumentsetup{xfdf}{xfdf:define}
+
+\startxmlsetups xfdf:value
+ \xmlflush{#1}
+\stopxmlsetups
+
+\def\xfdfload #1#2{\xmlloadonly{#1}{#2}{xfdf}}
+\def\xfdfvalue#1#2{\xmlfirst{#1}{/xfdf/fields/field[@name='#2']/value}}
+
+% \startxmlsetups xfdf:b
+% \bold{\xmlflush{#1}}
+% \stopxmlsetups
+
+% \xfdfload {whatever}{xfdf-001.xfdf}
+% \xfdfvalue{whatever}{somefield}
+
+\stopmodule
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 1140ff916..4700859ff 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 09/06/12 23:03:51
+-- merge date : 09/10/12 00:57:08
do -- begin closure to overcome local limits and interference
@@ -132,6 +132,14 @@ string.unquote = string.unquoted
string.itself = function(s) return s end
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- closure
do -- begin closure to overcome local limits and interference