summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkxl/node-ser.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/node-ser.lmt')
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/node-ser.lmt284
1 files changed, 284 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/node-ser.lmt b/Master/texmf-dist/tex/context/base/mkxl/node-ser.lmt
new file mode 100644
index 00000000000..8fcbb31e473
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/node-ser.lmt
@@ -0,0 +1,284 @@
+if not modules then modules = { } end modules ['node-ser'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, tostring = type, tostring
+local concat, tohash, sortedkeys, sortedhash, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.sortedhash, table.print, table.serialize
+local formatters, format, rep = string.formatters, string.format, string.rep
+
+local allocate = utilities.storage.allocate
+
+local context = context
+local nodes = nodes
+local node = node
+
+local getfields = node.fields
+
+local is_node = nodes.is_node
+
+local nodecodes = nodes.nodecodes
+local subtypes = nodes.subtypes
+
+local tonode = nodes.tonode
+local tonut = nodes.tonut
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local f_char = formatters["%U"]
+local f_attr = formatters["<attribute : %i>"]
+local f_recurse = formatters["<recursive : %i>"]
+
+-- flat : don't use next, but indexes
+-- verbose : also add type
+
+local canbezero = {
+ integer = true,
+ dimension = true,
+ number = true,
+}
+
+local canbelist = {
+ attribute = "<attribute>",
+ node = "<node>",
+ token = "<token>",
+ attribute_list = "<attributes>",
+ node_list = "<nodes>",
+ token_list = "<tokens>",
+}
+
+local canbeignored = {
+ prev = "<node>"
+}
+
+local canbechar = {
+ char = true,
+ small_char = true,
+ large_char = true,
+}
+
+local fieldtypes = table.setmetatableindex(function(t,k)
+ local v = getfields(k,true) or false
+ t[k] = v
+ return v
+end)
+
+nodes.fieldtypes = fieldtypes
+
+local function astable(n)
+ n = tonode(n)
+ if n then
+ local fields = fieldtypes[n.id]
+ if fields then
+ local result = { }
+ for field, fieldtype in sortedhash(fields) do
+ local value = n[field]
+ if value then
+ if canbeignored[field] then
+ value = nil
+ elseif canbezero[fieldtype] and value == 0 then
+ value = nil
+ elseif canbelist[fieldtype] then
+ value = canbelist[fieldtype]
+ end
+ if value then
+ result[field] = value
+ end
+ end
+ end
+ local id = n.id
+ if id then
+ id = nodecodes[id]
+ result.id = id
+ local subtype = n.subtype
+ if subtype then
+ local subtypes = subtypes[id]
+ if subtypes then
+ result.subtype = subtypes[subtype]
+ end
+ end
+ end
+ return result
+ end
+ end
+end
+
+nodes.astable = astable
+
+setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end)
+
+local function to_table(n,flat,verbose,noattributes,done)
+ local d = tonut(n)
+ if done[d] then
+ return f_recurse(d)
+ else
+ done[d] = true
+ local fields = fieldtypes[n.id]
+ if fields then
+ local result = { }
+ for field, fieldtype in sortedhash(fields) do
+ local value = n[field]
+ if value then
+ if fieldtype == "attribute_list" or fieldtype == "attribute" then
+ if noattributes then
+ result[value] = canbeignored[value]
+ else
+ result[value] = to_table(value,flat,verbose,noattributes,done)
+ end
+ elseif canbeignored[field] then
+ result[value] = canbeignored[value]
+ elseif not verbose and canbezero[fieldtype] and value == 0 then
+ value = nil
+ elseif canbelist[fieldtype] then
+ if flat then
+ result[value] = canbelist[value]
+ else
+ result[value] = to_table(value,flat,verbose,noattributes,done)
+ end
+ end
+ if value then
+ result[field] = value
+ end
+ end
+ end
+ if verbose then
+ local id = result.id
+ if id then
+ id = nodecodes[id]
+ result.id = id
+ local subtype = result.subtype
+ if subtype then
+ local subtypes = subtypes[id]
+ if subtypes then
+ result.subtype = subtypes[subtype]
+ end
+ end
+ end
+ for k, v in next, canbechar do
+ local v = result[k]
+ if v then
+ result[k] = f_char(v)
+ end
+ end
+ end
+ return result
+ end
+ end
+end
+
+local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true
+ if n then
+ local d = { }
+ if flat then
+ local t, tn = { }, 0
+ while n do
+ tn = tn + 1
+ local nt = to_table(n,flat,verbose,noattributes,d)
+ t[tn] = nt
+ nt.next = nil
+ nt.prev = nil
+ n = n.next
+ end
+ done = nil
+ return t
+ else
+ local t = to_table(n,flat,verbose,noattributes,d)
+ local n = n.next
+ if n then
+ t.next = totable(n,flat,verbose,noattributes,d)
+ end
+ return t
+ end
+ else
+ return { }
+ end
+end
+
+nodes.totable = function(n,...) return totable(tonode(n),...) end
+nodes.totree = function(n) return totable(tonode(n),true,true,true) end -- no attributes, todo: attributes in k,v list
+
+local function key(k)
+ return ((type(k) == "number") and "["..k.."]") or k
+end
+
+function nodes.serialize(root,flat,verbose,noattributes,name)
+ return serialize(totable(tonode(root),flat,verbose,noattributes),name)
+end
+
+function nodes.serializebox(n,flat,verbose,noattributes,name)
+ return serialize(totable(tex.box[n],flat,verbose,noattributes),name)
+end
+
+function nodes.visualizebox(n,flat,verbose,noattributes,name)
+ context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name)
+end
+
+function nodes.list(head,n) -- name might change to nodes.type -- to be checked .. will move to module anyway
+ head = tonode(head)
+ if not n then
+ context.starttyping(true)
+ end
+ while head do
+ local id = head.id
+ context(rep(" ",n or 0) .. tostring(head) .. "\n")
+ if id == hlist_code or id == vlist_code then
+ nodes.list(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+ if not n then
+ context.stoptyping(true)
+ end
+end
+
+function nodes.print(head,n)
+ head = tonode(head)
+ while head do
+ local id = head.id
+ logs.writer(string.formatters["%w%S"],n or 0,head)
+ if id == hlist_code or id == vlist_code then
+ nodes.print(head.list,(n or 0)+1)
+ end
+ head = head.next
+ end
+end
+
+-- quick hack, nicer is to have a proper expand per node type already prepared
+
+local function apply(n,action)
+ while n do
+ action(n)
+ local id = n.id
+ if id == hlist_code or id == vlist_code then
+ apply(n.list,action)
+ end
+ n = n.next
+ end
+end
+
+nodes.apply = apply
+
+local nuts = nodes.nuts
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getnext = nuts.getnext
+
+local function apply(n,action)
+ while n do
+ action(n)
+ local id = getid(n)
+ if id == hlist_code or id == vlist_code then
+ local list = getlist(n,action)
+ if list then
+ apply(list,action)
+ end
+ end
+ n = getnext(n)
+ end
+end
+
+nuts.apply = apply