summaryrefslogtreecommitdiff
path: root/tex/context/base/lxml-ini.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/lxml-ini.lua')
-rw-r--r--tex/context/base/lxml-ini.lua254
1 files changed, 228 insertions, 26 deletions
diff --git a/tex/context/base/lxml-ini.lua b/tex/context/base/lxml-ini.lua
index 75ad74ab9..67e1bc75b 100644
--- a/tex/context/base/lxml-ini.lua
+++ b/tex/context/base/lxml-ini.lua
@@ -13,6 +13,121 @@ lxml = { }
lxml.loaded = { }
lxml.self = { }
+do
+
+ local crlf = lpeg.P("\r\n")
+ local cr = lpeg.P("\r")
+ local lf = lpeg.P("\n")
+ local space = lpeg.S(" \t\f\v")
+ local newline = crlf + cr + lf
+ local spacing = space^0 * newline * space^0
+ local content = lpeg.C((1-spacing)^1)
+ local verbose = lpeg.C((1-(space+newline))^1)
+
+ local capture = (
+ newline^2 * lpeg.Cc("") / tex.print +
+ newline * lpeg.Cc(" ") / tex.sprint +
+ content / tex.sprint
+ )^0
+
+ xml.specialhandler = { }
+
+ local function sprint(root)
+ if not root then
+ -- quit
+ elseif type(root) == 'string' then
+ lpeg.match(capture,root)
+ elseif next(root) then
+ xml.serialize(root,sprint,nil,nil,xml.specialhandler)
+ end
+ end
+
+ xml.sprint = sprint
+
+ function xml.tprint(root)
+ if type(root) == "table" then
+ for i=1,#root do
+ sprint(root[i])
+ end
+ elseif type(root) == "string" then
+ sprint(root)
+ end
+ end
+
+ -- lines (untested)
+
+ local buffer = { }
+
+ local capture = (
+ newline^2 / function() buffer[#buffer+1] = "" end +
+ newline / function() buffer[#buffer] = buffer[#buffer] .. " " end +
+ content / function(s) buffer[#buffer] = buffer[#buffer] .. s end
+ )^0
+
+ function lines(root)
+ if not root then
+ -- quit
+ elseif type(root) == 'string' then
+ lpeg.match(capture,root)
+ elseif next(root) then
+ xml.serialize(root, lines)
+ end
+ end
+
+ function xml.lines(root)
+ buffer = { "" }
+ lines(root)
+ return result
+ end
+
+ -- cdata
+
+ local linecommand = "\\obeyedline"
+ local spacecommand = "\\obeyedspace" -- "\\strut\\obeyedspace"
+ local beforecommand = ""
+ local aftercommand = ""
+
+ local capture = (
+ newline / function( ) tex.sprint(tex.texcatcodes,linecommand .. "{}") end +
+ verbose / function(s) tex.sprint(tex.vrbcatcodes,s) end +
+ space / function( ) tex.sprint(tex.texcatcodes,spacecommand .. "{}") end
+ )^0
+
+ function toverbatim(str)
+ if beforecommand then tex.sprint(tex.texcatcodes,beforecommand .. "{}") end
+ lpeg.match(capture,str)
+ if aftercommand then tex.sprint(tex.texcatcodes,aftercommand .. "{}") end
+ end
+
+ function lxml.set_verbatim(before,after,obeyedline,obeyedspace)
+ beforecommand, aftercommand, linecommand, spacecommand = before, after, obeyedline, obeyedspace
+ end
+
+ function lxml.set_cdata()
+ xml.specialhandler['@cd@'] = toverbatim
+ end
+
+ function lxml.reset_cdata()
+ xml.specialhandler['@cd@'] = nil
+ end
+
+ function lxml.verbatim(id,before,after)
+ local root = lxml.id(id)
+ if before then tex.sprint(tex.ctxcatcodes,string.format("%s[%s]",before,id.tg)) end
+ xml.serialize(root,toverbatim,nil,nil,nil,true)
+ if after then tex.sprint(tex.ctxcatcodes,after) end
+ end
+ function lxml.inlineverbatim(id)
+ lxml.verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
+ end
+ function lxml.displayverbatim(id)
+ lxml.verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim")
+ end
+
+end
+
+-- now comes the lxml one
+
function lxml.id(id)
return (type(id) == "table" and id) or lxml.loaded[id] or lxml.self[tonumber(id)]
end
@@ -51,11 +166,11 @@ function lxml.last(id,pattern)
end
function lxml.all(id,pattern)
- xml.tprint(xml.all(lxml.id(id),pattern))
+ xml.tprint(xml.collect(lxml.id(id),pattern))
end
function lxml.nonspace(id,pattern)
- xml.tprint(xml.all(lxml.id(id),pattern,true))
+ xml.tprint(xml.collect(lxml.id(id),pattern,true))
end
function lxml.strip(id,pattern)
@@ -63,7 +178,7 @@ function lxml.strip(id,pattern)
end
function lxml.text(id,pattern)
- xml.tprint(xml.all_texts(lxml.id(id),pattern) or {})
+ xml.tprint(xml.collect_texts(lxml.id(id),pattern) or {})
end
function lxml.content(id,pattern)
@@ -90,7 +205,7 @@ end
function lxml.count(id,pattern)
tex.sprint(xml.count(lxml.id(id),pattern) or 0)
end
-function lxml.name(id)
+function lxml.name(id) -- or remapped name?
local r = lxml.id(id)
if r.ns then
tex.sprint(r.ns .. ":" .. r.tg)
@@ -101,23 +216,40 @@ end
function lxml.tag(id)
tex.sprint(lxml.id(id).tg or "")
end
-function lxml.namespace(id)
+function lxml.namespace(id) -- or remapped name?
tex.sprint(lxml.id(id).ns or "")
end
-function lxml.concat(id,what,separator)
- tex.sprint(table.concat(xml.all_texts(lxml.id(id),what,true),separator or ""))
+--~ function lxml.concat(id,what,separator,lastseparator)
+--~ tex.sprint(table.concat(xml.collect_texts(lxml.id(id),what,true),separator or ""))
+--~ end
+
+function lxml.concat(id,what,separator,lastseparator)
+ local t = xml.collect_texts(lxml.id(id),what,true)
+ local separator = separator or ""
+ local lastseparator = lastseparator or separator or ""
+ for i=1,#t do
+ tex.sprint(t[i])
+ if i == #t then
+ -- nothing
+ elseif i == #t-1 and lastseparator ~= "" then
+ tex.sprint(tex.ctxcatcodes,lastseparator)
+ elseif separator ~= "" then
+ tex.sprint(tex.ctxcatcodes,separator)
+ end
+ end
end
function xml.command(root) -- todo: free self after usage, so maybe hash after all
- xml.sflush()
+ -- no longer needed: xml.sflush()
if type(root.command) == "string" then
local n = #lxml.self + 1
lxml.self[n] = root
if xml.trace_print then
texio.write_nl(string.format("tex.sprint: (((%s:%s)))",n,root.command))
end
- tex.sprint(tex.ctxcatcodes,string.format("\\xmlsetup{%s}{%s}",n,root.command))
+ -- problems with empty elements
+ tex.sprint(tex.ctxcatcodes,string.format("\\xmlsetup{%s}{%s}",n,root.command)) -- no sprint, else spaces go wrong
else
root.command(root)
end
@@ -129,19 +261,25 @@ function lxml.setaction(id,pattern,action)
end
end
+lxml.trace_setups = false
+
function lxml.setsetup(id,pattern,setup)
if not setup or setup == "" or setup == "*" then
for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
- local dtdk = dt[dk]
- if dtdk.ns == "" then
- dtdk.command = dtdk.tg
+ local dtdk = dt and dt[dk] or rt
+ local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg
+ if ns == "" then
+ dtdk.command = tg
else
- dtdk.command = dtdk.ns .. ":" .. dtdk.tg
+ dtdk.command = ns .. ":" .. tg
+ end
+ if lxml.trace_setups then
+ texio.write_nl(string.format("xml setup: namespace=%s, tag=%s, setup=%s",ns, tg, dtdk.command))
end
end
else
for rt, dt, dk in xml.elements(lxml.id(id),pattern) do
- dt[dk].command = setup
+ ((dt and dt[dk]) or rt).command = setup
end
end
end
@@ -155,7 +293,7 @@ function lxml.idx(id,pattern,i)
r.patterns = rp
end
if not rp[pattern] then
- rp[pattern] = xml.all_elements(r,pattern) -- dd, rr
+ rp[pattern] = xml.collect_elements(r,pattern) -- dd, rr
end
local rpi = rp[pattern] and rp[pattern][i]
if rpi then
@@ -166,7 +304,7 @@ end
do
- local traverse = xml.traverse_tree
+ local traverse = xml.traverse
local lpath = xml.lpath
function xml.filters.command(root,pattern,command) -- met zonder ''
@@ -187,9 +325,28 @@ end
do
+ --~ <?xml version="1.0" standalone="yes"?>
+ --~ <!-- demo.cdx -->
+ --~ <directives>
+ --~ <!--
+ --~ <directive attribute='id' value="100" setup="cdx:100"/>
+ --~ <directive attribute='id' value="101" setup="cdx:101"/>
+ --~ -->
+ --~ <!--
+ --~ <directive attribute='cdx' value="colors" element="cals:table" setup="cdx:cals:table:colors"/>
+ --~ <directive attribute='cdx' value="vertical" element="cals:table" setup="cdx:cals:table:vertical"/>
+ --~ <directive attribute='cdx' value="noframe" element="cals:table" setup="cdx:cals:table:noframe"/>
+ --~ -->
+ --~ <directive attribute='cdx' value="*" element="cals:table" setup="cdx:cals:table:*"/>
+ --~ </directives>
+
lxml.directives = { }
- local data = { }
+ local data = {
+ setup = { },
+ before = { },
+ after = { }
+ }
function lxml.directives.load(filename)
if texmf then
@@ -199,23 +356,63 @@ do
end
end
local root = xml.load(filename)
+ local format = string.format
for r, d, k in xml.elements(root,"directive") do
local dk = d[k]
local at = dk.at
- local id, setup = at.id, at.setup
- if id and setup then
- data[id] = setup
+ local attribute, value, element = at.attribute or "", at.value or "", at.element or '*'
+ local setup, before, after = at.setup or "", at.before or "", at.after or ""
+ if attribute ~= "" and value ~= "" then
+ local key = format("%s::%s::%s",element,attribute,value)
+ local t = data[key] or { }
+ if setup ~= "" then t.setup = setup end
+ if before ~= "" then t.before = before end
+ if after ~= "" then t.after = after end
+ data[key] = t
end
end
end
- function lxml.directives.setups(root)
+ function lxml.directives.setup(root,attribute,element)
+ lxml.directives.handle_setup('setup',root,attribute,element)
+ end
+ function lxml.directives.before(root,attribute,element)
+ lxml.directives.handle_setup('before',root,attribute,element)
+ end
+ function lxml.directives.after(root,attribute,element)
+ lxml.directives.handle_setup('after',root,attribute,element)
+ end
+
+ function lxml.directives.handle_setup(category,root,attribute,element)
root = lxml.id(root)
- local id = root.at.id
- if id then
- local setup = data[id]
- if setup then
- tex.sprint(tex.ctxcatcodes,string.format("\\directsetup{%s}",setup))
+ attribute = attribute
+ if attribute then
+ local value = root.at[attribute]
+ if value then
+ if not element then
+ local ns, tg = root.rn or root.ns, root.tg
+ if ns == "" then
+ element = tg
+ else
+ element = ns .. ':' .. tg
+ end
+ end
+ local format = string.format
+ local setup = data[format("%s::%s::%s",element,attribute,value)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ tex.sprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup))
+ else
+ setup = data[format("%s::%s::*",element,attribute)]
+ if setup then
+ setup = setup[category]
+ end
+ if setup then
+ tex.sprint(tex.ctxcatcodes,format("\\directsetup{%s}",setup:gsub('%*',value)))
+ end
+ end
end
end
end
@@ -232,3 +429,8 @@ function lxml.loadbuffer(id,name)
input.stop_timing(lxml)
return lxml.loaded[id], name or id
end
+
+-- for the moment here:
+
+lxml.set_verbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace")
+lxml.set_cdata()