summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/lxml-tex.lua
diff options
context:
space:
mode:
authorMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
committerMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
commit15995e10bfc68edf79970c4ea4fbb6678566c46e (patch)
tree2de7ca2a83f2d37ef043ad7429a5cb945bb79ddb /Master/texmf-dist/tex/context/base/lxml-tex.lua
parentc9a39f716f1e5ec820ed3aab2c9aef25c5a9d730 (diff)
ConTeXt 2012.05.14 16:00
git-svn-id: svn://tug.org/texlive/trunk@26371 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/lxml-tex.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-tex.lua869
1 files changed, 538 insertions, 331 deletions
diff --git a/Master/texmf-dist/tex/context/base/lxml-tex.lua b/Master/texmf-dist/tex/context/base/lxml-tex.lua
index 26a8b29962e..22f98980528 100644
--- a/Master/texmf-dist/tex/context/base/lxml-tex.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-tex.lua
@@ -6,9 +6,13 @@ if not modules then modules = { } end modules ['lxml-tst'] = {
license = "see context related readme files"
}
+-- Because we split and resolve entities we use the direct printing
+-- interface and not the context one. If we ever do that there will
+-- be an cldf-xml helper library.
+
local utf = unicode.utf8
-local utfchar = utf.char
+local utfchar, utfupper = utf.char, utf.upper
local concat, insert, remove = table.concat, table.insert, table.remove
local format, sub, gsub, find, gmatch, match = string.format, string.sub, string.gsub, string.find, string.gmatch, string.match
local type, next, tonumber, tostring = type, next, tonumber, tostring
@@ -18,16 +22,18 @@ local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
local tex, xml = tex, xml
local lowerchars, upperchars, lettered = characters.lower, characters.upper, characters.lettered
-lxml = lxml or { }
+lxml = lxml or { }
local lxml = lxml
-local texsprint, texprint, texwrite = tex.sprint, tex.print, tex.write
-local texcatcodes, ctxcatcodes, vrbcatcodes, notcatcodes = tex.texcatcodes, tex.ctxcatcodes, tex.vrbcatcodes, tex.notcatcodes
+local ctxcatcodes, notcatcodes = tex.ctxcatcodes, tex.notcatcodes
+
+local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing)
local xmlelements, xmlcollected, xmlsetproperty = xml.elements, xml.collected, xml.setproperty
local xmlwithelements = xml.withelements
local xmlserialize, xmlcollect, xmltext, xmltostring = xml.serialize, xml.collect, xml.text, xml.tostring
local xmlapplylpath = xml.applylpath
+local xmlunprivatized, xmlprivatetoken, xmlprivatecodes = xml.unprivatized, xml.privatetoken, xml.privatecodes
local variables = (interfaces and interfaces.variables) or { }
@@ -39,8 +45,95 @@ local trace_setups = false trackers.register("lxml.setups", function(v) tra
local trace_loading = false trackers.register("lxml.loading", function(v) trace_loading = v end)
local trace_access = false trackers.register("lxml.access", function(v) trace_access = v end)
local trace_comments = false trackers.register("lxml.comments", function(v) trace_comments = v end)
+local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_lxml = logs.reporter("xml","tex")
+local report_xml = logs.reporter("xml","tex")
+
+local forceraw, rawroot = false, nil
+
+-- tex entities
+--
+-- todo: unprivatize attributes
+
+lxml.entities = lxml.entities or { }
+
+storage.register("lxml/entities",lxml.entities,"lxml.entities")
+
+--~ xml.placeholders.unknown_any_entity = nil -- has to be per xml
+
+local xmlentities = xml.entities
+local texentities = lxml.entities
+local parsedentity = xml.parsedentitylpeg
+
+function lxml.registerentity(key,value)
+ texentities[key] = value
+ if trace_entities then
+ report_xml("registering tex entity '%s' as: %s",key,value)
+ end
+end
+
+function lxml.resolvedentity(str)
+ if forceraw then
+ if trace_entities then
+ report_xml("passing entity '%s' as &%s;",str,str)
+ end
+ context("&%s;",str)
+ else
+ local e = texentities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ if trace_entities then
+ report_xml("passing entity '%s' using function",str)
+ end
+ e(str)
+ elseif e then
+ if trace_entities then
+ report_xml("passing entity '%s' as '%s'using ctxcatcodes",str,e)
+ end
+ context(e)
+ end
+ return
+ end
+ local e = xmlentities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ e = e(str)
+ end
+ if e then
+ if trace_entities then
+ report_xml("passing entity '%s' as '%s' using notcatcodes",str,e)
+ end
+ contextsprint(notcatcodes,e)
+ return
+ end
+ end
+ -- resolve hex and dec, todo: escape # & etc for ctxcatcodes
+ -- normally this is already solved while loading the file
+ local chr, err = lpegmatch(parsedentity,str)
+ if chr then
+ if trace_entities then
+ report_xml("passing entity '%s' as '%s' using ctxcatcodes",str,chr)
+ end
+ context(chr)
+ elseif err then
+ if trace_entities then
+ report_xml("passing faulty entity '%s' as '%s'",str,err)
+ end
+ context(err)
+ else
+ local tag = utfupper(str)
+ if trace_entities then
+ report_xml("passing entity '%s' to \\xmle using tag '%s'",str,tag)
+ end
+ context.xmle(str,tag) -- we need to use our own upper
+ end
+ end
+end
+
+-- tex interface
lxml.loaded = lxml.loaded or { }
local loaded = lxml.loaded
@@ -55,112 +148,68 @@ local finalizers = xml.finalizers
finalizers.xml = finalizers.xml or { }
finalizers.tex = finalizers.tex or { }
--- this might look inefficient but it's actually rather efficient
--- because we avoid tokenization of leading spaces and xml can be
--- rather verbose (indented)
+-- serialization with entity handling
-local newline = lpeg.patterns.newline
-local space = lpeg.patterns.spacer
local ampersand = P("&")
local semicolon = P(";")
-local spacing = newline * space^0
-local content = C((1-spacing-ampersand)^1)
-local verbose = C((1-(space+newline))^1)
-local entity = ampersand * C((1-semicolon)^1) * semicolon
-
-local xmltextcapture = (
- space^0 * newline^2 * Cc("") / texprint + -- better ^-2 ?
- space^0 * newline * space^0 * Cc(" ") / texsprint +
- content / function(str) return texsprint(notcatcodes,str) end + -- was just texsprint, current catcodes regime is notcatcodes
- entity / xml.resolvedentity
-)^0
-
-local ctxtextcapture = (
- space^0 * newline^2 * Cc("") / texprint + -- better ^-2 ?
- space^0 * newline * space^0 * Cc(" ") / texsprint +
- content / function(str) return texsprint(ctxcatcodes,str) end + -- was just texsprint, current catcodes regime is notcatcodes
- entity / xml.resolvedentity
-)^0
-
-local forceraw, rawroot = false, nil
+local entity = ampersand * C((1-semicolon)^1) * semicolon / lxml.resolvedentity -- context.bold
-function lxml.startraw()
- forceraw = true
-end
+local _, xmltextcapture = context.newtexthandler {
+ exception = entity,
+ catcodes = notcatcodes,
+}
-function lxml.stopraw()
- forceraw = false
-end
+local _, xmlspacecapture = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ exception = entity,
+ catcodes = notcatcodes,
+}
-function lxml.rawroot()
- return rawroot
-end
+local _, xmllinecapture = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ exception = entity,
+ catcodes = notcatcodes,
+}
---~ function lxml.rawpath(rootid)
---~ if rawroot and type(rawroot) == "table" then
---~ local text, path, rp
---~ if not rawroot.dt then
---~ text, path, rp = "text", "", rawroot[0]
---~ else
---~ path, rp = "tree", "", rawroot.__p__
---~ end
---~ while rp do
---~ local rptg = rp.tg
---~ if rptg then
---~ path = rptg .. "/" .. path
---~ end
---~ rp = rp.__p__
---~ end
---~ return { rootid, "/" .. path, text }
---~ end
---~ end
+local _, ctxtextcapture = context.newtexthandler {
+ exception = entity,
+ catcodes = ctxcatcodes,
+}
-- cdata
-local linecommand = "\\obeyedline"
-local spacecommand = "\\obeyedspace" -- "\\strut\\obeyedspace"
-local beforecommand = ""
-local aftercommand = ""
-
-local xmlverbosecapture = (
- newline / function( ) texsprint(texcatcodes,linecommand,"{}") end +
- verbose / function(s) texsprint(vrbcatcodes,s) end +
- space / function( ) texsprint(texcatcodes,spacecommand,"{}") end
-)^0
-
-local function toverbatim(str)
- if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end
- lpegmatch(xmlverbosecapture,str)
- if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end
-end
+local toverbatim = context.newverbosehandler {
+ line = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ before = context.xmlcdatabefore,
+ after = context.xmlcdataafter,
+}
-function lxml.setverbatim(before,after,obeyedline,obeyedspace)
- beforecommand, aftercommand, linecommand, spacecommand = before, after, obeyedline, obeyedspace
-end
+lxml.toverbatim = context.newverbosehandler {
+ line = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ before = context.xmlcdatabefore,
+ after = context.xmlcdataafter,
+ strip = true,
+}
-local obeycdata = true
+-- raw flushing
-function lxml.setcdata()
- obeycdata = true
+function lxml.startraw()
+ forceraw = true
end
-function lxml.resetcdata()
- obeycdata = false
+function lxml.stopraw()
+ forceraw = false
end
--- cdata and verbatim
-
-lxml.setverbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace")
-
--- local capture = (space^0*newline)^0 * capture * (space+newline)^0 * -1
-
-function lxml.toverbatim(str)
- if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end
- -- todo: add this to capture
- str = gsub(str,"^[ \t]+[\n\r]+","")
- str = gsub(str,"[ \t\n\r]+$","")
- lpegmatch(xmlverbosecapture,str)
- if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end
+function lxml.rawroot()
+ return rawroot
end
-- storage
@@ -303,22 +352,23 @@ end
function lxml.withindex(name,n,command) -- will change as name is always there now
local i, p = lpegmatch(splitter,n)
if p then
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
else
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
end
end
function lxml.getindex(name,n) -- will change as name is always there now
local i, p = lpegmatch(splitter,n)
if p then
- texsprint(ctxcatcodes,n)
+ contextsprint(ctxcatcodes,n)
else
- texsprint(ctxcatcodes,name,"::",n)
+ contextsprint(ctxcatcodes,name,"::",n)
end
end
--- loading (to be redone, no overload)
+-- loading (to be redone, no overload) .. best use different methods and
+-- keep raw xml (at least as option)
xml.originalload = xml.originalload or xml.load
@@ -333,28 +383,29 @@ function xml.load(filename,settings)
return xmltable
end
-local entities = xml.entities
-
local function entityconverter(id,str)
- return entities[str] and "&"..str..";" -- feed back into tex end later
+ return xmlentities[str] or xmlprivatetoken(str) or "" -- roundtrip handler
end
function lxml.convert(id,data,entities,compress)
- local settings = {
- unify_predefined_entities = true,
+ local settings = { -- we're now roundtrip anyway
+ unify_predefined_entities = true,
+ utfize_entities = true,
+ resolve_predefined_entities = true,
+ resolve_entities = function(str) return entityconverter(id,str) end, -- needed for mathml
}
if compress and compress == variables.yes then
settings.strip_cm_and_dt = true
end
- if entities and entities == variables.yes then
- settings.utfize_entities = true
- settings.resolve_entities = function (str) return entityconverter(id,str) end
- end
+ -- if entities and entities == variables.yes then
+ -- settings.utfize_entities = true
+ -- -- settings.resolve_entities = function (str) return entityconverter(id,str) end
+ -- end
return xml.convert(data,settings)
end
function lxml.load(id,filename,compress,entities)
- filename = commands.preparedfile(filename)
+ filename = commands.preparedfile(filename) -- not commands!
if trace_loading then
report_lxml("loading file '%s' as '%s'",filename,id)
end
@@ -407,12 +458,9 @@ function xml.getbuffer(name,compress,entities) -- we need to make sure that comm
end
function lxml.loadbuffer(id,name,compress,entities)
- if not name or name == "" then
- name = tex.jobname
- end
starttiming(xml)
nofconverted = nofconverted + 1
- local data = buffers.getcontent(name or id)
+ local data = buffers.collectcontent(name or id) -- name can be list
local xmltable = lxml.convert(id,data,compress,entities)
lxml.store(id,xmltable)
stoptiming(xml)
@@ -469,10 +517,11 @@ local function tex_element(e,handlers)
addindex(rootname,false,true)
ix = e.ix
end
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
+ -- faster than context.xmlw
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
else
report_lxml( "fatal error: no index for '%s'",command)
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
end
elseif tc == "function" then
command(e)
@@ -495,7 +544,7 @@ pihandlers[#pihandlers+1] = function(str)
if str then
local a, b, c, d = lpegmatch(parser,str)
if d then
- texsprint(ctxcatcodes,"\\xmlcontextdirective{",a",}{",b,"}{",c,"}{",d,"}")
+ contextsprint(ctxcatcodes,"\\xmlcontextdirective{",a,"}{",b,"}{",c,"}{",d,"}")
end
end
end
@@ -507,6 +556,16 @@ local function tex_pi(e,handlers)
end
end
+local obeycdata = true
+
+function lxml.setcdata()
+ obeycdata = true
+end
+
+function lxml.resetcdata()
+ obeycdata = false
+end
+
local function tex_cdata(e,handlers)
if obeycdata then
toverbatim(e.dt[1])
@@ -514,16 +573,16 @@ local function tex_cdata(e,handlers)
end
local function tex_text(e)
+ e = xmlunprivatized(e)
lpegmatch(xmltextcapture,e)
end
-local function ctx_text(e)
+local function ctx_text(e) -- can be just context(e) as we split there
lpegmatch(ctxtextcapture,e)
end
local function tex_handle(...)
--- report_lxml( "error while flushing: %s", concat { ... })
- texsprint(...) -- notcatcodes is active anyway
+ contextsprint(ctxcatcodes,...) -- notcatcodes is active anyway
end
local xmltexhandler = xml.newhandlers {
@@ -543,6 +602,62 @@ local xmltexhandler = xml.newhandlers {
lxml.xmltexhandler = xmltexhandler
+-- begin of test
+
+local function tex_space(e)
+ e = xmlunprivatized(e)
+ lpegmatch(xmlspacecapture,e)
+end
+
+local xmltexspacehandler = xml.newhandlers {
+ name = "texspace",
+ handle = tex_handle,
+ functions = {
+ ["@dt@"] = tex_doctype,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_space,
+ }
+}
+
+local function tex_line(e)
+ e = xmlunprivatized(e)
+ lpegmatch(xmllinecapture,e)
+end
+
+local xmltexlinehandler = xml.newhandlers {
+ name = "texline",
+ handle = tex_handle,
+ functions = {
+ ["@dt@"] = tex_doctype,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_line,
+ }
+}
+
+function lxml.flushspacewise(id) -- keeps spaces and lines
+ id = getid(id)
+ local dt = id and id.dt
+ if dt then
+ xmlserialize(dt,xmltexspacehandler)
+ end
+end
+
+function lxml.flushlinewise(id) -- keeps lines
+ id = getid(id)
+ local dt = id and id.dt
+ if dt then
+ xmlserialize(dt,xmltexlinehandler)
+ end
+end
+
+-- end of test
+
function lxml.serialize(root)
xmlserialize(root,xmltexhandler)
end
@@ -550,22 +665,28 @@ end
function lxml.setaction(id,pattern,action)
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- for c=1,#collected do
- collected[c].command = action
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ collected[c].command = action
+ end
end
end
end
-local function sprint(root)
+local function sprint(root) -- check rawroot usage
if root then
local tr = type(root)
if tr == "string" then -- can also be result of lpath
- -- rawroot = false
+ -- rawroot = false -- ?
+ root = xmlunprivatized(root)
lpegmatch(xmltextcapture,root)
elseif tr == "table" then
if forceraw then
rawroot = root
- texwrite(xmltostring(root))
+ -- contextsprint(ctxcatcodes,xmltostring(root)) -- goes wrong with % etc
+ root = xmlunprivatized(xmltostring(root))
+ lpegmatch(xmltextcapture,root) -- goes to toc
else
xmlserialize(root,xmltexhandler)
end
@@ -585,6 +706,7 @@ local function tprint(root) -- we can move sprint inline
end
end
elseif tr == "string" then
+ root = xmlunprivatized(root)
lpegmatch(xmltextcapture,root)
end
end
@@ -595,21 +717,24 @@ local function cprint(root) -- content
-- quit
elseif type(root) == 'string' then
-- rawroot = false
+ root = xmlunprivatized(root)
lpegmatch(xmltextcapture,root)
else
local rootdt = root.dt
if forceraw then
rawroot = root
- texwrite(xmltostring(rootdt or root))
+ -- contextsprint(ctxcatcodes,xmltostring(rootdt or root))
+ root = xmlunprivatized(xmltostring(root))
+ lpegmatch(xmltextcapture,root) -- goes to toc
else
xmlserialize(rootdt or root,xmltexhandler)
end
end
end
-xml.sprint = sprint local xmlsprint = sprint -- redo these names
-xml.tprint = tprint local xmltprint = tprint
-xml.cprint = cprint local xmlcprint = cprint
+xml.sprint = sprint local xmlsprint = sprint -- calls ct mathml -> will be replaced
+xml.tprint = tprint local xmltprint = tprint -- only used here
+xml.cprint = cprint local xmlcprint = cprint -- calls ct mathml -> will be replaced
-- now we can flush
@@ -720,7 +845,7 @@ function lxml.flushsetups(id,...)
if trace_loading then
report_lxml("applying setup %02i = %s to %s",k,v,document)
end
- texsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
+ contextsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
done[v] = true
end
end
@@ -756,40 +881,45 @@ function lxml.setsetup(id,pattern,setup)
if not setup or setup == "" or setup == "*" or setup == "-" or setup == "+" then
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- if trace_setups then
- for c=1, #collected do
- local e = collected[c]
- local ix = e.ix or 0
- if setup == "-" then
- e.command = false
- report_lxml("lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup)
- elseif setup == "+" then
- e.command = true
- report_lxml("lpath matched (b) %5i: %s = %s -> text",c,ix,setup)
- else
- local tg = e.tg
- if tg then -- to be sure
- e.command = tg
- local ns = e.rn or e.ns
- if ns == "" then
- report_lxml("lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg)
- else
- report_lxml("lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg)
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix or 0
+ if setup == "-" then
+ e.command = false
+ report_lxml("lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup)
+ elseif setup == "+" then
+ e.command = true
+ report_lxml("lpath matched (b) %5i: %s = %s -> text",c,ix,setup)
+ else
+ local tg = e.tg
+ if tg then -- to be sure
+ e.command = tg
+ local ns = e.rn or e.ns
+ if ns == "" then
+ report_lxml("lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg)
+ else
+ report_lxml("lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg)
+ end
end
end
end
- end
- else
- for c=1, #collected do
- local e = collected[c]
- if setup == "-" then
- e.command = false
- elseif setup == "+" then
- e.command = true
- else
- e.command = e.tg
+ else
+ for c=1,nc do
+ local e = collected[c]
+ if setup == "-" then
+ e.command = false
+ elseif setup == "+" then
+ e.command = true
+ else
+ e.command = e.tg
+ end
end
end
+ elseif trace_setups then
+ report_lxml("zero lpath matches for %s",pattern)
end
elseif trace_setups then
report_lxml("no lpath matches for %s",pattern)
@@ -799,44 +929,49 @@ function lxml.setsetup(id,pattern,setup)
if a and b then
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- if trace_setups then
- for c=1, #collected do
- local e = collected[c]
- local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
- if b == "-" then
- e.command = false
- if ns == "" then
- report_lxml("lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg)
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if b == "-" then
+ e.command = false
+ if ns == "" then
+ report_lxml("lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg)
+ else
+ report_lxml("lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg)
+ end
+ elseif b == "+" then
+ e.command = true
+ if ns == "" then
+ report_lxml("lpath matched (g) %5i: %s = %s -> text",c,ix,tg)
+ else
+ report_lxml("lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg)
+ end
else
- report_lxml("lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg)
+ e.command = a .. tg
+ if ns == "" then
+ report_lxml("lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command)
+ else
+ report_lxml("lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command)
+ end
end
- elseif b == "+" then
- e.command = true
- if ns == "" then
- report_lxml("lpath matched (g) %5i: %s = %s -> text",c,ix,tg)
- else
- report_lxml("lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg)
- end
- else
- e.command = a .. tg
- if ns == "" then
- report_lxml("lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command)
+ end
+ else
+ for c=1,nc do
+ local e = collected[c]
+ if b == "-" then
+ e.command = false
+ elseif b == "+" then
+ e.command = true
else
- report_lxml("lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command)
+ e.command = a .. e.tg
end
end
end
- else
- for c=1, #collected do
- local e = collected[c]
- if b == "-" then
- e.command = false
- elseif b == "+" then
- e.command = true
- else
- e.command = a .. e.tg
- end
- end
+ elseif trace_setups then
+ report_lxml("zero lpath matches for %s",pattern)
end
elseif trace_setups then
report_lxml("no lpath matches for %s",pattern)
@@ -844,21 +979,26 @@ function lxml.setsetup(id,pattern,setup)
else
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- if trace_setups then
- for c=1, #collected do
- local e = collected[c]
- e.command = setup
- local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
- if ns == "" then
- report_lxml("lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup)
- else
- report_lxml("lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup)
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ e.command = setup
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if ns == "" then
+ report_lxml("lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup)
+ else
+ report_lxml("lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup)
+ end
+ end
+ else
+ for c=1,nc do
+ collected[c].command = setup
end
end
- else
- for c=1, #collected do
- collected[c].command = setup
- end
+ elseif trace_setups then
+ report_lxml("zero lpath matches for %s",pattern)
end
elseif trace_setups then
report_lxml("no lpath matches for %s",pattern)
@@ -872,81 +1012,111 @@ end
local finalizers = xml.finalizers.tex
local function first(collected)
- if collected then
+ if collected and #collected > 0 then
xmlsprint(collected[1])
end
end
local function last(collected)
if collected then
- xmlsprint(collected[#collected])
+ local nc = #collected
+ if nc > 0 then
+ xmlsprint(collected[nc])
+ end
end
end
local function all(collected)
if collected then
- for c=1,#collected do
- xmlsprint(collected[c])
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ xmlsprint(collected[c])
+ end
end
end
end
local function reverse(collected)
if collected then
- for c=#collected,1,-1 do
- xmlsprint(collected[c])
+ local nc = #collected
+ if nc >0 then
+ for c=nc,1,-1 do
+ xmlsprint(collected[c])
+ end
end
end
end
local function count(collected)
- texwrite((collected and #collected) or 0)
+ contextsprint(ctxcatcodes,(collected and #collected) or 0) -- why ctxcatcodes
end
local function position(collected,n)
-- todo: if not n then == match
if collected then
- n = tonumber(n) or 0
- if n < 0 then
- n = #collected + n + 1
- end
- if n > 0 then
- xmlsprint(collected[n])
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = nc + n + 1
+ end
+ if n > 0 then
+ local cn = collected[n]
+ if cn then
+ xmlsprint(cn)
+ return
+ end
+ end
end
end
end
local function match(collected) -- is match in preceding collected, never change, see bibxml
local m = collected and collected[1]
- texwrite(m and m.mi or 0)
+ contextsprint(ctxcatcodes,m and m.mi or 0) -- why ctxcatcodes
end
local function index(collected,n)
if collected then
- n = tonumber(n) or 0
- if n < 0 then
- n = #collected + n + 1
- end
- if n > 0 then
- texwrite(collected[n].ni or 0)
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = nc + n + 1 -- brrr
+ end
+ if n > 0 then
+ local cn = collected[n]
+ if cn then
+ contextsprint(ctxcatcodes,cn.ni or 0) -- why ctxcatcodes
+ return
+ end
+ end
end
end
+ contextsprint(ctxcatcodes,0) -- why ctxcatcodes
end
local function command(collected,cmd,otherwise)
local n = collected and #collected
if n and n > 0 then
- for c=1,n do
+ local wildcard = find(cmd,"%*")
+ for c=1,n do -- maybe optimize for n=1
local e = collected[c]
local ix = e.ix
+ local name = e.name
if not ix then
- lxml.addindex(e.name,false,true)
+ lxml.addindex(name,false,true)
ix = e.ix
end
- texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",e.name,"::",ix,"}")
+ if wildcard then
+ contextsprint(ctxcatcodes,"\\xmlw{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}")
+ else
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}")
+ end
end
elseif otherwise then
- texsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
+ contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
end
end
@@ -955,22 +1125,22 @@ local function attribute(collected,a,default)
local at = collected[1].at
local str = (at and at[a]) or default
if str and str ~= "" then
- texsprint(notcatcodes,str)
+ contextsprint(notcatcodes,str)
end
elseif default then
- texsprint(notcatcodes,default)
+ contextsprint(notcatcodes,default)
end
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
if at then
local a = at[arguments]
if a then
- texsprint(notcatcodes,a)
+ contextsprint(notcatcodes,a)
end
else
break -- error
@@ -983,7 +1153,9 @@ end
local function text(collected)
if collected then
local nc = #collected
- if nc == 1 then -- hardly any gain so this will go
+ if nc == 0 then
+ -- nothing
+ elseif nc == 1 then -- hardly any gain so this will go
cprint(collected[1])
else for c=1,nc do
cprint(collected[c])
@@ -993,71 +1165,80 @@ end
local function ctxtext(collected)
if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,collected[1].dt)
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,collected[c].dt)
+ end
end
end
end
---~ local str = xmltext(getid(id),pattern) or ""
---~ str = gsub(str,"^%s*(.-)%s*$","%1")
---~ if nolines then
---~ str = gsub(str,"%s+"," ")
---~ end
-
local function stripped(collected) -- tricky as we strip in place
if collected then
- for c=1,#collected do
- cprint(xml.stripelement(collected[c]))
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ cprint(xml.stripelement(collected[c]))
+ end
end
end
end
local function lower(collected)
- if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,lowerchars(collected[1].dt[1]))
+ if not collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,lowerchars(collected[c].dt[1]))
+ end
end
end
end
local function upper(collected)
if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,upperchars(collected[1].dt[1]))
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,upperchars(collected[c].dt[1]))
+ end
end
end
end
local function number(collected)
- if collected then
- local n = 0
- for c=1,#collected do
+ local nc = collected and #collected or 0
+ local n = 0
+ if nc > 0 then
+ for c=1,nc do
n = n + tonumber(collected[c].dt[1] or 0)
end
- texwrite(n)
end
+ contextsprint(ctxcatcodes,n)
end
local function concatrange(collected,start,stop,separator,lastseparator,textonly) -- test this on mml
if collected then
local nofcollected = #collected
- local separator = separator or ""
- local lastseparator = lastseparator or separator or ""
- start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and nofcollected) or tonumber(stop) or nofcollected
- if stop < 0 then stop = nofcollected + stop end -- -1 == last-1
- for i=start,stop do
- if textonly then
- xmlcprint(collected[i])
- else
- xmlsprint(collected[i])
- end
- if i == nofcollected then
- -- nothing
- elseif i == nofcollected-1 and lastseparator ~= "" then
- texsprint(ctxcatcodes,lastseparator)
- elseif separator ~= "" then
- texsprint(ctxcatcodes,separator)
+ if nofcollected > 0 then
+ local separator = separator or ""
+ local lastseparator = lastseparator or separator or ""
+ start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and nofcollected) or tonumber(stop) or nofcollected
+ if stop < 0 then stop = nofcollected + stop end -- -1 == last-1
+ for i=start,stop do
+ if textonly then
+ xmlcprint(collected[i])
+ else
+ xmlsprint(collected[i])
+ end
+ if i == nofcollected then
+ -- nothing
+ elseif i == nofcollected-1 and lastseparator ~= "" then
+ contextsprint(ctxcatcodes,lastseparator)
+ elseif separator ~= "" then
+ contextsprint(ctxcatcodes,separator)
+ end
end
end
end
@@ -1090,37 +1271,44 @@ finalizers.default = all -- !!
local concat = table.concat
-function finalizers.tag(collected)
+function finalizers.tag(collected,n)
if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- texsprint(c.tg)
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ local c
+ if n == 0 then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if c then
+ contextsprint(ctxcatcodes,c.tg)
+ end
end
end
end
-function finalizers.name(collected)
+function finalizers.name(collected,n)
if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- texsprint(c.tg)
+ local nc = #collected
+ if nc > 0 then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
else
- texsprint(c.ns,":",c.tg)
+ c = collected[nc-n+1]
+ end
+ if c then
+ if c.ns == "" then
+ contextsprint(ctxcatcodes,c.tg)
+ else
+ contextsprint(ctxcatcodes,c.ns,":",c.tg)
+ end
end
end
end
@@ -1128,13 +1316,16 @@ end
function finalizers.tags(collected,nonamespace)
if collected then
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- if nonamespace or ns == "" then
- texsprint(tg)
- else
- texsprint(ns,":",tg)
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ if nonamespace or ns == "" then
+ contextsprint(ctxcatcodes,tg)
+ else
+ contextsprint(ctxcatcodes,ns,":",tg)
+ end
end
end
end
@@ -1145,14 +1336,17 @@ end
local function verbatim(id,before,after)
local root = getid(id)
if root then
- if before then texsprint(ctxcatcodes,before,"[",root.tg or "?","]") end
+ if before then contextsprint(ctxcatcodes,before,"[",root.tg or "?","]") end
lxml.toverbatim(xmltostring(root.dt))
- if after then texsprint(ctxcatcodes,after) end
+--~ lxml.toverbatim(xml.totext(root.dt))
+ if after then contextsprint(ctxcatcodes,after) end
end
end
+
function lxml.inlineverbatim(id)
verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
end
+
function lxml.displayverbatim(id)
verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim")
end
@@ -1196,27 +1390,40 @@ end
function lxml.raw(id,pattern) -- the content, untouched by commands
local collected = (pattern and xmlapplylpath(getid(id),pattern)) or getid(id)
- if collected then
- texsprint(xmltostring(collected[1].dt))
+ if collected and #collected > 0 then
+ contextsprint(notcatcodes,xmltostring(collected[1].dt))
end
end
function lxml.context(id,pattern) -- the content, untouched by commands
if not pattern then
local collected = getid(id)
- -- texsprint(ctxcatcodes,collected.dt[1])
ctx_text(collected.dt[1])
else
local collected = xmlapplylpath(getid(id),pattern) or getid(id)
if collected and #collected > 0 then
- texsprint(ctxcatcodes,collected[1].dt)
+ contextsprint(ctxcatcodes,collected[1].dt)
+ end
+ end
+end
+
+function lxml.context(id,pattern) -- the content, untouched by commands
+ if pattern then
+ local collected = xmlapplylpath(getid(id),pattern) or getid(id)
+ if collected and #collected > 0 then
+ contextsprint(ctxcatcodes,collected[1].dt)
+ end
+ else
+ local collected = getid(id)
+ if collected and #collected > 0 then
+ ctx_text(collected.dt[1])
end
end
end
function lxml.text(id,pattern)
local collected = (pattern and xmlapplylpath(getid(id),pattern)) or getid(id)
- if collected then
+ if collected and #collected > 0 then
text(collected)
end
end
@@ -1224,17 +1431,11 @@ end
lxml.content = text
function lxml.position(id,pattern,n)
- local collected = xmlapplylpath(getid(id),pattern)
- if collected then
- position(collected,n)
- end
+ position(xmlapplylpath(getid(id),pattern),n)
end
function lxml.chainattribute(id,pattern,a,default)
- local collected = xmlapplylpath(getid(id),pattern)
- if collected then
- chainattribute(collected,a,default)
- end
+ chainattribute(xmlapplylpath(getid(id),pattern),a,default)
end
function lxml.concatrange(id,pattern,start,stop,separator,lastseparator,textonly) -- test this on mml
@@ -1253,7 +1454,7 @@ lxml.index = lxml.position
function lxml.pos(id)
local root = getid(id)
- texwrite((root and root.ni) or 0)
+ contextsprint(ctxcatcodes,(root and root.ni) or 0)
end
function lxml.att(id,a,default)
@@ -1262,10 +1463,10 @@ function lxml.att(id,a,default)
local at = root.at
local str = (at and at[a]) or default
if str and str ~= "" then
- texsprint(notcatcodes,str)
+ contextsprint(notcatcodes,str)
end
elseif default then
- texsprint(notcatcodes,default)
+ contextsprint(notcatcodes,default)
end
end
@@ -1273,23 +1474,23 @@ function lxml.name(id) -- or remapped name? -> lxml.info, combine
local r = getid(id)
local ns = r.rn or r.ns or ""
if ns ~= "" then
- texsprint(ns,":",r.tg)
+ contextsprint(ctxcatcodes,ns,":",r.tg)
else
- texsprint(r.tg)
+ contextsprint(ctxcatcodes,r.tg)
end
end
function lxml.match(id) -- or remapped name? -> lxml.info, combine
- texsprint(getid(id).mi or 0)
+ contextsprint(ctxcatcodes,getid(id).mi or 0)
end
function lxml.tag(id) -- tag vs name -> also in l-xml tag->name
- texsprint(getid(id).tg or "")
+ contextsprint(ctxcatcodes,getid(id).tg or "")
end
function lxml.namespace(id) -- or remapped name?
local root = getid(id)
- texsprint(root.rn or root.ns or "")
+ contextsprint(ctxcatcodes,root.rn or root.ns or "")
end
function lxml.flush(id)
@@ -1318,15 +1519,18 @@ function lxml.command(id,pattern,cmd)
local i, p = getid(id,true)
local collected = xmlapplylpath(getid(i),pattern)
if collected then
- local rootname = p or i.name
- for c=1,#collected do
- local e = collected[c]
- local ix = e.ix
- if not ix then
- addindex(rootname,false,true)
- ix = e.ix
+ local nc = #collected
+ if nc > 0 then
+ local rootname = p or i.name
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
end
- texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
end
end
end
@@ -1434,8 +1638,11 @@ lxml.get_id = getid lxml.obsolete.get_id = getid
function xml.finalizers.tex.lettered(collected)
if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,lettered(collected[1].dt[1]))
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,lettered(collected[c].dt[1]))
+ end
end
end
end
@@ -1443,7 +1650,7 @@ end
--~ function xml.finalizers.tex.apply(collected,what) -- to be tested
--~ if collected then
--~ for c=1,#collected do
---~ texsprint(ctxcatcodes,what(collected[1].dt[1]))
+--~ contextsprint(ctxcatcodes,what(collected[c].dt[1]))
--~ end
--~ end
--~ end