1if not modules then modules = { } end modules ['node-ser'] = {
2 version = 1.001,
3 comment = "companion to node-ini.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12local type, tostring = type, tostring
13local concat, tohash, sortedkeys, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.print, table.serialize
14local formatters, format, rep = string.formatters, string.format, string.rep
15
16local allocate = utilities.storage.allocate
17
18local context = context
19local nodes = nodes
20
21local isnode = nodes.isnode
22local nodecodes = nodes.nodecodes
23local subtcodes = nodes.codes
24local getfields = nodes.fields
25local tonode = nodes.tonode
26local tonut = nodes.tonut
27
28local hlist_code = nodecodes.hlist
29local vlist_code = nodecodes.vlist
30
31
32local f_char = formatters["%U"]
33local f_attr = formatters["<%i>"]
34
35
36
37
38
39
40local expand = allocate ( tohash {
41
42 "list",
43 "pre",
44 "post",
45 "replace",
46 "top_skip",
47 "attr",
48 "components",
49 "box_left",
50 "box_right",
51 "glyph",
52 "leader",
53 "action",
54 "value",
55 "head",
56
57 "nucleus",
58 "sup",
59 "sub",
60 "list",
61 "num",
62 "denom",
63 "left",
64 "right",
65 "display",
66 "text",
67 "script",
68 "scriptscript",
69 "delim",
70 "degree",
71 "accent",
72 "bot_accent",
73} )
74
75
76
77
78local ignore = allocate ( tohash {
79 "page_insert",
80 "split_insert",
81 "ref_count",
82} )
83
84local dimension = allocate ( tohash {
85 "width", "height", "depth", "shift",
86 "stretch", "shrink",
87 "xoffset", "yoffset",
88 "surround",
89 "kern",
90 "box_left_width", "box_right_width"
91} )
92
93
94
95
96
97nodes.dimensionfields = dimension
98nodes.listablefields = expand
99nodes.ignorablefields = ignore
100
101
102
103local function astable(n,sparse)
104 n = tonode(n)
105 local f = getfields(n)
106 local t = { }
107 for i=1,#f do
108 local v = f[i]
109 local d = n[v]
110 if d then
111 if ignore[v] or v == "id" then
112
113 elseif expand[v] then
114 t[v] = "<list>"
115 elseif sparse then
116 if (type(d) == "number" and d ~= 0) or (type(d) == "string" and d ~= "") then
117 t[v] = d
118 end
119 else
120 t[v] = d
121 end
122 end
123 end
124 t.type = nodecodes[n.id]
125 return t
126end
127
128nodes.astable = astable
129
130setinspector("node",function(v) if isnode(v) then printtable(astable(v),tostring(v)) return true end end)
131
132
133
134local function totable(n,flat,verbose,noattributes)
135 local function to_table(n,flat,verbose,noattributes)
136 local f = getfields(n.id)
137 local tt = { }
138 for k=1,#f do
139 local v = f[k]
140 local nv = v and n[v]
141 if nv then
142 if ignore[v] then
143
144 elseif noattributes and v == "attr" then
145 tt[v] = f_attr(tonut(nv))
146
147 elseif v == "prev" then
148 tt[v] = "<node>"
149 elseif expand[v] then
150 if type(nv) == "number" or type(nv) == "string" then
151 tt[v] = nv
152 else
153 tt[v] = totable(nv,flat,verbose,noattributes)
154 end
155 elseif type(nv) == "table" then
156 tt[v] = nv
157 else
158 tt[v] = nv
159 end
160 end
161 end
162 if verbose then
163 local subtype = tt.subtype
164 local id = tt.id
165 local nodename = nodecodes[id]
166 tt.id = nodename
167 local subtypes = subtcodes[nodename]
168 if subtypes then
169 tt.subtype = subtypes[subtype]
170 elseif subtype == 0 then
171 tt.subtype = nil
172 else
173
174 end
175 if tt.char then
176 tt.char = f_char(tt.char)
177 end
178 if tt.small_char then
179 tt.small_char = f_char(tt.small_char)
180 end
181 if tt.large_char then
182 tt.large_char = f_char(tt.large_char)
183 end
184 end
185 return tt
186 end
187 if n then
188 if flat then
189 local t, tn = { }, 0
190 while n do
191 tn = tn + 1
192 local nt = to_table(n,flat,verbose,noattributes)
193 t[tn] = nt
194 nt.next = nil
195 nt.prev = nil
196 n = n.next
197 end
198 return t
199 else
200 local t = to_table(n,flat,verbose,noattributes)
201 local n = n.next
202 if n then
203 t.next = totable(n,flat,verbose,noattributes)
204 end
205 return t
206 end
207 else
208 return { }
209 end
210end
211
212nodes.totable = function(n,...) return totable(tonode(n),...) end
213nodes.totree = function(n) return totable(tonode(n),true,true,true) end
214
215local function key(k)
216 return ((type(k) == "number") and "["..k.."]") or k
217end
218
219function nodes.serialize(root,flat,verbose,noattributes,name)
220 return serialize(totable(tonode(root),flat,verbose,noattributes),name)
221end
222
223function nodes.serializebox(n,flat,verbose,noattributes,name)
224 return serialize(totable(tex.box[n],flat,verbose,noattributes),name)
225end
226
227function nodes.visualizebox(n,flat,verbose,noattributes,name)
228 context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name)
229end
230
231function nodes.list(head,n)
232 head = tonode(head)
233 if not n then
234 context.starttyping(true)
235 end
236 while head do
237 local id = head.id
238 context(rep(" ",n or 0) .. tostring(head) .. "\n")
239 if id == hlist_code or id == vlist_code then
240 nodes.list(head.list,(n or 0)+1)
241 end
242 head = head.next
243 end
244 if not n then
245 context.stoptyping(true)
246 end
247end
248
249function nodes.print(head,n)
250 head = tonode(head)
251 while head do
252 local id = head.id
253 logs.writer(string.formatters["%w%S"],n or 0,head)
254 if id == hlist_code or id == vlist_code then
255 nodes.print(head.list,(n or 0)+1)
256 end
257 head = head.next
258 end
259end
260
261
262
263
264local function apply(n,action)
265 while n do
266 action(n)
267 local id = n.id
268 if id == hlist_code or id == vlist_code then
269 apply(n.list,action)
270 end
271 n = n.next
272 end
273end
274
275nodes.apply = apply
276
277local nuts = nodes.nuts
278local getid = nuts.getid
279local getlist = nuts.getlist
280local getnext = nuts.getnext
281
282local function apply(n,action)
283 while n do
284 action(n)
285 local id = getid(n)
286 if id == hlist_code or id == vlist_code then
287 local list = getlist(n,action)
288 if list then
289 apply(list,action)
290 end
291 end
292 n = getnext(n)
293 end
294end
295
296nuts.apply = apply
297 |