diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/node-ser.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/node-ser.lua | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua new file mode 100644 index 00000000000..2ad1242c533 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua @@ -0,0 +1,342 @@ +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" +} + +-- beware, some field names will change in a next releases +-- of luatex; this is pretty old code that needs an overhaul + +local type = type +local concat, tohash, sortedkeys, printtable = table.concat, table.tohash, table.sortedkeys, table.print +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 traverse = nodes.traverse +local is_node = nodes.is_node + +local nodecodes = nodes.nodecodes +local subtcodes = nodes.codes +local noadcodes = nodes.noadcodes +local getfields = nodes.fields + +local tonode = nodes.tonode + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist + +----- utfchar = utf.char +local f_char = formatters["%U"] +----- fontchars = { } table.setmetatableindex(fontchars,function(t,k) fontchars = fonts.hashes.characters return fontchars[k] end) + +----- f_char = utilities.strings.chkuni -- formatters["%!chkuni!"] + +local expand = allocate ( tohash { + -- text: + "list", -- list_ptr & ins_ptr & adjust_ptr + "pre", -- + "post", -- + "top_skip", -- + "attr", -- + "replace", -- nobreak + "components", -- lig_ptr + "box_left", -- + "box_right", -- + "glyph", -- margin_char + "leader", -- leader_ptr + "action", -- action_ptr + "value", -- user_defined nodes with subtype 'a' en 'n' + "head", + -- math: + "nucleus", + "sup", + "sub", + "list", + "num", + "denom", + "left", + "right", + "display", + "text", + "script", + "scriptscript", + "delim", + "degree", + "accent", + "bot_accent", +} ) + +-- page_insert: "height", "last_ins_ptr", "best_ins_ptr" +-- split_insert: "height", "last_ins_ptr", "best_ins_ptr", "broken_ptr", "broken_ins" + +local ignore = allocate ( tohash { + "page_insert", + "split_insert", + "ref_count", +} ) + +local dimension = allocate ( tohash { + "width", "height", "depth", "shift", + "stretch", "shrink", + "xoffset", "yoffset", + "surround", + "kern", + "box_left_width", "box_right_width" +} ) + +-- flat: don't use next, but indexes +-- verbose: also add type +-- can be sped up + +nodes.dimensionfields = dimension +nodes.listablefields = expand +nodes.ignorablefields = ignore + +-- not ok yet: + +local function astable(n,sparse) -- not yet ok, might get obsolete anyway + n = tonode(n) + local f, t = getfields(n), { } + for i=1,#f do + local v = f[i] + local d = n[v] + if d then + if ignore[v] or v == "id" then + -- skip + elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" or type(n[v]) ~= "table" + t[v] = "pointer to list" + elseif sparse then + if (type(d) == "number" and d ~= 0) or (type(d) == "string" and d ~= "") then + t[v] = d + end + else + t[v] = d + end + end + end + t.type = nodecodes[n.id] + return t +end + +nodes.astable = astable + +setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end) + +-- under construction: + +local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true + local function to_table(n,flat,verbose,noattributes) -- no need to pass + local f = getfields(n) + local tt = { } + for k=1,#f do + local v = f[k] + local nv = v and n[v] + if nv then + if ignore[v] then + -- skip + elseif noattributes and v == "attr" then + -- skip + elseif expand[v] then + if type(nv) == "number" or type(nv) == "string" then + tt[v] = nv + else + tt[v] = totable(nv,flat,verbose,noattributes) + end + elseif type(nv) == "table" then + tt[v] = nv -- totable(nv,flat,verbose) -- data + else + tt[v] = nv + end + end + end + if verbose then + local subtype = tt.subtype + local id = tt.id + local nodename = nodecodes[id] + tt.id = nodename + local subtypes = subtcodes[nodename] + if subtypes then + tt.subtype = subtypes[subtype] + elseif subtype == 0 then + tt.subtype = nil + else + -- we need a table + end + if tt.char then + tt.char = f_char(tt.char) + end + if tt.small_char then + tt.small_char = f_char(tt.small_char) + end + if tt.large_char then + tt.large_char = f_char(tt.large_char) + end + end + return tt + end + if n then + if flat then + local t, tn = { }, 0 + while n do + tn = tn + 1 + local nt = to_table(n,flat,verbose,noattributes) + t[tn] = nt + nt.next = nil + nt.prev = nil + n = n.next + end + return t + else + local t = to_table(n,flat,verbose,noattributes) + local n = n.next + if n then + t.next = totable(n,flat,verbose,noattributes) + 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 + +-- not ok yet; this will become a module + +-- todo: adapt to nodecodes etc .. use formatters + +local function serialize(root,name,handle,depth,m,noattributes) + handle = handle or print + if depth then + depth = depth .. " " + handle(format("%s%s={",depth,key(name))) + else + depth = "" + local tname = type(name) + if tname == "string" then + if name == "return" then + handle("return {") + else + handle(name .. "={") + end + elseif tname == "number" then + handle("[" .. name .. "]={") + else + handle("t={") + end + end + if root then + local fld + if root.id then + fld = getfields(root) -- we can cache these (todo) + else + fld = sortedkeys(root) + end + if type(root) == 'table' and root['type'] then -- userdata or table + handle(format("%s type=%q,",depth,root['type'])) + end + for f=1,#fld do + local k = fld[f] + if k == "ref_count" then + -- skip + elseif noattributes and k == "attr" then + -- skip + elseif k == "id" then + local v = root[k] + handle(format("%s id=%s,",depth,nodecodes[v] or noadcodes[v] or v)) + elseif k then + local v = root[k] + local t = type(v) + if t == "number" then + if v == 0 then + -- skip + else + handle(format("%s %s=%s,",depth,key(k),v)) + end + elseif t == "string" then + if v == "" then + -- skip + else + handle(format("%s %s=%q,",depth,key(k),v)) + end + elseif t == "boolean" then + handle(format("%s %s=%q,",depth,key(k),tostring(v))) + elseif v then -- userdata or table + serialize(v,k,handle,depth,m+1,noattributes) + end + end + end + if root['next'] then -- userdata or table + serialize(root['next'],'next',handle,depth,m+1,noattributes) + end + end + if m and m > 0 then + handle(format("%s},",depth)) + else + handle(format("%s}",depth)) + end +end + +function nodes.serialize(root,name,noattributes) + local t, n = { }, 0 + local function flush(s) + n = n + 1 + t[n] = s + end + serialize(tonode(root),name,flush,nil,0,noattributes) + return concat(t,"\n") +end + +function nodes.serializebox(n,flat,verbose,name) + return nodes.serialize(nodes.totable(tex.box[n],flat,verbose),name) +end + +function nodes.visualizebox(...) -- to be checked .. will move to module anyway + context.starttyping() + context.pushcatcodes("verbatim") + context(nodes.serializebox(...)) + context.stoptyping() + context.popcatcodes() +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 |